about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEsteban Küber <esteban@kuber.com.ar>2024-02-10 03:33:20 +0000
committerEsteban Küber <esteban@kuber.com.ar>2024-02-22 18:04:55 +0000
commit385eea1d4610f5bd756dd930f36762a7fc8f75e0 (patch)
tree1566a424674269c07da13a44c77c28cfaadc6161
parentd30dfb0af72ab71ee267eecef26a6270cee8822b (diff)
downloadrust-385eea1d4610f5bd756dd930f36762a7fc8f75e0.tar.gz
rust-385eea1d4610f5bd756dd930f36762a7fc8f75e0.zip
Consider methods from traits when suggesting typos
Do not provide a structured suggestion when the arguments don't match.

```
error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in the current scope
  --> $DIR/auto-ref-slice-plus-ref.rs:7:7
   |
LL |     a.test_mut();
   |       ^^^^^^^^
   |
   = help: items from traits can only be used if the trait is implemented and in scope
note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
  --> $DIR/auto-ref-slice-plus-ref.rs:14:1
   |
LL | trait MyIter {
   | ^^^^^^^^^^^^
help: there is a method `get_mut` with a similar name, but with different arguments
  --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
```

Consider methods beyond inherent ones when suggesting typos.

```
error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope
  --> $DIR/object-pointer-types.rs:11:7
   |
LL |     fn owned(self: Box<Self>);
   |                    --------- the method might not be found because of this arbitrary self type
...
LL |     x.owned();
   |       ^^^^^ help: there is a method with a similar name: `to_owned`
```

Fix #101013.
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs88
-rw-r--r--tests/ui/associated-item/associated-item-enum.stderr2
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.rs2
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.stderr6
-rw-r--r--tests/ui/auto-ref-slice-plus-ref.stderr4
-rw-r--r--tests/ui/confuse-field-and-method/issue-33784.stderr4
-rw-r--r--tests/ui/hygiene/no_implicit_prelude.stderr4
-rw-r--r--tests/ui/impl-trait/no-method-suggested-traits.stderr36
-rw-r--r--tests/ui/issues/issue-28344.stderr16
-rw-r--r--tests/ui/issues/issue-39175.stderr4
-rw-r--r--tests/ui/issues/issue-56175.stderr12
-rw-r--r--tests/ui/object-pointer-types.stderr2
-rw-r--r--tests/ui/rust-2018/trait-import-suggestions.stderr18
-rw-r--r--tests/ui/rust-2021/future-prelude-collision-shadow.stderr6
-rw-r--r--tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr5
-rw-r--r--tests/ui/suggestions/suggest-methods.rs5
-rw-r--r--tests/ui/suggestions/suggest-methods.stderr16
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.rs1
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.stderr12
-rw-r--r--tests/ui/traits/issue-117794.stderr8
-rw-r--r--tests/ui/traits/item-privacy.stderr28
23 files changed, 223 insertions, 68 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index b686e65a1d9..0ca7a8bb47b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -553,14 +553,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && let ty::AssocKind::Fn = assoc.kind
                 && assoc.fn_has_self_parameter
             {
-                let fn_sig =
-                    if let ty::Adt(_, args) = callee_ty.peel_refs().kind() {
-                        let args = ty::GenericArgs::identity_for_item(tcx, assoc.def_id)
-                            .rebase_onto(tcx, assoc.container_id(tcx), args);
-                        tcx.fn_sig(assoc.def_id).instantiate(tcx, args)
-                    } else {
-                        tcx.fn_sig(assoc.def_id).instantiate_identity()
-                    };
+                let args = self.infcx.fresh_args_for_item(call_name.span, assoc.def_id);
+                let fn_sig = tcx.fn_sig(assoc.def_id).instantiate(tcx, args);
                 let fn_sig =
                     self.instantiate_binder_with_fresh_vars(call_name.span, FnCall, fn_sig);
                 Some((assoc, fn_sig));
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 2d83e74b6db..7117a59c409 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -1768,6 +1768,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
             );
             pcx.allow_similar_names = true;
             pcx.assemble_inherent_candidates();
