about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2023-11-07 05:22:20 +0000
committerMichael Goulet <michael@errs.io>2023-11-07 05:23:09 +0000
commit0add056dee57a0b56f3316596dcecb1bbde17a08 (patch)
tree571d5580fb5612d4927025c52588e94c9cf5eb51
parent88a37acb26a58472a124e38a8b63d27c204ca5a8 (diff)
downloadrust-0add056dee57a0b56f3316596dcecb1bbde17a08.tar.gz
rust-0add056dee57a0b56f3316596dcecb1bbde17a08.zip
Rework print_disambiguation_help
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs126
-rw-r--r--tests/ui/methods/disambiguate-multiple-blanket-impl.stderr12
-rw-r--r--tests/ui/methods/disambiguate-multiple-impl.stderr8
-rw-r--r--tests/ui/methods/disambiguate-multiple-trait-2.stderr28
-rw-r--r--tests/ui/methods/disambiguate-multiple-trait.stderr12
-rw-r--r--tests/ui/methods/method-ambig-two-traits-from-bounds.stderr8
-rw-r--r--tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr4
-rw-r--r--tests/ui/span/issue-37767.stderr8
8 files changed, 93 insertions, 113 deletions
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 426cec11d0e..b1a2df8ace4 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -34,7 +34,7 @@ use rustc_middle::ty::{self, GenericArgKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::def_id::DefIdSet;
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
-use rustc_span::{edit_distance, source_map, ExpnKind, FileName, MacroKind, Span};
+use rustc_span::{edit_distance, ExpnKind, FileName, MacroKind, Span};
 use rustc_trait_selection::infer::InferCtxtExt;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedNote;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::TypeErrCtxtExt as _;
@@ -1320,39 +1320,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     if let Some(sugg_span) = sugg_span
                         && let Some(trait_ref) = self.tcx.impl_trait_ref(impl_did)
-                    {
-                        let path = self.tcx.def_path_str(trait_ref.skip_binder().def_id);
-
-                        let ty = match item.kind {
-                            ty::AssocKind::Const | ty::AssocKind::Type => impl_ty,
-                            ty::AssocKind::Fn => self
-                                .tcx
-                                .fn_sig(item.def_id)
-                                .instantiate_identity()
-                                .inputs()
-                                .skip_binder()
-                                .get(0)
-                                .filter(|ty| ty.is_ref() && !rcvr_ty.is_ref())
-                                .copied()
-                                .unwrap_or(rcvr_ty),
-                        };
-                        if let Some(sugg) = print_disambiguation_help(
-                            item_name,
-                            args,
-                            self_source,
+                        && let Some(sugg) = print_disambiguation_help(
+                            self.tcx,
                             err,
-                            path,
-                            ty,
-                            Some(impl_ty),
-                            item.kind,
-                            self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
-                            sugg_span,
+                            self_source,
+                            args,
+                            trait_ref.instantiate(
+                                self.tcx,
+                                self.fresh_args_for_item(sugg_span, impl_did)
+                            ).with_self_ty(self.tcx, rcvr_ty),
                             idx,
-                            self.tcx.sess.source_map(),
-                            item.fn_has_self_parameter,
-                        ) {
-                            suggs.push(sugg);
-                        }
+                            sugg_span,
+                            item,
+                        )
+                    {
+                        suggs.push(sugg);
                     }
                 }
                 CandidateSource::Trait(trait_did) => {
@@ -1374,25 +1356,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.span_note(item_span, msg);
                         None
                     };
-                    if let Some(sugg_span) = sugg_span {
-                        let path = self.tcx.def_path_str(trait_did);
-                        if let Some(sugg) = print_disambiguation_help(
-                            item_name,
-                            args,
-                            self_source,
+                    if let Some(sugg_span) = sugg_span
+                        && let Some(sugg) = print_disambiguation_help(
+                            self.tcx,
                             err,
-                            path,
-                            rcvr_ty,
-                            None,
-                            item.kind,
-                            self.tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id),
-                            sugg_span,
+                            self_source,
+                            args,
+                            ty::TraitRef::new(
+                                self.tcx,
+                                trait_did,
+                                self.fresh_args_for_item(sugg_span, trait_did)
+                            ).with_self_ty(self.tcx, rcvr_ty),
                             idx,
-                            self.tcx.sess.source_map(),
-                            item.fn_has_self_parameter,
-                        ) {
-                            suggs.push(sugg);
-                        }
+                            sugg_span,
+                            item,
+                        )
+                    {
+                        suggs.push(sugg);
                     }
                 }
             }
