From 857eb02abe3931271db6d85a899fccba6d3ab65e Mon Sep 17 00:00:00 2001 From: Takayuki Maeda <41065217+TaKO8Ki@users.noreply.github.com> Date: Fri, 6 May 2022 23:14:11 +0900 Subject: [PATCH] suggest fully qualified path with appropriate params --- .../infer/error_reporting/need_type_info.rs | 23 ++++++- ...-qualified-path-with-appropriate-params.rs | 24 ++++++++ ...lified-path-with-appropriate-params.stderr | 61 +++++++++++++++++++ 3 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs create mode 100644 src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.stderr 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 b1eb9f0da87f7..78e0864d918d9 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: `>::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 0000000000000..da68b996be999 --- /dev/null +++ b/src/test/ui/traits/suggest-fully-qualified-path-with-appropriate-params.rs @@ -0,0 +1,24 @@ +struct Thing; + +trait Method { + fn method(&self) -> T; + fn mut_method(&mut self) -> T; +} + +impl Method for Thing { + fn method(&self) -> i32 { 0 } + fn mut_method(&mut self) -> i32 { 0 } +} + +impl Method 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 0000000000000..0c4962417e9bc --- /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 for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use the fully qualified path for the potential candidates + | +LL | >::method(&thing); + | ++++++++++++++++++++++++++++++++ ~ +LL | >::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 for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | impl Method for Thing { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: use the fully qualified path for the potential candidates + | +LL | >::mut_method(&mut thing); + | +++++++++++++++++++++++++++++++++++++++ ~ +LL | >::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`.