+            pcx.assemble_extension_candidates_for_all_traits();
 
             let method_names = pcx.candidate_method_names(|_| true);
             pcx.allow_similar_names = false;
@@ -1777,6 +1778,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                     pcx.reset();
                     pcx.method_name = Some(method_name);
                     pcx.assemble_inherent_candidates();
+                    pcx.assemble_extension_candidates_for_all_traits();
                     pcx.pick_core().and_then(|pick| pick.ok()).map(|pick| pick.item)
                 })
                 .collect();
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 989b9d7741d..735a1b17d7e 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -1359,27 +1359,89 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 && Some(similar_candidate.name) != confusable_suggested
             {
                 let def_kind = similar_candidate.kind.as_def_kind();
-                // Methods are defined within the context of a struct and their first parameter is always self,
-                // which represents the instance of the struct the method is being called on
-                // Associated functions don’t take self as a parameter and
-                // they are not methods because they don’t have an instance of the struct to work with.
-                if def_kind == DefKind::AssocFn && similar_candidate.fn_has_self_parameter {
+                let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
+                // Methods are defined within the context of a struct and their first parameter
+                // is always `self`, which represents the instance of the struct the method is
+                // being called on Associated functions don’t take self as a parameter and they are
+                // not methods because they don’t have an instance of the struct to work with.
+                if def_kind == DefKind::AssocFn {
+                    let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id);
+                    let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args);
+                    let fn_sig =
+                        self.instantiate_binder_with_fresh_vars(span, infer::FnCall, fn_sig);
+                    if similar_candidate.fn_has_self_parameter {
+                        if let Some(args) = args
+                            && fn_sig.inputs()[1..].len() == args.len()
+                        {
+                            // We found a method with the same number of arguments as the method
+                            // call expression the user wrote.
+                            err.span_suggestion(
+                                span,
+                                format!("there is {an} method with a similar name"),
+                                similar_candidate.name,
+                                Applicability::MaybeIncorrect,
+                            );
+                        } else {
+                            // We found a method but either the expression is not a method call or
+                            // the argument count didn't match.
+                            err.span_help(
+                                tcx.def_span(similar_candidate.def_id),
+                                format!(
+                                    "there is {an} method `{}` with a similar name{}",
+                                    similar_candidate.name,
+                                    if let None = args {
+                                        ""
+                                    } else {
+                                        ", but with different arguments"
+                                    },
+                                ),
+                            );
+                        }
+                    } else if let Some(args) = args
+                        && fn_sig.inputs().len() == args.len()
+                    {
+                        // We have fn call expression and the argument count match the associated
+                        // function we found.
+                        err.span_suggestion(
+                            span,
+                            format!(
+                                "there is {an} {} with a similar name",
+                                self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
+                            ),
+                            similar_candidate.name,
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        err.span_help(
+                            tcx.def_span(similar_candidate.def_id),
+                            format!(
+                                "there is {an} {} `{}` with a similar name",
+                                self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
+                                similar_candidate.name,
+                            ),
+                        );
+                    }
+                } else if let Mode::Path = mode {
+                    // We have an associated item syntax and we found something that isn't an fn.
                     err.span_suggestion(
                         span,
-                        "there is a method with a similar name",
+                        format!(
+                            "there is {an} {} with a similar name",
+                            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
+                        ),
                         similar_candidate.name,
                         Applicability::MaybeIncorrect,
                     );
                 } else {
-                    err.span_suggestion(
-                        span,
+                    // The expression is a function or method call, but the item we found is an
+                    // associated const or type.
+                    err.span_help(
+                        tcx.def_span(similar_candidate.def_id),
                         format!(
-                            "there is {} {} with a similar name",
-                            self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id),
-                            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id)
+                            "there is {an} {} `{}` with a similar name",
+                            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
+                            similar_candidate.name,
                         ),
-                        similar_candidate.name,
-                        Applicability::MaybeIncorrect,
                     );
                 }
             }