@@ -3263,59 +3243,59 @@ pub fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
 }
 
 fn print_disambiguation_help<'tcx>(
-    item_name: Ident,
-    args: Option<&'tcx [hir::Expr<'tcx>]>,
-    source: SelfSource<'tcx>,
+    tcx: TyCtxt<'tcx>,
     err: &mut Diagnostic,
-    trait_name: String,
-    rcvr_ty: Ty<'_>,
-    impl_self_ty: Option<Ty<'_>>,
-    kind: ty::AssocKind,
-    def_kind_descr: &'static str,
+    source: SelfSource<'tcx>,
+    args: Option<&'tcx [hir::Expr<'tcx>]>,
+    trait_ref: ty::TraitRef<'tcx>,
+    candidate_idx: Option<usize>,
     span: Span,
-    candidate: Option<usize>,
-    source_map: &source_map::SourceMap,
-    fn_has_self_parameter: bool,
+    item: ty::AssocItem,
 ) -> Option<String> {
+    let trait_ref = if item.fn_has_self_parameter {
+        trait_ref.print_only_trait_name().to_string()
+    } else {
+        format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
+    };
     Some(
-        if matches!(kind, ty::AssocKind::Fn)
+        if matches!(item.kind, ty::AssocKind::Fn)
             && let SelfSource::MethodCall(receiver) = source
             && let Some(args) = args
         {
+            let def_kind_descr = tcx.def_kind_descr(item.kind.as_def_kind(), item.def_id);
+            let item_name = item.ident(tcx);
+            let rcvr_ref = tcx.fn_sig(item.def_id).skip_binder().skip_binder().inputs()[0]
+                .ref_mutability()
+                .map_or("", |mutbl| mutbl.ref_prefix_str());
             let args = format!(
                 "({}{})",
-                rcvr_ty.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()),
+                rcvr_ref,
                 std::iter::once(receiver)
                     .chain(args.iter())
-                    .map(|arg| source_map
+                    .map(|arg| tcx
+                        .sess
+                        .source_map()
                         .span_to_snippet(arg.span)
                         .unwrap_or_else(|_| { "_".to_owned() }))
                     .collect::<Vec<_>>()
                     .join(", "),
             );
-            let trait_name = if !fn_has_self_parameter && let Some(impl_self_ty) = impl_self_ty {
-            format!("<{impl_self_ty} as {trait_name}>")
-        } else {
-            trait_name
-        };
             err.span_suggestion_verbose(
                 span,
                 format!(
                     "disambiguate the {def_kind_descr} for {}",
-                    if let Some(candidate) = candidate {
+                    if let Some(candidate) = candidate_idx {
                         format!("candidate #{candidate}")
                     } else {
                         "the candidate".to_string()
                     },
                 ),
-                format!("{trait_name}::{item_name}{args}"),
+                format!("{trait_ref}::{item_name}{args}"),
                 Applicability::HasPlaceholders,
             );
             return None;
-        } else if let Some(impl_self_ty) = impl_self_ty {
-            format!("<{impl_self_ty} as {trait_name}>::")
         } else {
-            format!("{trait_name}::")
+            format!("{trait_ref}::")
         },
     )
 }
diff --git a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
index a9e9c679fdb..ccdd9a95451 100644
--- a/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-blanket-impl.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-blanket-impl.rs:33:8
@@ -52,9 +52,9 @@ LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::CONST;
+LL |     <S as A>::CONST;
    |     ~~~~~~~~~~
-LL |     <T as B>::CONST;
+LL |     <S as B>::CONST;
    |     ~~~~~~~~~~
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/methods/disambiguate-multiple-impl.stderr b/tests/ui/methods/disambiguate-multiple-impl.stderr
index 901bfc30a3f..4172120770c 100644
--- a/tests/ui/methods/disambiguate-multiple-impl.stderr
+++ b/tests/ui/methods/disambiguate-multiple-impl.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <S as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <S as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-impl.rs:34:16
diff --git a/tests/ui/methods/disambiguate-multiple-trait-2.stderr b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
index 0f9c60ce243..2778f254a56 100644
--- a/tests/ui/methods/disambiguate-multiple-trait-2.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait-2.stderr
@@ -37,12 +37,12 @@ LL |     fn foo(&self);
    |     ^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(t);
-   |     ~~~~~~~~~
+LL |     A::foo(&t);
+   |     ~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(t);
-   |     ~~~~~~~~~
+LL |     B::foo(&t);
+   |     ~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait-2.rs:20:16
@@ -62,10 +62,10 @@ LL |     const CONST: usize;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = A::CONST;
-   |             ~~~
-LL |     let _ = B::CONST;
-   |             ~~~
+LL |     let _ = <T as A>::CONST;
+   |             ~~~~~~~~~~
+LL |     let _ = <T as B>::CONST;
+   |             ~~~~~~~~~~
 
 error[E0223]: ambiguous associated type
   --> $DIR/disambiguate-multiple-trait-2.rs:52:12
@@ -98,10 +98,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait-2.rs:49:16
@@ -121,9 +121,9 @@ LL |     const CONST: usize = 1;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = <T as A>::CONST;
+LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-LL |     let _ = <T as B>::CONST;
+LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/methods/disambiguate-multiple-trait.stderr b/tests/ui/methods/disambiguate-multiple-trait.stderr
index 9a50d51245b..e00498ca62b 100644
--- a/tests/ui/methods/disambiguate-multiple-trait.stderr
+++ b/tests/ui/methods/disambiguate-multiple-trait.stderr
@@ -29,10 +29,10 @@ LL |     fn foo(&self) {}
    |     ^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     <T as A>::foo(&s);
-   |     ~~~~~~~~~~
-LL |     <T as B>::foo(&s);
-   |     ~~~~~~~~~~
+LL |     A::foo(&s);
+   |     ~~~
+LL |     B::foo(&s);
+   |     ~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/disambiguate-multiple-trait.rs:27:16
@@ -52,9 +52,9 @@ LL |     const CONST: usize = 2;
    |     ^^^^^^^^^^^^^^^^^^
 help: use fully-qualified syntax to disambiguate
    |
-LL |     let _ = <T as A>::CONST;
+LL |     let _ = <S as A>::CONST;
    |             ~~~~~~~~~~
-LL |     let _ = <T as B>::CONST;
+LL |     let _ = <S as B>::CONST;
    |             ~~~~~~~~~~
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
index 601e6bbb006..9a84768a9f4 100644
--- a/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
+++ b/tests/ui/methods/method-ambig-two-traits-from-bounds.stderr
@@ -16,12 +16,12 @@ LL | trait B { fn foo(&self); }
    |           ^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(t);
-   |     ~~~~~~~~~
+LL |     A::foo(&t);
+   |     ~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(t);
-   |     ~~~~~~~~~
+LL |     B::foo(&t);
+   |     ~~~~~~~~~~
 
 error: aborting due to previous error
 
diff --git a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
index 4e83e4b77f1..755179650bb 100644
--- a/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
+++ b/tests/ui/methods/method-deref-to-same-trait-object-with-separate-params.stderr
@@ -54,8 +54,8 @@ LL |     let z = NuisanceFoo::foo(x);
    |             ~~~~~~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #3
    |
-LL |     let z = FinalFoo::foo(x);
-   |             ~~~~~~~~~~~~~~~~
+LL |     let z = FinalFoo::foo(&x);
+   |             ~~~~~~~~~~~~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/method-deref-to-same-trait-object-with-separate-params.rs:139:24
diff --git a/tests/ui/span/issue-37767.stderr b/tests/ui/span/issue-37767.stderr
index b612fdf16fc..457870821a1 100644
--- a/tests/ui/span/issue-37767.stderr
+++ b/tests/ui/span/issue-37767.stderr
@@ -16,12 +16,12 @@ LL |     fn foo(&mut self) {}
    |     ^^^^^^^^^^^^^^^^^
 help: disambiguate the method for candidate #1
    |
-LL |     A::foo(&a)
-   |     ~~~~~~~~~~
+LL |     A::foo(&mut a)
+   |     ~~~~~~~~~~~~~~
 help: disambiguate the method for candidate #2
    |
-LL |     B::foo(&a)
-   |     ~~~~~~~~~~
+LL |     B::foo(&mut a)
+   |     ~~~~~~~~~~~~~~
 
 error[E0034]: multiple applicable items in scope
   --> $DIR/issue-37767.rs:22:7