about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs23
-rw-r--r--src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs24
-rw-r--r--src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr61
3 files changed, 107 insertions, 1 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index b1eb9f0da87..78e0864d918 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -731,6 +731,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 //    |               help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
                 //    |
                 //    = note: cannot satisfy `Impl: Into<_>`
+                debug!(?segment);
                 if !impl_candidates.is_empty() && e.span.contains(span)
                     && let Some(expr) = exprs.first()
                     && let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
@@ -739,9 +740,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     let mut eraser = TypeParamEraser(self.tcx);
                     let candidate_len = impl_candidates.len();
                     let mut suggestions: Vec<_> = impl_candidates.iter().map(|candidate| {
+                        let trait_item = self.tcx
+                            .associated_items(candidate.def_id)
+                            .find_by_name_and_kind(
+                                self.tcx,
+                                segment.ident,
+                                ty::AssocKind::Fn,
+                                candidate.def_id
+                            );
+                        let prefix = if let Some(trait_item) = trait_item
+                            && let Some(trait_m) = trait_item.def_id.as_local()
+                            && let hir::TraitItemKind::Fn(fn_, _) = &self.tcx.hir().trait_item(hir::TraitItemId { def_id: trait_m }).kind
+                        {
+                            match fn_.decl.implicit_self {
+                                hir::ImplicitSelfKind::ImmRef => "&",
+                                hir::ImplicitSelfKind::MutRef => "&mut ",
+                                _ => "",
+                            }
+                        } else {
+                            ""
+                        };
                         let candidate = candidate.super_fold_with(&mut eraser);
                         vec![
-                            (expr.span.shrink_to_lo(), format!("{}::{}(", candidate, segment.ident)),
+                            (expr.span.shrink_to_lo(), format!("{}::{}({}", candidate, segment.ident, prefix)),
                             if exprs.len() == 1 {
                                 (expr.span.shrink_to_hi().with_hi(e.span.hi()), ")".to_string())
                             } else {
diff --git a/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs
new file mode 100644
index 00000000000..da68b996be9
--- /dev/null
+++ b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs
@@ -0,0 +1,24 @@
+struct Thing;
+
+trait Method<T> {
+    fn method(&self) -> T;
+    fn mut_method(&mut self) -> T;
+}
+
+impl Method<i32> for Thing {
+    fn method(&self) -> i32 { 0 }
+    fn mut_method(&mut self) -> i32 { 0 }
+}
+
+impl Method<u32> for Thing {
+    fn method(&self) -> u32 { 0 }
+    fn mut_method(&mut self) -> u32 { 0 }
+}
+
+fn main() {
+    let thing = Thing;
+    thing.method();
+    //~^ ERROR type annotations needed
+    //~| ERROR type annotations needed
+    thing.mut_method(); //~ ERROR type annotations needed
+}
diff --git a/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr
new file mode 100644
index 00000000000..0c4962417e9
--- /dev/null
+++ b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr
@@ -0,0 +1,61 @@
+error[E0282]: type annotations needed
+  --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:20:11
+   |
+LL |     thing.method();
+   |     ------^^^^^^--
+   |     |     |
+   |     |     cannot infer type for type parameter `T` declared on the trait `Method`
+   |     this method call resolves to `T`
+
+error[E0283]: type annotations needed
+  --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:20:11
+   |
+LL |     thing.method();
+   |     ------^^^^^^--
+   |     |     |
+   |     |     cannot infer type for type parameter `T` declared on the trait `Method`
+   |     this method call resolves to `T`
+   |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+  --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:8:1
+   |
+LL | impl Method<i32> for Thing {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use the fully qualified path for the potential candidates
+   |
+LL |     <Thing as Method<i32>>::method(&thing);
+   |     ++++++++++++++++++++++++++++++++     ~
+LL |     <Thing as Method<u32>>::method(&thing);
+   |     ++++++++++++++++++++++++++++++++     ~
+
+error[E0283]: type annotations needed
+  --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:23:11
+   |
+LL |     thing.mut_method();
+   |     ------^^^^^^^^^^--
+   |     |     |
+   |     |     cannot infer type for type parameter `T` declared on the trait `Method`
+   |     this method call resolves to `T`
+   |
+note: multiple `impl`s satisfying `Thing: Method<_>` found
+  --> $DIR/suggest-fully-qualified-path-with-appropriate-params.rs:8:1
+   |
+LL | impl Method<i32> for Thing {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL | impl Method<u32> for Thing {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use the fully qualified path for the potential candidates
+   |
+LL |     <Thing as Method<i32>>::mut_method(&mut thing);
+   |     +++++++++++++++++++++++++++++++++++++++      ~
+LL |     <Thing as Method<u32>>::mut_method(&mut thing);
+   |     +++++++++++++++++++++++++++++++++++++++      ~
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0282, E0283.
+For more information about an error, try `rustc --explain E0282`.