diff --git a/tests/ui/associated-item/associated-item-enum.stderr b/tests/ui/associated-item/associated-item-enum.stderr
index ebf3c5499a6..9e9f5c0daad 100644
--- a/tests/ui/associated-item/associated-item-enum.stderr
+++ b/tests/ui/associated-item/associated-item-enum.stderr
@@ -20,7 +20,7 @@ LL |     Enum::mispellable_trait();
    |           ^^^^^^^^^^^^^^^^^
    |           |
    |           variant or associated item not found in `Enum`
-   |           help: there is an associated function with a similar name: `misspellable`
+   |           help: there is an associated function with a similar name: `misspellable_trait`
 
 error[E0599]: no variant or associated item named `MISPELLABLE` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:19:11
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.rs b/tests/ui/attributes/rustc_confusables_std_cases.rs
index 95093f5e72c..d9121695950 100644
--- a/tests/ui/attributes/rustc_confusables_std_cases.rs
+++ b/tests/ui/attributes/rustc_confusables_std_cases.rs
@@ -16,7 +16,7 @@ fn main() {
     //~^ HELP you might have meant to use `len`
     x.size(); //~ ERROR E0599
     //~^ HELP you might have meant to use `len`
-    //~| HELP there is a method with a similar name
+    //~| HELP there is a method `resize` with a similar name
     x.append(42); //~ ERROR E0308
     //~^ HELP you might have meant to use `push`
     String::new().push(""); //~ ERROR E0308
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr
index 7d2410bb0ef..45d571f435c 100644
--- a/tests/ui/attributes/rustc_confusables_std_cases.stderr
+++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr
@@ -48,14 +48,12 @@ error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the cu
 LL |     x.size();
    |       ^^^^
    |
+help: there is a method `resize` with a similar name, but with different arguments
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
 help: you might have meant to use `len`
    |
 LL |     x.len();
    |       ~~~
-help: there is a method with a similar name
-   |
-LL |     x.resize();
-   |       ~~~~~~
 
 error[E0308]: mismatched types
   --> $DIR/rustc_confusables_std_cases.rs:20:14
diff --git a/tests/ui/auto-ref-slice-plus-ref.stderr b/tests/ui/auto-ref-slice-plus-ref.stderr
index e2883050720..806c1ee064f 100644
--- a/tests/ui/auto-ref-slice-plus-ref.stderr
+++ b/tests/ui/auto-ref-slice-plus-ref.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `test_mut` found for struct `Vec<{integer}>` in th
   --> $DIR/auto-ref-slice-plus-ref.rs:7:7
    |
 LL |     a.test_mut();
-   |       ^^^^^^^^ help: there is a method with a similar name: `get_mut`
+   |       ^^^^^^^^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
@@ -10,6 +10,8 @@ note: `MyIter` defines an item `test_mut`, perhaps you need to implement it
    |
 LL | trait MyIter {
    | ^^^^^^^^^^^^
+help: there is a method `get_mut` with a similar name, but with different arguments
+  --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
 
 error[E0599]: no method named `test` found for struct `Vec<{integer}>` in the current scope
   --> $DIR/auto-ref-slice-plus-ref.rs:8:7
diff --git a/tests/ui/confuse-field-and-method/issue-33784.stderr b/tests/ui/confuse-field-and-method/issue-33784.stderr
index aaf953a66d5..f6678dc8543 100644
--- a/tests/ui/confuse-field-and-method/issue-33784.stderr
+++ b/tests/ui/confuse-field-and-method/issue-33784.stderr
@@ -8,6 +8,10 @@ help: to call the function stored in `closure`, surround the field access with p
    |
 LL |     (p.closure)();
    |     +         +
+help: there is a method with a similar name
+   |
+LL |     p.clone();
+   |       ~~~~~
 
 error[E0599]: no method named `fn_ptr` found for reference `&&Obj<{closure@$DIR/issue-33784.rs:25:43: 25:45}>` in the current scope
   --> $DIR/issue-33784.rs:29:7
diff --git a/tests/ui/hygiene/no_implicit_prelude.stderr b/tests/ui/hygiene/no_implicit_prelude.stderr
index 96187b1c501..646863a884c 100644
--- a/tests/ui/hygiene/no_implicit_prelude.stderr
+++ b/tests/ui/hygiene/no_implicit_prelude.stderr
@@ -20,9 +20,11 @@ LL |     fn f() { ::bar::m!(); }
    |              ----------- in this macro invocation
 ...
 LL |         ().clone()
-   |            ^^^^^ method not found in `()`
+   |            ^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
+help: there is a method `clone_from` with a similar name, but with different arguments
+  --> $SRC_DIR/core/src/clone.rs:LL:COL
    = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
diff --git a/tests/ui/impl-trait/no-method-suggested-traits.stderr b/tests/ui/impl-trait/no-method-suggested-traits.stderr
index 160cc044078..cf1bf59ab20 100644
--- a/tests/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/tests/ui/impl-trait/no-method-suggested-traits.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `method` found for type `u32` in the current scope
   --> $DIR/no-method-suggested-traits.rs:23:10
    |
 LL |     1u32.method();
-   |          ^^^^^^ method not found in `u32`
+   |          ^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
@@ -15,12 +15,16 @@ LL + use no_method_suggested_traits::foo::PubPub;
    |
 LL + use no_method_suggested_traits::qux::PrivPub;
    |
+help: there is a method with a similar name
+   |
+LL |     1u32.method2();
+   |          ~~~~~~~
 
 error[E0599]: no method named `method` found for struct `Rc<&mut Box<&u32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:26:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method();
-   |                                            ^^^^^^ method not found in `Rc<&mut Box<&u32>>`
+   |                                            ^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
@@ -33,6 +37,10 @@ LL + use no_method_suggested_traits::foo::PubPub;
    |
 LL + use no_method_suggested_traits::qux::PrivPub;
    |
+help: there is a method with a similar name
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&1u32)).method2();
+   |                                            ~~~~~~~
 
 error[E0599]: no method named `method` found for type `char` in the current scope
   --> $DIR/no-method-suggested-traits.rs:30:9
@@ -41,31 +49,39 @@ LL |         fn method(&self) {}
    |            ------ the method is available for `char` here
 ...
 LL |     'a'.method();
-   |         ^^^^^^ method not found in `char`
+   |         ^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use foo::Bar;
    |
+help: there is a method with a similar name
+   |
+LL |     'a'.method2();
+   |         ~~~~~~~
 
 error[E0599]: no method named `method` found for struct `Rc<&mut Box<&char>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:32:43
    |
 LL |     std::rc::Rc::new(&mut Box::new(&'a')).method();
-   |                                           ^^^^^^ method not found in `Rc<&mut Box<&char>>`
+   |                                           ^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use foo::Bar;
    |
+help: there is a method with a similar name
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&'a')).method2();
+   |                                           ~~~~~~~
 
 error[E0599]: no method named `method` found for type `i32` in the current scope
   --> $DIR/no-method-suggested-traits.rs:35:10
    |
 LL |     1i32.method();
-   |          ^^^^^^ method not found in `i32`
+   |          ^^^^^^
    |
   ::: $DIR/auxiliary/no_method_suggested_traits.rs:8:12
    |
@@ -77,18 +93,26 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use no_method_suggested_traits::foo::PubPub;
    |
+help: there is a method with a similar name
+   |
+LL |     1i32.method3();
+   |          ~~~~~~~
 
 error[E0599]: no method named `method` found for struct `Rc<&mut Box<&i32>>` in the current scope
   --> $DIR/no-method-suggested-traits.rs:37:44
    |
 LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method();
-   |                                            ^^^^^^ method not found in `Rc<&mut Box<&i32>>`
+   |                                            ^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use no_method_suggested_traits::foo::PubPub;
    |
+help: there is a method with a similar name
+   |
+LL |     std::rc::Rc::new(&mut Box::new(&1i32)).method3();
+   |                                            ~~~~~~~
 
 error[E0599]: no method named `method` found for struct `Foo` in the current scope
   --> $DIR/no-method-suggested-traits.rs:40:9
diff --git a/tests/ui/issues/issue-28344.stderr b/tests/ui/issues/issue-28344.stderr
index 8b427b692a7..ddc1027c16b 100644
--- a/tests/ui/issues/issue-28344.stderr
+++ b/tests/ui/issues/issue-28344.stderr
@@ -22,10 +22,10 @@ error[E0599]: no function or associated item named `bitor` found for trait objec
   --> $DIR/issue-28344.rs:4:25
    |
 LL |     let x: u8 = BitXor::bitor(0 as u8, 0 as u8);
-   |                         ^^^^^
-   |                         |
-   |                         function or associated item not found in `dyn BitXor<_>`
-   |                         help: there is a method with a similar name: `bitxor`
+   |                         ^^^^^ function or associated item not found in `dyn BitXor<_>`
+   |
+help: there is a method `bitxor` with a similar name, but with different arguments
+  --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
 warning: trait objects without an explicit `dyn` are deprecated
   --> $DIR/issue-28344.rs:10:13
@@ -50,10 +50,10 @@ error[E0599]: no function or associated item named `bitor` found for trait objec
   --> $DIR/issue-28344.rs:10:21
    |
 LL |     let g = BitXor::bitor;
-   |                     ^^^^^
-   |                     |
-   |                     function or associated item not found in `dyn BitXor<_>`
-   |                     help: there is a method with a similar name: `bitxor`
+   |                     ^^^^^ function or associated item not found in `dyn BitXor<_>`
+   |
+help: there is a method `bitxor` with a similar name, but with different arguments
+  --> $SRC_DIR/core/src/ops/bit.rs:LL:COL
 
 error: aborting due to 4 previous errors; 2 warnings emitted
 
diff --git a/tests/ui/issues/issue-39175.stderr b/tests/ui/issues/issue-39175.stderr
index 1bc11dab327..bdc9e422e86 100644
--- a/tests/ui/issues/issue-39175.stderr
+++ b/tests/ui/issues/issue-39175.stderr
@@ -2,9 +2,11 @@ error[E0599]: no method named `exec` found for mutable reference `&mut Command`
   --> $DIR/issue-39175.rs:14:39
    |
 LL |     Command::new("echo").arg("hello").exec();
-   |                                       ^^^^ method not found in `&mut Command`
+   |                                       ^^^^
    |
    = help: items from traits can only be used if the trait is in scope
+help: there is a method `pre_exec` with a similar name, but with different arguments
+  --> $SRC_DIR/std/src/os/unix/process.rs:LL:COL
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use std::os::unix::process::CommandExt;
diff --git a/tests/ui/issues/issue-56175.stderr b/tests/ui/issues/issue-56175.stderr
index 1ddee1f4895..d8c757c1583 100644
--- a/tests/ui/issues/issue-56175.stderr
+++ b/tests/ui/issues/issue-56175.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `trait_method` found for struct `FooStruct` in the
   --> $DIR/issue-56175.rs:5:33
    |
 LL |     reexported_trait::FooStruct.trait_method();
-   |                                 ^^^^^^^^^^^^ method not found in `FooStruct`
+   |                                 ^^^^^^^^^^^^
    |
   ::: $DIR/auxiliary/reexported-trait.rs:3:12
    |
@@ -14,12 +14,16 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use reexported_trait::Trait;
    |
+help: there is a method with a similar name
+   |
+LL |     reexported_trait::FooStruct.trait_method_b();
+   |                                 ~~~~~~~~~~~~~~
 
 error[E0599]: no method named `trait_method_b` found for struct `FooStruct` in the current scope
   --> $DIR/issue-56175.rs:7:33
    |
 LL |     reexported_trait::FooStruct.trait_method_b();
-   |                                 ^^^^^^^^^^^^^^ method not found in `FooStruct`
+   |                                 ^^^^^^^^^^^^^^
    |
   ::: $DIR/auxiliary/reexported-trait.rs:7:12
    |
@@ -31,6 +35,10 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use reexported_trait::TraitBRename;
    |
+help: there is a method with a similar name
+   |
+LL |     reexported_trait::FooStruct.trait_method();
+   |                                 ~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/object-pointer-types.stderr b/tests/ui/object-pointer-types.stderr
index 2c8df3b616f..fe21bf3aede 100644
--- a/tests/ui/object-pointer-types.stderr
+++ b/tests/ui/object-pointer-types.stderr
@@ -5,7 +5,7 @@ LL |     fn owned(self: Box<Self>);
    |                    --------- the method might not be found because of this arbitrary self type
 ...
 LL |     x.owned();
-   |       ^^^^^ method not found in `&dyn Foo`
+   |       ^^^^^ help: there is a method with a similar name: `to_owned`
 
 error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope
   --> $DIR/object-pointer-types.rs:17:7
diff --git a/tests/ui/rust-2018/trait-import-suggestions.stderr b/tests/ui/rust-2018/trait-import-suggestions.stderr
index 325c5976e7c..a9d625df9ba 100644
--- a/tests/ui/rust-2018/trait-import-suggestions.stderr
+++ b/tests/ui/rust-2018/trait-import-suggestions.stderr
@@ -5,13 +5,17 @@ LL |             fn foobar(&self) { }
    |                ------ the method is available for `u32` here
 ...
 LL |         x.foobar();
-   |           ^^^^^^ method not found in `u32`
+   |           ^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL +     use crate::foo::foobar::Foobar;
    |
+help: there is a method with a similar name
+   |
+LL |         x.bar();
+   |           ~~~
 
 error[E0599]: no method named `bar` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:28:7
@@ -20,19 +24,23 @@ LL |         fn bar(&self) { }
    |            --- the method is available for `u32` here
 ...
 LL |     x.bar();
-   |       ^^^ method not found in `u32`
+   |       ^^^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use crate::foo::Bar;
    |
+help: there is a method with a similar name
+   |
+LL |     x.foobar();
+   |       ~~~~~~
 
 error[E0599]: no method named `baz` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:29:7
    |
 LL |     x.baz();
-   |       ^^^ method not found in `u32`
+   |       ^^^ help: there is a method with a similar name: `bar`
 
 error[E0599]: no function or associated item named `from_str` found for type `u32` in the current scope
   --> $DIR/trait-import-suggestions.rs:30:18
@@ -47,8 +55,8 @@ LL + use std::str::FromStr;
    |
 help: there is an associated function with a similar name
    |
-LL |     let y = u32::from_str_radix("33");
-   |                  ~~~~~~~~~~~~~~
+LL |     let y = u32::from("33");
+   |                  ~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr
index d2b2e5b2fd7..1ca5708e753 100644
--- a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr
+++ b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `try_into` found for type `u8` in the current scop
   --> $DIR/future-prelude-collision-shadow.rs:27:26
    |
 LL |         let _: u32 = 3u8.try_into().unwrap();
-   |                          ^^^^^^^^ method not found in `u8`
+   |                          ^^^^^^^^
    |
    = help: items from traits can only be used if the trait is in scope
    = note: 'std::convert::TryInto' is included in the prelude starting in Edition 2021
@@ -12,6 +12,10 @@ LL +     use crate::m::TryIntoU32;
    |
 LL +     use std::convert::TryInto;
    |
+help: there is a method with a similar name
+   |
+LL |         let _: u32 = 3u8.into().unwrap();
+   |                          ~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr
index 8f738465d38..b1a618e7176 100644
--- a/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr
+++ b/tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr
@@ -2,7 +2,10 @@ error[E0599]: no method named `set` found for array `[u8; 1]` in the current sco
   --> $DIR/dont-suggest-pin-array-dot-set.rs:14:7
    |
 LL |     a.set(0, 3);
-   |       ^^^ help: there is a method with a similar name: `get`
+   |       ^^^
+   |
+help: there is a method `get` with a similar name, but with different arguments
+  --> $SRC_DIR/core/src/slice/mod.rs:LL:COL
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/suggestions/suggest-methods.rs b/tests/ui/suggestions/suggest-methods.rs
index f40b9ed99b8..f8095795447 100644
--- a/tests/ui/suggestions/suggest-methods.rs
+++ b/tests/ui/suggestions/suggest-methods.rs
@@ -7,6 +7,7 @@ impl Foo {
 
 trait FooT {
     fn bag(&self);
+    //~^ HELP there is a method
 }
 
 impl FooT for Foo {
@@ -19,12 +20,14 @@ fn main() {
 
     let s = "foo".to_string();
     let _ = s.is_emtpy(); //~ ERROR no method named
+    //~^ HELP there is a method
 
     // Generates a warning for `count_zeros()`. `count_ones()` is also a close
     // match, but the former is closer.
     let _ = 63u32.count_eos(); //~ ERROR no method named
+    //~^ HELP there is a method
 
-    // Does not generate a warning
     let _ = 63u32.count_o(); //~ ERROR no method named
+    //~^ HELP there is a method
 
 }
diff --git a/tests/ui/suggestions/suggest-methods.stderr b/tests/ui/suggestions/suggest-methods.stderr
index 03cb9c77922..293009f289b 100644
--- a/tests/ui/suggestions/suggest-methods.stderr
+++ b/tests/ui/suggestions/suggest-methods.stderr
@@ -1,26 +1,32 @@
 error[E0599]: no method named `bat` found for struct `Foo` in the current scope
-  --> $DIR/suggest-methods.rs:18:7
+  --> $DIR/suggest-methods.rs:19:7
    |
 LL | struct Foo;
    | ---------- method `bat` not found for this struct
 ...
 LL |     f.bat(1.0);
-   |       ^^^ help: there is a method with a similar name: `bar`
+   |       ^^^
+   |
+help: there is a method `bag` with a similar name, but with different arguments
+  --> $DIR/suggest-methods.rs:9:5
+   |
+LL |     fn bag(&self);
+   |     ^^^^^^^^^^^^^^
 
 error[E0599]: no method named `is_emtpy` found for struct `String` in the current scope
-  --> $DIR/suggest-methods.rs:21:15
+  --> $DIR/suggest-methods.rs:22:15
    |
 LL |     let _ = s.is_emtpy();
    |               ^^^^^^^^ help: there is a method with a similar name: `is_empty`
 
 error[E0599]: no method named `count_eos` found for type `u32` in the current scope
-  --> $DIR/suggest-methods.rs:25:19
+  --> $DIR/suggest-methods.rs:27:19
    |
 LL |     let _ = 63u32.count_eos();
    |                   ^^^^^^^^^ help: there is a method with a similar name: `count_zeros`
 
 error[E0599]: no method named `count_o` found for type `u32` in the current scope
-  --> $DIR/suggest-methods.rs:28:19
+  --> $DIR/suggest-methods.rs:30:19
    |
 LL |     let _ = 63u32.count_o();
    |                   ^^^^^^^ help: there is a method with a similar name: `count_ones`
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.rs b/tests/ui/suggestions/suggest-tryinto-edition-change.rs
index c4a24ffee93..37321774874 100644
--- a/tests/ui/suggestions/suggest-tryinto-edition-change.rs
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.rs
@@ -5,7 +5,6 @@
 fn test() {
     let _i: i16 = 0_i32.try_into().unwrap();
     //~^ ERROR no method named `try_into` found for type `i32` in the current scope
-    //~| NOTE method not found in `i32`
     //~| NOTE 'std::convert::TryInto' is included in the prelude starting in Edition 2021
 
     let _i: i16 = TryFrom::try_from(0_i32).unwrap();
diff --git a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
index 057e37dbe10..01fabbadbff 100644
--- a/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
+++ b/tests/ui/suggestions/suggest-tryinto-edition-change.stderr
@@ -1,5 +1,5 @@
 error[E0433]: failed to resolve: use of undeclared type `TryFrom`
-  --> $DIR/suggest-tryinto-edition-change.rs:11:19
+  --> $DIR/suggest-tryinto-edition-change.rs:10:19
    |
 LL |     let _i: i16 = TryFrom::try_from(0_i32).unwrap();
    |                   ^^^^^^^ use of undeclared type `TryFrom`
@@ -14,7 +14,7 @@ LL + use std::convert::TryFrom;
    |
 
 error[E0433]: failed to resolve: use of undeclared type `TryInto`
-  --> $DIR/suggest-tryinto-edition-change.rs:17:19
+  --> $DIR/suggest-tryinto-edition-change.rs:16:19
    |
 LL |     let _i: i16 = TryInto::try_into(0_i32).unwrap();
    |                   ^^^^^^^ use of undeclared type `TryInto`
@@ -29,7 +29,7 @@ LL + use std::convert::TryInto;
    |
 
 error[E0433]: failed to resolve: use of undeclared type `FromIterator`
-  --> $DIR/suggest-tryinto-edition-change.rs:23:22
+  --> $DIR/suggest-tryinto-edition-change.rs:22:22
    |
 LL |     let _v: Vec<_> = FromIterator::from_iter(&[1]);
    |                      ^^^^^^^^^^^^ use of undeclared type `FromIterator`
@@ -51,7 +51,7 @@ error[E0599]: no method named `try_into` found for type `i32` in the current sco
   --> $DIR/suggest-tryinto-edition-change.rs:6:25
    |
 LL |     let _i: i16 = 0_i32.try_into().unwrap();
-   |                         ^^^^^^^^ method not found in `i32`
+   |                         ^^^^^^^^
   --> $SRC_DIR/core/src/convert/mod.rs:LL:COL
    |
    = note: the method is available for `i32` here
@@ -62,6 +62,10 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use std::convert::TryInto;
    |
+help: there is a method with a similar name
+   |
+LL |     let _i: i16 = 0_i32.into().unwrap();
+   |                         ~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/issue-117794.stderr b/tests/ui/traits/issue-117794.stderr
index af63b47f07d..66561ffa4ce 100644
--- a/tests/ui/traits/issue-117794.stderr
+++ b/tests/ui/traits/issue-117794.stderr
@@ -2,7 +2,13 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco
   --> $DIR/issue-117794.rs:5:14
    |
 LL |         self.b(|| 0)
-   |              ^ help: there is a method with a similar name: `a`
+   |              ^
+   |
+help: there is a method `a` with a similar name, but with different arguments
+  --> $DIR/issue-117794.rs:4:5
+   |
+LL |     fn a(&self) -> impl Foo {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr
index 244cc2fc592..ede1764efdc 100644
--- a/tests/ui/traits/item-privacy.stderr
+++ b/tests/ui/traits/item-privacy.stderr
@@ -5,13 +5,17 @@ LL | struct S;
    | -------- method `a` not found for this struct
 ...
 LL |     S.a();
-   |       ^ method not found in `S`
+   |       ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use method::A;
    |
+help: there is a method with a similar name
+   |
+LL |     S.b();
+   |       ~
 
 error[E0599]: no method named `b` found for struct `S` in the current scope
   --> $DIR/item-privacy.rs:68:7
@@ -23,13 +27,17 @@ LL |         fn b(&self) { }
    |            - the method is available for `S` here
 ...
 LL |     S.b();
-   |       ^ method not found in `S`
+   |       ^
    |
    = help: items from traits can only be used if the trait is in scope
 help: the following trait is implemented but not in scope; perhaps add a `use` for it:
    |
 LL + use method::B;
    |
+help: there is a method with a similar name
+   |
+LL |     S.c();
+   |       ~
 
 error[E0624]: method `a` is private
   --> $DIR/item-privacy.rs:72:7
@@ -54,6 +62,10 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use method::A;
    |
+help: there is an associated constant with a similar name
+   |
+LL |     S::B(&S);
+   |        ~
 
 error[E0599]: no function or associated item named `b` found for struct `S` in the current scope
   --> $DIR/item-privacy.rs:80:8
@@ -69,6 +81,10 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use method::B;
    |
+help: there is an associated constant with a similar name
+   |
+LL |     S::B(&S);
+   |        ~
 
 error[E0624]: method `a` is private
   --> $DIR/item-privacy.rs:84:14
@@ -93,6 +109,10 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use assoc_const::A;
    |
+help: there is an associated constant with a similar name
+   |
+LL |     S::B;
+   |        ~
 
 error[E0599]: no associated item named `B` found for struct `S` in the current scope
   --> $DIR/item-privacy.rs:98:8
@@ -108,6 +128,10 @@ help: the following trait is implemented but not in scope; perhaps add a `use` f
    |
 LL + use assoc_const::B;
    |
+help: there is a method with a similar name
+   |
+LL |     S::b;
+   |        ~
 
 error[E0624]: associated constant `A` is private
   --> $DIR/item-privacy.rs:101:14