about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs126
-rw-r--r--compiler/rustc_hir_typeck/src/method/probe.rs26
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs248
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs2
-rw-r--r--library/alloc/src/collections/btree/map.rs3
-rw-r--r--library/alloc/src/collections/btree/map/entry.rs3
-rw-r--r--library/alloc/src/collections/btree/set.rs5
-rw-r--r--library/alloc/src/collections/linked_list.rs10
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs5
-rw-r--r--library/alloc/src/string.rs4
-rw-r--r--library/alloc/src/vec/mod.rs3
-rw-r--r--library/core/src/cell.rs2
-rw-r--r--library/core/src/option.rs1
-rw-r--r--library/core/src/result.rs1
-rw-r--r--library/proc_macro/src/bridge/scoped_cell.rs1
-rw-r--r--library/std/src/collections/hash/map.rs2
-rw-r--r--library/std/src/collections/hash/set.rs3
-rw-r--r--library/std/src/ffi/os_str.rs1
-rw-r--r--library/std/src/path.rs1
-rw-r--r--library/std/src/thread/local.rs2
-rw-r--r--tests/ui/associated-item/associated-item-enum.stderr30
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr2
-rw-r--r--tests/ui/atomic-from-mut-not-available.stderr4
-rw-r--r--tests/ui/attributes/rustc_confusables.rs4
-rw-r--r--tests/ui/attributes/rustc_confusables.stderr14
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.rs26
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.stderr104
-rw-r--r--tests/ui/auto-ref-slice-plus-ref.stderr4
-rw-r--r--tests/ui/block-result/issue-3563.stderr7
-rw-r--r--tests/ui/coherence/coherence_inherent.stderr2
-rw-r--r--tests/ui/coherence/coherence_inherent_cc.stderr2
-rw-r--r--tests/ui/confuse-field-and-method/issue-33784.stderr4
-rw-r--r--tests/ui/hygiene/no_implicit_prelude.stderr6
-rw-r--r--tests/ui/hygiene/trait_items.stderr2
-rw-r--r--tests/ui/impl-trait/no-method-suggested-traits.stderr48
-rw-r--r--tests/ui/impl-trait/where-allowed.stderr2
-rw-r--r--tests/ui/imports/overlapping_pub_trait.rs2
-rw-r--r--tests/ui/imports/overlapping_pub_trait.stderr2
-rw-r--r--tests/ui/imports/unnamed_pub_trait.rs2
-rw-r--r--tests/ui/imports/unnamed_pub_trait.stderr2
-rw-r--r--tests/ui/issues/issue-10465.stderr2
-rw-r--r--tests/ui/issues/issue-28344.stderr16
-rw-r--r--tests/ui/issues/issue-39175.stderr6
-rw-r--r--tests/ui/issues/issue-56175.stderr16
-rw-r--r--tests/ui/methods/issues/issue-105732.stderr7
-rw-r--r--tests/ui/methods/method-not-found-but-doc-alias.stderr7
-rw-r--r--tests/ui/object-pointer-types.stderr7
-rw-r--r--tests/ui/parser/emoji-identifiers.stderr9
-rw-r--r--tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr10
-rw-r--r--tests/ui/rust-2018/trait-import-suggestions.stderr31
-rw-r--r--tests/ui/rust-2018/uniform-paths/issue-87932.stderr2
-rw-r--r--tests/ui/rust-2021/future-prelude-collision-shadow.stderr8
-rw-r--r--tests/ui/self/arbitrary_self_type_mut_difference.stderr12
-rw-r--r--tests/ui/shadowed/shadowed-trait-methods.stderr2
-rw-r--r--tests/ui/suggestions/dont-suggest-pin-array-dot-set.stderr5
-rw-r--r--tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs2
-rw-r--r--tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr2
-rw-r--r--tests/ui/suggestions/import-trait-for-method-call.stderr2
-rw-r--r--tests/ui/suggestions/issue-109291.stderr9
-rw-r--r--tests/ui/suggestions/suggest-methods.rs5
-rw-r--r--tests/ui/suggestions/suggest-methods.stderr37
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.rs1
-rw-r--r--tests/ui/suggestions/suggest-tryinto-edition-change.stderr14
-rw-r--r--tests/ui/suggestions/use-placement-typeck.stderr2
-rw-r--r--tests/ui/traits/issue-117794.stderr8
-rw-r--r--tests/ui/traits/item-privacy.stderr42
-rw-r--r--tests/ui/traits/method-private.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.stderr30
-rw-r--r--tests/ui/typeck/issue-43189.stderr2
-rw-r--r--tests/ui/ufcs/bad-builder.stderr9
-rw-r--r--tests/ui/underscore-imports/shadow.stderr2
72 files changed, 833 insertions, 196 deletions
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 2d9ec9f6bab..4bc86435482 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1,7 +1,11 @@
 use crate::coercion::CoerceMany;
 use crate::errors::SuggestPtrNullMut;
 use crate::fn_ctxt::arg_matrix::{ArgMatrix, Compatibility, Error, ExpectedIdx, ProvidedIdx};
+use crate::fn_ctxt::infer::FnCall;
 use crate::gather_locals::Declaration;
+use crate::method::probe::IsSuggestion;
+use crate::method::probe::Mode::MethodCall;
+use crate::method::probe::ProbeScope::TraitsInScope;
 use crate::method::MethodCallee;
 use crate::TupleArgumentsFlag::*;
 use crate::{errors, Expectation::*};
@@ -451,7 +455,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         call_expr: &'tcx hir::Expr<'tcx>,
     ) -> ErrorGuaranteed {
         // Next, let's construct the error
-        let (error_span, full_call_span, call_name, is_method) = match &call_expr.kind {
+        let (error_span, call_ident, full_call_span, call_name, is_method) = match &call_expr.kind {
             hir::ExprKind::Call(
                 hir::Expr { hir_id, span, kind: hir::ExprKind::Path(qpath), .. },
                 _,
@@ -463,12 +467,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         CtorOf::Struct => "struct",
                         CtorOf::Variant => "enum variant",
                     };
-                    (call_span, *span, name, false)
+                    (call_span, None, *span, name, false)
                 } else {
-                    (call_span, *span, "function", false)
+                    (call_span, None, *span, "function", false)
                 }
             }
-            hir::ExprKind::Call(hir::Expr { span, .. }, _) => (call_span, *span, "function", false),
+            hir::ExprKind::Call(hir::Expr { span, .. }, _) => {
+                (call_span, None, *span, "function", false)
+            }
             hir::ExprKind::MethodCall(path_segment, _, _, span) => {
                 let ident_span = path_segment.ident.span;
                 let ident_span = if let Some(args) = path_segment.args {
@@ -476,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     ident_span
                 };
-                (*span, ident_span, "method", true)
+                (*span, Some(path_segment.ident), ident_span, "method", true)
             }
             k => span_bug!(call_span, "checking argument types on a non-call: `{:?}`", k),
         };
@@ -530,6 +536,104 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let callee_ty = callee_expr
             .and_then(|callee_expr| self.typeck_results.borrow().expr_ty_adjusted_opt(callee_expr));
 
+        // Obtain another method on `Self` that have similar name.
+        let similar_assoc = |call_name: Ident| -> Option<(ty::AssocItem, ty::FnSig<'_>)> {
+            if let Some(callee_ty) = callee_ty
+                && let Ok(Some(assoc)) = self.probe_op(
+                    call_name.span,
+                    MethodCall,
+                    Some(call_name),
+                    None,
+                    IsSuggestion(true),
+                    callee_ty.peel_refs(),
+                    callee_expr.unwrap().hir_id,
+                    TraitsInScope,
+                    |mut ctxt| ctxt.probe_for_similar_candidate(),
+                )
+                && let ty::AssocKind::Fn = assoc.kind
+                && assoc.fn_has_self_parameter
+            {
+                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));
+            }
+            None
+        };
+
+        let suggest_confusable = |err: &mut DiagnosticBuilder<'_>| {
+            let Some(call_name) = call_ident else {
+                return;
+            };
+            let Some(callee_ty) = callee_ty else {
+                return;
+            };
+            let input_types: Vec<Ty<'_>> = provided_arg_tys.iter().map(|(ty, _)| *ty).collect();
+            // Check for other methods in the following order
+            //  - methods marked as `rustc_confusables` with the provided arguments
+            //  - methods with the same argument type/count and short levenshtein distance
+            //  - methods marked as `rustc_confusables` (done)
+            //  - methods with short levenshtein distance
+
+            // Look for commonly confusable method names considering arguments.
+            if let Some(_name) = self.confusable_method_name(
+                err,
+                callee_ty.peel_refs(),
+                call_name,
+                Some(input_types.clone()),
+            ) {
+                return;
+            }
+            // Look for method names with short levenshtein distance, considering arguments.
+            if let Some((assoc, fn_sig)) = similar_assoc(call_name)
+                && fn_sig.inputs()[1..]
+                    .iter()
+                    .zip(input_types.iter())
+                    .all(|(expected, found)| self.can_coerce(*expected, *found))
+                && fn_sig.inputs()[1..].len() == input_types.len()
+            {
+                err.span_suggestion_verbose(
+                    call_name.span,
+                    format!("you might have meant to use `{}`", assoc.name),
+                    assoc.name,
+                    Applicability::MaybeIncorrect,
+                );
+                return;
+            }
+            // Look for commonly confusable method names disregarding arguments.
+            if let Some(_name) =
+                self.confusable_method_name(err, callee_ty.peel_refs(), call_name, None)
+            {
+                return;
+            }
+            // Look for similarly named methods with levenshtein distance with the right
+            // number of arguments.
+            if let Some((assoc, fn_sig)) = similar_assoc(call_name)
+                && fn_sig.inputs()[1..].len() == input_types.len()
+            {
+                err.span_note(
+                    tcx.def_span(assoc.def_id),
+                    format!(
+                        "there's is a method with similar name `{}`, but the arguments don't match",
+                        assoc.name,
+                    ),
+                );
+                return;
+            }
+            // Fallthrough: look for similarly named methods with levenshtein distance.
+            if let Some((assoc, _)) = similar_assoc(call_name) {
+                err.span_note(
+                    tcx.def_span(assoc.def_id),
+                    format!(
+                        "there's is a method with similar name `{}`, but their argument count \
+                         doesn't match",
+                        assoc.name,
+                    ),
+                );
+                return;
+            }
+        };
         // A "softer" version of the `demand_compatible`, which checks types without persisting them,
         // and treats error types differently
         // This will allow us to "probe" for other argument orders that would likely have been correct
@@ -694,6 +798,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         Some(mismatch_idx),
                         is_method,
                     );
+                    suggest_confusable(&mut err);
                     return err.emit();
                 }
             }
@@ -718,7 +823,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             if cfg!(debug_assertions) {
                 span_bug!(error_span, "expected errors from argument matrix");
             } else {
-                return tcx.dcx().emit_err(errors::ArgMismatchIndeterminate { span: error_span });
+                let mut err =
+                    tcx.dcx().create_err(errors::ArgMismatchIndeterminate { span: error_span });
+                suggest_confusable(&mut err);
+                return err.emit();
             }
         }
 
@@ -733,7 +841,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             let trace =
                 mk_trace(provided_span, formal_and_expected_inputs[*expected_idx], provided_ty);
             if !matches!(trace.cause.as_failure_code(*e), FailureCode::Error0308) {
-                reported = Some(self.err_ctxt().report_and_explain_type_error(trace, *e).emit());
+                let mut err = self.err_ctxt().report_and_explain_type_error(trace, *e);
+                suggest_confusable(&mut err);
+                reported = Some(err.emit());
                 return false;
             }
             true
@@ -802,6 +912,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Some(expected_idx.as_usize()),
                 is_method,
             );
+            suggest_confusable(&mut err);
             return err.emit();
         }
 
@@ -829,6 +940,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .with_code(err_code.to_owned())
         };
 
+        suggest_confusable(&mut err);
         // As we encounter issues, keep track of what we want to provide for the suggestion
         let mut labels = vec![];
         // If there is a single error, we give a specific suggestion; otherwise, we change to
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index a58e194e20a..7117a59c409 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -54,7 +54,7 @@ pub use self::PickKind::*;
 #[derive(Clone, Copy, Debug)]
 pub struct IsSuggestion(pub bool);
 
-struct ProbeContext<'a, 'tcx> {
+pub(crate) struct ProbeContext<'a, 'tcx> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     span: Span,
     mode: Mode,
@@ -355,7 +355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         .unwrap()
     }
 
-    fn probe_op<OP, R>(
+    pub(crate) fn probe_op<OP, R>(
         &'a self,
         span: Span,
         mode: Mode,
@@ -1750,7 +1750,9 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
     /// Similarly to `probe_for_return_type`, this method attempts to find the best matching
     /// candidate method where the method name may have been misspelled. Similarly to other
     /// edit distance based suggestions, we provide at most one such suggestion.
-    fn probe_for_similar_candidate(&mut self) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
+    pub(crate) fn probe_for_similar_candidate(
+        &mut self,
+    ) -> Result<Option<ty::AssocItem>, MethodError<'tcx>> {
         debug!("probing for method names similar to {:?}", self.method_name);
 
         self.probe(|_| {
@@ -1766,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;
@@ -1775,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();
@@ -1942,7 +1946,21 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
         let hir_id = self.fcx.tcx.local_def_id_to_hir_id(local_def_id);
         let attrs = self.fcx.tcx.hir().attrs(hir_id);
         for attr in attrs {
-            let sym::doc = attr.name_or_empty() else {
+            if sym::doc == attr.name_or_empty() {
+            } else if sym::rustc_confusables == attr.name_or_empty() {
+                let Some(confusables) = attr.meta_item_list() else {
+                    continue;
+                };
+                // #[rustc_confusables("foo", "bar"))]
+                for n in confusables {
+                    if let Some(lit) = n.lit()
+                        && name.as_str() == lit.symbol.as_str()
+                    {
+                        return true;
+                    }
+                }
+                continue;
+            } else {
                 continue;
             };
             let Some(values) = attr.meta_item_list() else {
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index cc111af5d8f..babdbce0005 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -23,6 +23,7 @@ use rustc_hir::PatKind::Binding;
 use rustc_hir::PathSegment;
 use rustc_hir::{ExprKind, Node, QPath};
 use rustc_infer::infer::{
+    self,
     type_variable::{TypeVariableOrigin, TypeVariableOriginKind},
     RegionVariableOrigin,
 };
@@ -274,7 +275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     .span_if_local(def_id)
                     .unwrap_or_else(|| self.tcx.def_span(def_id));
                 err.span_label(sp, format!("private {kind} defined here"));
-                self.suggest_valid_traits(&mut err, out_of_scope_traits, true);
+                self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true);
                 err.emit();
             }
 
@@ -1209,32 +1210,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         err.note(format!(
                             "the {item_kind} was found for\n{type_candidates}{additional_types}"
                         ));
-                    } else {
-                        'outer: for inherent_impl_did in
-                            self.tcx.inherent_impls(adt.did()).into_iter().flatten()
-                        {
-                            for inherent_method in
-                                self.tcx.associated_items(inherent_impl_did).in_definition_order()
-                            {
-                                if let Some(attr) = self
-                                    .tcx
-                                    .get_attr(inherent_method.def_id, sym::rustc_confusables)
-                                    && let Some(candidates) = parse_confusables(attr)
-                                    && candidates.contains(&item_name.name)
-                                {
-                                    err.span_suggestion_verbose(
-                                        item_name.span,
-                                        format!(
-                                            "you might have meant to use `{}`",
-                                            inherent_method.name
-                                        ),
-                                        inherent_method.name,
-                                        Applicability::MaybeIncorrect,
-                                    );
-                                    break 'outer;
-                                }
-                            }
-                        }
                     }
                 }
             } else {
@@ -1260,6 +1235,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             label_span_not_found(&mut err);
         }
 
+        let confusable_suggested = self.confusable_method_name(
+            &mut err,
+            rcvr_ty,
+            item_name,
+            args.map(|args| {
+                args.iter()
+                    .map(|expr| {
+                        self.node_ty_opt(expr.hir_id).unwrap_or_else(|| {
+                            self.next_ty_var(TypeVariableOrigin {
+                                kind: TypeVariableOriginKind::MiscVariable,
+                                span: expr.span,
+                            })
+                        })
+                    })
+                    .collect()
+            }),
+        );
+
         // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
         // can't be called due to `typeof(expr): Clone` not holding.
         if unsatisfied_predicates.is_empty() {
@@ -1361,31 +1354,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else if let Some(similar_candidate) = similar_candidate {
             // Don't emit a suggestion if we found an actual method
             // that had unsatisfied trait bounds
-            if unsatisfied_predicates.is_empty() {
-                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 {
-                    err.span_suggestion(
-                        span,
-                        "there is a method with a similar name",
-                        similar_candidate.name,
-                        Applicability::MaybeIncorrect,
-                    );
-                } else {
-                    err.span_suggestion(
-                        span,
-                        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)
-                        ),
-                        similar_candidate.name,
-                        Applicability::MaybeIncorrect,
-                    );
-                }
+            if unsatisfied_predicates.is_empty()
+                // ...or if we already suggested that name because of `rustc_confusable` annotation.
+                && Some(similar_candidate.name) != confusable_suggested
+            {
+                self.find_likely_intended_associated_item(
+                    &mut err,
+                    similar_candidate,
+                    span,
+                    args,
+                    mode,
+                );
             }
         }
         // If an appropriate error source is not found, check method chain for possible candiates
@@ -1437,6 +1416,146 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         Some(err)
     }
 
+    fn find_likely_intended_associated_item(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        similar_candidate: ty::AssocItem,
+        span: Span,
+        args: Option<&'tcx [hir::Expr<'tcx>]>,
+        mode: Mode,
+    ) {
+        let tcx = self.tcx;
+        let def_kind = similar_candidate.kind.as_def_kind();
+        let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
+        let msg = format!(
+            "there is {an} {} `{}` with a similar name",
+            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
+            similar_candidate.name,
+        );
+        // 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_verbose(
+                        span,
+                        msg,
+                        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!(
+                            "{msg}{}",
+                            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_verbose(
+                    span,
+                    msg,
+                    similar_candidate.name,
+                    Applicability::MaybeIncorrect,
+                );
+            } else {
+                err.span_help(tcx.def_span(similar_candidate.def_id), msg);
+            }
+        } else if let Mode::Path = mode
+            && args.unwrap_or(&[]).is_empty()
+        {
+            // We have an associated item syntax and we found something that isn't an fn.
+            err.span_suggestion_verbose(
+                span,
+                msg,
+                similar_candidate.name,
+                Applicability::MaybeIncorrect,
+            );
+        } else {
+            // 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), msg);
+        }
+    }
+
+    pub(crate) fn confusable_method_name(
+        &self,
+        err: &mut DiagnosticBuilder<'_>,
+        rcvr_ty: Ty<'tcx>,
+        item_name: Ident,
+        call_args: Option<Vec<Ty<'tcx>>>,
+    ) -> Option<Symbol> {
+        if let ty::Adt(adt, adt_args) = rcvr_ty.kind() {
+            for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter().flatten() {
+                for inherent_method in
+                    self.tcx.associated_items(inherent_impl_did).in_definition_order()
+                {
+                    if let Some(attr) =
+                        self.tcx.get_attr(inherent_method.def_id, sym::rustc_confusables)
+                        && let Some(candidates) = parse_confusables(attr)
+                        && candidates.contains(&item_name.name)
+                        && let ty::AssocKind::Fn = inherent_method.kind
+                    {
+                        let args =
+                            ty::GenericArgs::identity_for_item(self.tcx, inherent_method.def_id)
+                                .rebase_onto(
+                                    self.tcx,
+                                    inherent_method.container_id(self.tcx),
+                                    adt_args,
+                                );
+                        let fn_sig =
+                            self.tcx.fn_sig(inherent_method.def_id).instantiate(self.tcx, args);
+                        let fn_sig = self.instantiate_binder_with_fresh_vars(
+                            item_name.span,
+                            infer::FnCall,
+                            fn_sig,
+                        );
+                        if let Some(ref args) = call_args
+                            && fn_sig.inputs()[1..]
+                                .iter()
+                                .zip(args.into_iter())
+                                .all(|(expected, found)| self.can_coerce(*expected, *found))
+                            && fn_sig.inputs()[1..].len() == args.len()
+                        {
+                            err.span_suggestion_verbose(
+                                item_name.span,
+                                format!("you might have meant to use `{}`", inherent_method.name),
+                                inherent_method.name,
+                                Applicability::MaybeIncorrect,
+                            );
+                            return Some(inherent_method.name);
+                        } else if let None = call_args {
+                            err.span_note(
+                                self.tcx.def_span(inherent_method.def_id),
+                                format!(
+                                    "you might have meant to use method `{}`",
+                                    inherent_method.name,
+                                ),
+                            );
+                            return Some(inherent_method.name);
+                        }
+                    }
+                }
+            }
+        }
+        None
+    }
     fn note_candidates_on_method_error(
         &self,
         rcvr_ty: Ty<'tcx>,
@@ -2768,6 +2887,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn suggest_valid_traits(
         &self,
         err: &mut DiagnosticBuilder<'_>,
+        item_name: Ident,
         valid_out_of_scope_traits: Vec<DefId>,
         explain: bool,
     ) -> bool {
@@ -2786,9 +2906,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 err.help("items from traits can only be used if the trait is in scope");
             }
             let msg = format!(
-                "the following {traits_are} implemented but not in scope; \
-                 perhaps add a `use` for {one_of_them}:",
-                traits_are = if candidates.len() == 1 { "trait is" } else { "traits are" },
+                "{this_trait_is} implemented but not in scope; perhaps you want to import \
+                 {one_of_them}",
+                this_trait_is = if candidates.len() == 1 {
+                    format!(
+                        "trait `{}` which provides `{item_name}` is",
+                        self.tcx.item_name(candidates[0]),
+                    )
+                } else {
+                    format!("the following traits which provide `{item_name}` are")
+                },
                 one_of_them = if candidates.len() == 1 { "it" } else { "one of them" },
             );
 
@@ -2996,7 +3123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
             }
         }
-        if self.suggest_valid_traits(err, valid_out_of_scope_traits, true) {
+        if self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true) {
             return;
         }
 
@@ -3282,7 +3409,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 [] => {}
                 [trait_info] if trait_info.def_id.is_local() => {
                     if impls_trait(trait_info.def_id) {
-                        self.suggest_valid_traits(err, vec![trait_info.def_id], false);
+                        self.suggest_valid_traits(err, item_name, vec![trait_info.def_id], false);
                     } else {
                         err.subdiagnostic(
                             self.dcx(),
@@ -3309,7 +3436,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ));
                     for (i, trait_info) in trait_infos.iter().enumerate() {
                         if impls_trait(trait_info.def_id) {
-                            self.suggest_valid_traits(err, vec![trait_info.def_id], false);
+                            self.suggest_valid_traits(
+                                err,
+                                item_name,
+                                vec![trait_info.def_id],
+                                false,
+                            );
                         }
                         msg.push_str(&format!(
                             "\ncandidate #{}: `{}`",
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 92ec1a83bee..1910841f268 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2929,7 +2929,7 @@ define_print_and_forward_display! {
 
     ty::ExistentialTraitRef<'tcx> {
         // Use a type that can't appear in defaults of type parameters.
-        let dummy_self = Ty::new_fresh(cx.tcx(),0);
+        let dummy_self = Ty::new_fresh(cx.tcx(), 0);
         let trait_ref = self.with_self_ty(cx.tcx(), dummy_self);
         p!(print(trait_ref.print_only_trait_path()))
     }
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index c89a3806280..83b2678f7f5 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -607,6 +607,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
     /// occurs when capacity is exhausted and needs a resize. The resize cost
     /// has been amortized in the previous figures.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("append", "put")]
     pub fn push(&mut self, item: T) {
         let old_len = self.len();
         self.data.push(item);
@@ -1264,6 +1265,7 @@ impl<T, A: Allocator> BinaryHeap<T, A> {
     /// ```
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("length", "size")]
     pub fn len(&self) -> usize {
         self.data.len()
     }
diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs
index addcc71a2d4..80be4ee57c5 100644
--- a/library/alloc/src/collections/btree/map.rs
+++ b/library/alloc/src/collections/btree/map.rs
@@ -979,6 +979,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
     /// assert_eq!(map[&37], "c");
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "put", "set")]
     pub fn insert(&mut self, key: K, value: V) -> Option<V>
     where
         K: Ord,
@@ -1041,6 +1042,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
     /// assert_eq!(map.remove(&1), None);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V>
     where
         K: Borrow<Q> + Ord,
@@ -2495,6 +2497,7 @@ impl<K, V, A: Allocator + Clone> BTreeMap<K, V, A> {
         issue = "71835",
         implied_by = "const_btree_new"
     )]
+    #[rustc_confusables("length", "size")]
     pub const fn len(&self) -> usize {
         self.length
     }
diff --git a/library/alloc/src/collections/btree/map/entry.rs b/library/alloc/src/collections/btree/map/entry.rs
index e9366eec9ce..0a894258f46 100644
--- a/library/alloc/src/collections/btree/map/entry.rs
+++ b/library/alloc/src/collections/btree/map/entry.rs
@@ -347,6 +347,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> {
     /// assert_eq!(map["poneyland"], 37);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "put")]
     pub fn insert(mut self, value: V) -> &'a mut V {
         let out_ptr = match self.handle {
             None => {
@@ -524,6 +525,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> {
     /// assert_eq!(map["poneyland"], 15);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "put")]
     pub fn insert(&mut self, value: V) -> V {
         mem::replace(self.get_mut(), value)
     }
@@ -546,6 +548,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> {
     /// // println!("{}", map["poneyland"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove(self) -> V {
         self.remove_kv().1
     }
diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs
index 0e03551286e..ed91ae1a66e 100644
--- a/library/alloc/src/collections/btree/set.rs
+++ b/library/alloc/src/collections/btree/set.rs
@@ -790,6 +790,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     /// ```
     #[must_use]
     #[stable(feature = "map_first_last", since = "1.66.0")]
+    #[rustc_confusables("front")]
     pub fn first(&self) -> Option<&T>
     where
         T: Ord,
@@ -816,6 +817,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     /// ```
     #[must_use]
     #[stable(feature = "map_first_last", since = "1.66.0")]
+    #[rustc_confusables("back")]
     pub fn last(&self) -> Option<&T>
     where
         T: Ord,
@@ -896,6 +898,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     /// assert_eq!(set.len(), 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "put")]
     pub fn insert(&mut self, value: T) -> bool
     where
         T: Ord,
@@ -919,6 +922,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
     /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10);
     /// ```
     #[stable(feature = "set_recovery", since = "1.9.0")]
+    #[rustc_confusables("swap")]
     pub fn replace(&mut self, value: T) -> Option<T>
     where
         T: Ord,
@@ -1152,6 +1156,7 @@ impl<T, A: Allocator + Clone> BTreeSet<T, A> {
         issue = "71835",
         implied_by = "const_btree_new"
     )]
+    #[rustc_confusables("length", "size")]
     pub const fn len(&self) -> usize {
         self.map.len()
     }
diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs
index 9e109feb3d3..6dfb82ac807 100644
--- a/library/alloc/src/collections/linked_list.rs
+++ b/library/alloc/src/collections/linked_list.rs
@@ -656,6 +656,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("length", "size")]
     pub fn len(&self) -> usize {
         self.len
     }
@@ -740,6 +741,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("first")]
     pub fn front(&self) -> Option<&T> {
         unsafe { self.head.as_ref().map(|node| &node.as_ref().element) }
     }
@@ -890,6 +892,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
     /// assert_eq!(3, *d.back().unwrap());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "append")]
     pub fn push_back(&mut self, elt: T) {
         let node = Box::new_in(Node::new(elt), &self.alloc);
         let node_ptr = NonNull::from(Box::leak(node));
@@ -1004,6 +1007,7 @@ impl<T, A: Allocator> LinkedList<T, A> {
     /// assert_eq!(d.remove(0), 1);
     /// ```
     #[unstable(feature = "linked_list_remove", issue = "69210")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove(&mut self, at: usize) -> T {
         let len = self.len();
         assert!(at < len, "Cannot remove at an index outside of the list bounds");
@@ -1478,6 +1482,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {
     /// or None if the list is empty.
     #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    #[rustc_confusables("first")]
     pub fn front(&self) -> Option<&'a T> {
         self.list.front()
     }
@@ -1486,6 +1491,7 @@ impl<'a, T, A: Allocator> Cursor<'a, T, A> {
     /// or None if the list is empty.
     #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    #[rustc_confusables("last")]
     pub fn back(&self) -> Option<&'a T> {
         self.list.back()
     }
@@ -1788,6 +1794,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
     ///
     /// This operation should compute in *O*(1) time.
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    #[rustc_confusables("push", "append")]
     pub fn push_back(&mut self, elt: T) {
         // Safety: We know that `push_back` does not change the position in
         // memory of other nodes. This ensures that `self.current` remains
@@ -1834,6 +1841,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
     ///
     /// This operation should compute in *O*(1) time.
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    #[rustc_confusables("pop")]
     pub fn pop_back(&mut self) -> Option<T> {
         if self.list.is_empty() {
             None
@@ -1854,6 +1862,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
     /// or None if the list is empty.
     #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    #[rustc_confusables("first")]
     pub fn front(&self) -> Option<&T> {
         self.list.front()
     }
@@ -1870,6 +1879,7 @@ impl<'a, T, A: Allocator> CursorMut<'a, T, A> {
     /// or None if the list is empty.
     #[must_use]
     #[unstable(feature = "linked_list_cursors", issue = "58533")]
+    #[rustc_confusables("last")]
     pub fn back(&self) -> Option<&T> {
         self.list.back()
     }
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index bcba6525fda..c35bab5ef66 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -1209,6 +1209,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(deque.len(), 1);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("length", "size")]
     pub fn len(&self) -> usize {
         self.len
     }
@@ -1491,6 +1492,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(d.front(), Some(&1));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("first")]
     pub fn front(&self) -> Option<&T> {
         self.get(0)
     }
@@ -1535,6 +1537,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(d.back(), Some(&2));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("last")]
     pub fn back(&self) -> Option<&T> {
         self.get(self.len.wrapping_sub(1))
     }
@@ -1654,6 +1657,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(3, *buf.back().unwrap());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "put", "append")]
     pub fn push_back(&mut self, value: T) {
         if self.is_full() {
             self.grow();
@@ -1813,6 +1817,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// assert_eq!(buf, [1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove(&mut self, index: usize) -> Option<T> {
         if self.len <= index {
             return None;
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 4d6968157de..6dadbc8e364 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1049,6 +1049,7 @@ impl String {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("append", "push")]
     pub fn push_str(&mut self, string: &str) {
         self.vec.extend_from_slice(string.as_bytes())
     }
@@ -1445,6 +1446,7 @@ impl String {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove(&mut self, idx: usize) -> char {
         let ch = match self[idx..].chars().next() {
             Some(ch) => ch,
@@ -1639,6 +1641,7 @@ impl String {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("set")]
     pub fn insert(&mut self, idx: usize, ch: char) {
         assert!(self.is_char_boundary(idx));
         let mut bits = [0; 4];
@@ -1738,6 +1741,7 @@ impl String {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("length", "size")]
     pub fn len(&self) -> usize {
         self.vec.len()
     }
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 08e3cdedc66..b59699219eb 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -1554,6 +1554,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[track_caller]
+    #[rustc_confusables("delete", "take")]
     pub fn remove(&mut self, index: usize) -> T {
         #[cold]
         #[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))]
@@ -1915,6 +1916,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push_back", "put", "append")]
     pub fn push(&mut self, value: T) {
         // This will panic or abort if we would allocate > isize::MAX bytes
         // or if the length increment would overflow for zero-sized types.
@@ -2141,6 +2143,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("length", "size")]
     pub fn len(&self) -> usize {
         self.len
     }
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index c77fa371cc7..19b05448c87 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -471,6 +471,7 @@ impl<T> Cell<T> {
     /// ```
     #[inline]
     #[stable(feature = "move_cell", since = "1.17.0")]
+    #[rustc_confusables("swap")]
     pub fn replace(&self, val: T) -> T {
         // SAFETY: This can cause data races if called from a separate thread,
         // but `Cell` is `!Sync` so this won't happen.
@@ -862,6 +863,7 @@ impl<T> RefCell<T> {
     #[inline]
     #[stable(feature = "refcell_replace", since = "1.24.0")]
     #[track_caller]
+    #[rustc_confusables("swap")]
     pub fn replace(&self, t: T) -> T {
         mem::replace(&mut *self.borrow_mut(), t)
     }
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index 0e5eb03239c..53c9ae498c0 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -1403,6 +1403,7 @@ impl<T> Option<T> {
     #[doc(alias = "flatmap")]
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("flat_map", "flatmap")]
     pub fn and_then<U, F>(self, f: F) -> Option<U>
     where
         F: FnOnce(T) -> Option<U>,
diff --git a/library/core/src/result.rs b/library/core/src/result.rs
index 80f7fe75e82..6879ac03f70 100644
--- a/library/core/src/result.rs
+++ b/library/core/src/result.rs
@@ -1315,6 +1315,7 @@ impl<T, E> Result<T, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("flat_map", "flatmap")]
     pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
         match self {
             Ok(t) => op(t),
diff --git a/library/proc_macro/src/bridge/scoped_cell.rs b/library/proc_macro/src/bridge/scoped_cell.rs
index 53eae1ebdb0..a8b34143908 100644
--- a/library/proc_macro/src/bridge/scoped_cell.rs
+++ b/library/proc_macro/src/bridge/scoped_cell.rs
@@ -25,6 +25,7 @@ impl<T: LambdaL> ScopedCell<T> {
     /// running `f`, which gets the old value, mutably.
     /// The old value will be restored after `f` exits, even
     /// by panic, including modifications made to it by `f`.
+    #[rustc_confusables("swap")]
     pub fn replace<'a, R>(
         &self,
         replacement: <T as ApplyL<'a>>::Out,
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index 0d4c1fa05cc..627befb63a1 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -1101,6 +1101,7 @@ where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "append")]
     pub fn insert(&mut self, k: K, v: V) -> Option<V> {
         self.base.insert(k, v)
     }
@@ -1155,6 +1156,7 @@ where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove<Q: ?Sized>(&mut self, k: &Q) -> Option<V>
     where
         K: Borrow<Q>,
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index dcb2fa0f771..371201ff44c 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -885,6 +885,7 @@ where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("push", "append")]
     pub fn insert(&mut self, value: T) -> bool {
         self.base.insert(value)
     }
@@ -906,6 +907,7 @@ where
     /// ```
     #[inline]
     #[stable(feature = "set_recovery", since = "1.9.0")]
+    #[rustc_confusables("swap")]
     pub fn replace(&mut self, value: T) -> Option<T> {
         self.base.replace(value)
     }
@@ -930,6 +932,7 @@ where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("delete", "take")]
     pub fn remove<Q: ?Sized>(&mut self, value: &Q) -> bool
     where
         T: Borrow<Q>,
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index 28747ad8f34..bbcbbc52843 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -255,6 +255,7 @@ impl OsString {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
+    #[rustc_confusables("append", "put")]
     pub fn push<T: AsRef<OsStr>>(&mut self, s: T) {
         self.inner.push_slice(&s.as_ref().inner)
     }
diff --git a/library/std/src/path.rs b/library/std/src/path.rs
index 60562f64c90..89fbd5c4c64 100644
--- a/library/std/src/path.rs
+++ b/library/std/src/path.rs
@@ -1270,6 +1270,7 @@ impl PathBuf {
     /// assert_eq!(path, PathBuf::from("/etc"));
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_confusables("append", "put")]
     pub fn push<P: AsRef<Path>>(&mut self, path: P) {
         self._push(path.as_ref())
     }
diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs
index d1213e2f166..34d30a259ee 100644
--- a/library/std/src/thread/local.rs
+++ b/library/std/src/thread/local.rs
@@ -435,6 +435,7 @@ impl<T: 'static> LocalKey<Cell<T>> {
     /// assert_eq!(X.replace(3), 2);
     /// ```
     #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
+    #[rustc_confusables("swap")]
     pub fn replace(&'static self, value: T) -> T {
         self.with(|cell| cell.replace(value))
     }
@@ -606,6 +607,7 @@ impl<T: 'static> LocalKey<RefCell<T>> {
     /// X.with_borrow(|v| assert_eq!(*v, vec![1, 2, 3]));
     /// ```
     #[stable(feature = "local_key_cell_methods", since = "1.73.0")]
+    #[rustc_confusables("swap")]
     pub fn replace(&'static self, value: T) -> T {
         self.with(|cell| cell.replace(value))
     }
diff --git a/tests/ui/associated-item/associated-item-enum.stderr b/tests/ui/associated-item/associated-item-enum.stderr
index ebf3c5499a6..3b00588f1d1 100644
--- a/tests/ui/associated-item/associated-item-enum.stderr
+++ b/tests/ui/associated-item/associated-item-enum.stderr
@@ -5,10 +5,12 @@ LL | enum Enum { Variant }
    | --------- variant or associated item `mispellable` not found for this enum
 ...
 LL |     Enum::mispellable();
-   |           ^^^^^^^^^^^
-   |           |
-   |           variant or associated item not found in `Enum`
-   |           help: there is an associated function with a similar name: `misspellable`
+   |           ^^^^^^^^^^^ variant or associated item not found in `Enum`
+   |
+help: there is an associated function `misspellable` with a similar name
+   |
+LL |     Enum::misspellable();
+   |           ~~~~~~~~~~~~
 
 error[E0599]: no variant or associated item named `mispellable_trait` found for enum `Enum` in the current scope
   --> $DIR/associated-item-enum.rs:18:11
@@ -17,10 +19,12 @@ LL | enum Enum { Variant }
    | --------- variant or associated item `mispellable_trait` not found for this enum
 ...
 LL |     Enum::mispellable_trait();
-   |           ^^^^^^^^^^^^^^^^^
-   |           |
-   |           variant or associated item not found in `Enum`
-   |           help: there is an associated function with a similar name: `misspellable`
+   |           ^^^^^^^^^^^^^^^^^ variant or associated item not found in `Enum`
+   |
+help: there is an associated function `misspellable_trait` with a similar name
+   |
+LL |     Enum::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
@@ -29,10 +33,12 @@ LL | enum Enum { Variant }
    | --------- variant or associated item `MISPELLABLE` not found for this enum
 ...
 LL |     Enum::MISPELLABLE;
-   |           ^^^^^^^^^^^
-   |           |
-   |           variant or associated item not found in `Enum`
-   |           help: there is an associated constant with a similar name: `MISSPELLABLE`
+   |           ^^^^^^^^^^^ variant or associated item not found in `Enum`
+   |
+help: there is an associated constant `MISSPELLABLE` with a similar name
+   |
+LL |     Enum::MISSPELLABLE;
+   |           ~~~~~~~~~~~~
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
index b7336485eb8..3d82f572a1a 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -30,7 +30,7 @@ LL |         match fut.as_mut().poll(ctx) {
    = note: the method is available for `Pin<&mut impl Future<Output = ()>>` here
    |
    = 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:
+help: trait `Future` which provides `poll` is implemented but not in scope; perhaps you want to import it
    |
 LL + use std::future::Future;
    |
diff --git a/tests/ui/atomic-from-mut-not-available.stderr b/tests/ui/atomic-from-mut-not-available.stderr
index a3edf189356..a4514524f48 100644
--- a/tests/ui/atomic-from-mut-not-available.stderr
+++ b/tests/ui/atomic-from-mut-not-available.stderr
@@ -7,6 +7,10 @@ LL |     core::sync::atomic::AtomicU64::from_mut(&mut 0u64);
 note: if you're trying to build a new `AtomicU64`, consider using `AtomicU64::new` which returns `AtomicU64`
   --> $SRC_DIR/core/src/sync/atomic.rs:LL:COL
    = note: this error originates in the macro `atomic_int` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: there is an associated function `from` with a similar name
+   |
+LL |     core::sync::atomic::AtomicU64::from(&mut 0u64);
+   |                                    ~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/attributes/rustc_confusables.rs b/tests/ui/attributes/rustc_confusables.rs
index a88432ead75..93d9a7d572c 100644
--- a/tests/ui/attributes/rustc_confusables.rs
+++ b/tests/ui/attributes/rustc_confusables.rs
@@ -11,7 +11,7 @@ fn main() {
     let x = BTreeSet {};
     x.inser();
     //~^ ERROR no method named
-    //~| HELP there is a method with a similar name
+    //~| HELP there is a method `insert` with a similar name
     x.foo();
     //~^ ERROR no method named
     x.push();
@@ -21,7 +21,7 @@ fn main() {
     //~^ ERROR no method named
     x.pulled();
     //~^ ERROR no method named
-    //~| HELP there is a method with a similar name
+    //~| HELP you might have meant to use `pull`
 }
 
 struct Bar;
diff --git a/tests/ui/attributes/rustc_confusables.stderr b/tests/ui/attributes/rustc_confusables.stderr
index 9fd4470cdbb..9e37d5f5083 100644
--- a/tests/ui/attributes/rustc_confusables.stderr
+++ b/tests/ui/attributes/rustc_confusables.stderr
@@ -31,7 +31,12 @@ error[E0599]: no method named `inser` found for struct `rustc_confusables_across
   --> $DIR/rustc_confusables.rs:12:7
    |
 LL |     x.inser();
-   |       ^^^^^ help: there is a method with a similar name: `insert`
+   |       ^^^^^
+   |
+help: there is a method `insert` with a similar name
+   |
+LL |     x.insert();
+   |       ~~~~~~
 
 error[E0599]: no method named `foo` found for struct `rustc_confusables_across_crate::BTreeSet` in the current scope
   --> $DIR/rustc_confusables.rs:15:7
@@ -60,7 +65,12 @@ error[E0599]: no method named `pulled` found for struct `rustc_confusables_acros
   --> $DIR/rustc_confusables.rs:22:7
    |
 LL |     x.pulled();
-   |       ^^^^^^ help: there is a method with a similar name: `pull`
+   |       ^^^^^^
+   |
+help: you might have meant to use `pull`
+   |
+LL |     x.pull();
+   |       ~~~~
 
 error: aborting due to 9 previous errors
 
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.rs b/tests/ui/attributes/rustc_confusables_std_cases.rs
new file mode 100644
index 00000000000..d9121695950
--- /dev/null
+++ b/tests/ui/attributes/rustc_confusables_std_cases.rs
@@ -0,0 +1,26 @@
+use std::collections::BTreeSet;
+use std::collections::VecDeque;
+
+fn main() {
+    let mut x = BTreeSet::new();
+    x.push(1); //~ ERROR E0599
+    //~^ HELP you might have meant to use `insert`
+    let mut x = Vec::new();
+    x.push_back(1); //~ ERROR E0599
+    //~^ HELP you might have meant to use `push`
+    let mut x = VecDeque::new();
+    x.push(1); //~ ERROR E0599
+    //~^ HELP you might have meant to use `push_back`
+    let mut x = vec![1, 2, 3];
+    x.length(); //~ ERROR E0599
+    //~^ 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 `resize` with a similar name
+    x.append(42); //~ ERROR E0308
+    //~^ HELP you might have meant to use `push`
+    String::new().push(""); //~ ERROR E0308
+    //~^ HELP you might have meant to use `push_str`
+    String::new().append(""); //~ ERROR E0599
+    //~^ HELP you might have meant to use `push_str`
+}
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr
new file mode 100644
index 00000000000..45d571f435c
--- /dev/null
+++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr
@@ -0,0 +1,104 @@
+error[E0599]: no method named `push` found for struct `BTreeSet` in the current scope
+  --> $DIR/rustc_confusables_std_cases.rs:6:7
+   |
+LL |     x.push(1);
+   |       ^^^^ method not found in `BTreeSet<_>`
+   |
+help: you might have meant to use `insert`
+   |
+LL |     x.insert(1);
+   |       ~~~~~~
+
+error[E0599]: no method named `push_back` found for struct `Vec<_>` in the current scope
+  --> $DIR/rustc_confusables_std_cases.rs:9:7
+   |
+LL |     x.push_back(1);
+   |       ^^^^^^^^^ method not found in `Vec<_>`
+   |
+help: you might have meant to use `push`
+   |
+LL |     x.push(1);
+   |       ~~~~
+
+error[E0599]: no method named `push` found for struct `VecDeque` in the current scope
+  --> $DIR/rustc_confusables_std_cases.rs:12:7
+   |
+LL |     x.push(1);
+   |       ^^^^ method not found in `VecDeque<_>`
+   |
+help: you might have meant to use `push_back`
+   |
+LL |     x.push_back(1);
+   |       ~~~~~~~~~
+
+error[E0599]: no method named `length` found for struct `Vec<{integer}>` in the current scope
+  --> $DIR/rustc_confusables_std_cases.rs:15:7
+   |
+LL |     x.length();
+   |       ^^^^^^
+   |
+help: you might have meant to use `len`
+   |
+LL |     x.len();
+   |       ~~~
+
+error[E0599]: no method named `size` found for struct `Vec<{integer}>` in the current scope
+  --> $DIR/rustc_confusables_std_cases.rs:17:7
+   |
+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();
+   |       ~~~
+
+error[E0308]: mismatched types
+  --> $DIR/rustc_confusables_std_cases.rs:20:14
+   |
+LL |     x.append(42);
+   |       ------ ^^ expected `&mut Vec<{integer}>`, found integer
+   |       |
+   |       arguments to this method are incorrect
+   |
+   = note: expected mutable reference `&mut Vec<{integer}>`
+                           found type `{integer}`
+note: method defined here
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+help: you might have meant to use `push`
+   |
+LL |     x.push(42);
+   |       ~~~~
+
+error[E0308]: mismatched types
+  --> $DIR/rustc_confusables_std_cases.rs:22:24
+   |
+LL |     String::new().push("");
+   |                   ---- ^^ expected `char`, found `&str`
+   |                   |
+   |                   arguments to this method are incorrect
+   |
+note: method defined here
+  --> $SRC_DIR/alloc/src/string.rs:LL:COL
+help: you might have meant to use `push_str`
+   |
+LL |     String::new().push_str("");
+   |                   ~~~~~~~~
+
+error[E0599]: no method named `append` found for struct `String` in the current scope
+  --> $DIR/rustc_confusables_std_cases.rs:24:19
+   |
+LL |     String::new().append("");
+   |                   ^^^^^^ method not found in `String`
+   |
+help: you might have meant to use `push_str`
+   |
+LL |     String::new().push_str("");
+   |                   ~~~~~~~~
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0599.
+For more information about an error, try `rustc --explain E0308`.
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/block-result/issue-3563.stderr b/tests/ui/block-result/issue-3563.stderr
index c473a84413e..22606a52f85 100644
--- a/tests/ui/block-result/issue-3563.stderr
+++ b/tests/ui/block-result/issue-3563.stderr
@@ -2,7 +2,12 @@ error[E0599]: no method named `b` found for reference `&Self` in the current sco
   --> $DIR/issue-3563.rs:3:17
    |
 LL |         || self.b()
-   |                 ^ help: there is a method with a similar name: `a`
+   |                 ^
+   |
+help: there is a method `a` with a similar name
+   |
+LL |         || self.a()
+   |                 ~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence_inherent.stderr b/tests/ui/coherence/coherence_inherent.stderr
index da8c03847ed..17b49279de7 100644
--- a/tests/ui/coherence/coherence_inherent.stderr
+++ b/tests/ui/coherence/coherence_inherent.stderr
@@ -5,7 +5,7 @@ LL |         s.the_fn();
    |           ^^^^^^ method not found in `&TheStruct`
    |
    = 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:
+help: trait `TheTrait` which provides `the_fn` is implemented but not in scope; perhaps you want to import it
    |
 LL +     use Lib::TheTrait;
    |
diff --git a/tests/ui/coherence/coherence_inherent_cc.stderr b/tests/ui/coherence/coherence_inherent_cc.stderr
index d34f6fa213b..b3c1125d63e 100644
--- a/tests/ui/coherence/coherence_inherent_cc.stderr
+++ b/tests/ui/coherence/coherence_inherent_cc.stderr
@@ -5,7 +5,7 @@ LL |         s.the_fn();
    |           ^^^^^^ method not found in `&TheStruct`
    |
    = 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:
+help: trait `TheTrait` which provides `the_fn` is implemented but not in scope; perhaps you want to import it
    |
 LL +     use coherence_inherent_cc_lib::TheTrait;
    |
diff --git a/tests/ui/confuse-field-and-method/issue-33784.stderr b/tests/ui/confuse-field-and-method/issue-33784.stderr
index aaf953a66d5..8acd1f8ff1e 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 `clone` 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..5de6e3db327 100644
--- a/tests/ui/hygiene/no_implicit_prelude.stderr
+++ b/tests/ui/hygiene/no_implicit_prelude.stderr
@@ -20,11 +20,13 @@ 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:
+help: trait `Clone` which provides `clone` is implemented but not in scope; perhaps you want to import it
    |
 LL +     use std::clone::Clone;
    |
diff --git a/tests/ui/hygiene/trait_items.stderr b/tests/ui/hygiene/trait_items.stderr
index 016ee8f71f9..0e276bf69d6 100644
--- a/tests/ui/hygiene/trait_items.stderr
+++ b/tests/ui/hygiene/trait_items.stderr
@@ -12,7 +12,7 @@ LL |     pub macro m() { ().f() }
    |
    = help: items from traits can only be used if the trait is in scope
    = note: this error originates in the macro `::baz::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:
+help: trait `T` which provides `f` is implemented but not in scope; perhaps you want to import it
    |
 LL +     use foo::T;
    |
diff --git a/tests/ui/impl-trait/no-method-suggested-traits.stderr b/tests/ui/impl-trait/no-method-suggested-traits.stderr
index 160cc044078..7a4dc366618 100644
--- a/tests/ui/impl-trait/no-method-suggested-traits.stderr
+++ b/tests/ui/impl-trait/no-method-suggested-traits.stderr
@@ -2,10 +2,10 @@ 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:
+help: the following traits which provide `method` are implemented but not in scope; perhaps you want to import one of them
    |
 LL + use foo::Bar;
    |
@@ -15,15 +15,19 @@ LL + use no_method_suggested_traits::foo::PubPub;
    |
 LL + use no_method_suggested_traits::qux::PrivPub;
    |
+help: there is a method `method2` 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:
+help: the following traits which provide `method` are implemented but not in scope; perhaps you want to import one of them
    |
 LL + use foo::Bar;
    |
@@ -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 `method2` 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:
+help: trait `Bar` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use foo::Bar;
    |
+help: there is a method `method2` 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:
+help: trait `Bar` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use foo::Bar;
    |
+help: there is a method `method2` 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
    |
@@ -73,22 +89,30 @@ LL |         fn method(&self) {}
    |            ------ the method is available for `i32` here
    |
    = 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:
+help: trait `PubPub` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use no_method_suggested_traits::foo::PubPub;
    |
+help: there is a method `method3` 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:
+help: trait `PubPub` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use no_method_suggested_traits::foo::PubPub;
    |
+help: there is a method `method3` 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/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index f203f4cabc8..c4bdd484fdb 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -395,6 +395,8 @@ error[E0599]: no function or associated item named `into_vec` found for slice `[
 LL |     vec![vec![0; 10], vec![12; 7], vec![8; 3]]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function or associated item not found in `[_]`
    |
+help: there is an associated function `to_vec` with a similar name
+  --> $SRC_DIR/alloc/src/slice.rs:LL:COL
    = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0053]: method `in_trait_impl_return` has an incompatible type for trait
diff --git a/tests/ui/imports/overlapping_pub_trait.rs b/tests/ui/imports/overlapping_pub_trait.rs
index cde9f7d8edb..9a56b96adbf 100644
--- a/tests/ui/imports/overlapping_pub_trait.rs
+++ b/tests/ui/imports/overlapping_pub_trait.rs
@@ -4,7 +4,7 @@
  * This crate declares two public paths, `m::Tr` and `prelude::_`. Make sure we prefer the former.
  */
 extern crate overlapping_pub_trait_source;
-//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
+//~^ HELP trait `Tr` which provides `method` is implemented but not in scope; perhaps you want to import it
 //~| SUGGESTION overlapping_pub_trait_source::m::Tr
 
 fn main() {
diff --git a/tests/ui/imports/overlapping_pub_trait.stderr b/tests/ui/imports/overlapping_pub_trait.stderr
index a82a4101ce0..51a8bec85b7 100644
--- a/tests/ui/imports/overlapping_pub_trait.stderr
+++ b/tests/ui/imports/overlapping_pub_trait.stderr
@@ -10,7 +10,7 @@ LL |     pub trait Tr { fn method(&self); }
    |                       ------ the method is available for `S` here
    |
    = 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:
+help: trait `Tr` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use overlapping_pub_trait_source::m::Tr;
    |
diff --git a/tests/ui/imports/unnamed_pub_trait.rs b/tests/ui/imports/unnamed_pub_trait.rs
index 09a01643c5e..1527dfef147 100644
--- a/tests/ui/imports/unnamed_pub_trait.rs
+++ b/tests/ui/imports/unnamed_pub_trait.rs
@@ -5,7 +5,7 @@
  * importing it by name, and instead we suggest importing it by glob.
  */
 extern crate unnamed_pub_trait_source;
-//~^ HELP the following trait is implemented but not in scope; perhaps add a `use` for it:
+//~^ HELP trait `Tr` which provides `method` is implemented but not in scope; perhaps you want to import it
 //~| SUGGESTION unnamed_pub_trait_source::prelude::*; // trait Tr
 
 fn main() {
diff --git a/tests/ui/imports/unnamed_pub_trait.stderr b/tests/ui/imports/unnamed_pub_trait.stderr
index 41772b8e694..7d6b7742981 100644
--- a/tests/ui/imports/unnamed_pub_trait.stderr
+++ b/tests/ui/imports/unnamed_pub_trait.stderr
@@ -10,7 +10,7 @@ LL |     pub trait Tr { fn method(&self); }
    |                       ------ the method is available for `S` here
    |
    = 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:
+help: trait `Tr` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use unnamed_pub_trait_source::prelude::*; // trait Tr
    |
diff --git a/tests/ui/issues/issue-10465.stderr b/tests/ui/issues/issue-10465.stderr
index c6bc0786af1..0f46ebe505a 100644
--- a/tests/ui/issues/issue-10465.stderr
+++ b/tests/ui/issues/issue-10465.stderr
@@ -5,7 +5,7 @@ LL |             b.foo();
    |               ^^^ method not found in `&B`
    |
    = 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:
+help: trait `A` which provides `foo` is implemented but not in scope; perhaps you want to import it
    |
 LL +         use a::A;
    |
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..bbe8badb652 100644
--- a/tests/ui/issues/issue-39175.stderr
+++ b/tests/ui/issues/issue-39175.stderr
@@ -2,10 +2,12 @@ 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: the following trait is implemented but not in scope; perhaps add a `use` for it:
+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: trait `CommandExt` which provides `exec` is implemented but not in scope; perhaps you want to import 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..6ed35c3a3d3 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
    |
@@ -10,16 +10,20 @@ LL |         fn trait_method(&self) {
    |            ------------ the method is available for `FooStruct` here
    |
    = 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:
+help: trait `Trait` which provides `trait_method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use reexported_trait::Trait;
    |
+help: there is a method `trait_method_b` 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
    |
@@ -27,10 +31,14 @@ LL |         fn trait_method_b(&self) {
    |            -------------- the method is available for `FooStruct` here
    |
    = 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:
+help: trait `TraitB` which provides `trait_method_b` is implemented but not in scope; perhaps you want to import it
    |
 LL + use reexported_trait::TraitBRename;
    |
+help: there is a method `trait_method` with a similar name
+   |
+LL |     reexported_trait::FooStruct.trait_method();
+   |                                 ~~~~~~~~~~~~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/methods/issues/issue-105732.stderr b/tests/ui/methods/issues/issue-105732.stderr
index 19ccd2de685..a4924b3e663 100644
--- a/tests/ui/methods/issues/issue-105732.stderr
+++ b/tests/ui/methods/issues/issue-105732.stderr
@@ -10,7 +10,12 @@ error[E0599]: no method named `g` found for reference `&Self` in the current sco
   --> $DIR/issue-105732.rs:10:14
    |
 LL |         self.g();
-   |              ^ help: there is a method with a similar name: `f`
+   |              ^
+   |
+help: there is a method `f` with a similar name
+   |
+LL |         self.f();
+   |              ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/methods/method-not-found-but-doc-alias.stderr b/tests/ui/methods/method-not-found-but-doc-alias.stderr
index 9746c404013..c49ffa8971f 100644
--- a/tests/ui/methods/method-not-found-but-doc-alias.stderr
+++ b/tests/ui/methods/method-not-found-but-doc-alias.stderr
@@ -5,7 +5,12 @@ LL | struct Foo;
    | ---------- method `quux` not found for this struct
 ...
 LL |     Foo.quux();
-   |         ^^^^ help: there is a method with a similar name: `bar`
+   |         ^^^^
+   |
+help: there is a method `bar` with a similar name
+   |
+LL |     Foo.bar();
+   |         ~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/object-pointer-types.stderr b/tests/ui/object-pointer-types.stderr
index 2c8df3b616f..7d915ebdab6 100644
--- a/tests/ui/object-pointer-types.stderr
+++ b/tests/ui/object-pointer-types.stderr
@@ -5,7 +5,12 @@ 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 `to_owned` with a similar name
+   |
+LL |     x.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/parser/emoji-identifiers.stderr b/tests/ui/parser/emoji-identifiers.stderr
index 1fc561d32c6..536afc53f0c 100644
--- a/tests/ui/parser/emoji-identifiers.stderr
+++ b/tests/ui/parser/emoji-identifiers.stderr
@@ -71,16 +71,17 @@ LL | struct πŸ‘€;
    | --------- function or associated item `full_of✨` not found for this struct
 ...
 LL |     πŸ‘€::full_of✨()
-   |         ^^^^^^^^^
-   |         |
-   |         function or associated item not found in `πŸ‘€`
-   |         help: there is an associated function with a similar name: `full_of_✨`
+   |         ^^^^^^^^^ function or associated item not found in `πŸ‘€`
    |
 note: if you're trying to build a new `πŸ‘€`, consider using `πŸ‘€::full_of_✨` which returns `πŸ‘€`
   --> $DIR/emoji-identifiers.rs:4:5
    |
 LL |     fn full_of_✨() -> πŸ‘€ {
    |     ^^^^^^^^^^^^^^^^^^^^^
+help: there is an associated function `full_of_✨` with a similar name
+   |
+LL |     πŸ‘€::full_of_✨()
+   |         ~~~~~~~~~~
 
 error[E0425]: cannot find function `i_like_to_πŸ˜„_a_lot` in this scope
   --> $DIR/emoji-identifiers.rs:13:13
diff --git a/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr b/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr
index 89b69e14099..f4fb7fd955f 100644
--- a/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr
+++ b/tests/ui/resolve/typo-suggestion-mistyped-in-path.stderr
@@ -14,10 +14,12 @@ LL | struct Struct;
    | ------------- function or associated item `fob` not found for this struct
 ...
 LL |     Struct::fob();
-   |             ^^^
-   |             |
-   |             function or associated item not found in `Struct`
-   |             help: there is an associated function with a similar name: `foo`
+   |             ^^^ function or associated item not found in `Struct`
+   |
+help: there is an associated function `foo` with a similar name
+   |
+LL |     Struct::foo();
+   |             ~~~
 
 error[E0433]: failed to resolve: use of undeclared type `Struc`
   --> $DIR/typo-suggestion-mistyped-in-path.rs:27:5
diff --git a/tests/ui/rust-2018/trait-import-suggestions.stderr b/tests/ui/rust-2018/trait-import-suggestions.stderr
index 325c5976e7c..85262888579 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:
+help: trait `Foobar` which provides `foobar` is implemented but not in scope; perhaps you want to import it
    |
 LL +     use crate::foo::foobar::Foobar;
    |
+help: there is a method `bar` 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,28 @@ 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:
+help: trait `Bar` which provides `bar` is implemented but not in scope; perhaps you want to import it
    |
 LL + use crate::foo::Bar;
    |
+help: there is a method `foobar` 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 `bar` with a similar name
+   |
+LL |     x.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
@@ -41,14 +54,14 @@ LL |     let y = u32::from_str("33");
    |                  ^^^^^^^^ function or associated item 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:
+help: trait `FromStr` which provides `from_str` is implemented but not in scope; perhaps you want to import it
    |
 LL + use std::str::FromStr;
    |
-help: there is an associated function with a similar name
+help: there is an associated function `from` 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-2018/uniform-paths/issue-87932.stderr b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr
index 4a874a834bb..3e6fc3ff2a5 100644
--- a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr
+++ b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr
@@ -8,7 +8,7 @@ LL |     A::deserialize();
    |        ^^^^^^^^^^^ function or associated item not found in `A`
    |
    = 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:
+help: trait `Deserialize` which provides `deserialize` is implemented but not in scope; perhaps you want to import it
    |
 LL + use <crate::A as issue_87932_a::Deserialize>::deserialize::_a::Deserialize;
    |
diff --git a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr
index d2b2e5b2fd7..d9c0fa47eca 100644
--- a/tests/ui/rust-2021/future-prelude-collision-shadow.stderr
+++ b/tests/ui/rust-2021/future-prelude-collision-shadow.stderr
@@ -2,16 +2,20 @@ 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
-help: the following traits are implemented but not in scope; perhaps add a `use` for one of them:
+help: the following traits which provide `try_into` are implemented but not in scope; perhaps you want to import one of them
    |
 LL +     use crate::m::TryIntoU32;
    |
 LL +     use std::convert::TryInto;
    |
+help: there is a method `into` with a similar name
+   |
+LL |         let _: u32 = 3u8.into().unwrap();
+   |                          ~~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/self/arbitrary_self_type_mut_difference.stderr b/tests/ui/self/arbitrary_self_type_mut_difference.stderr
index a56d58694aa..ffc61ee0d78 100644
--- a/tests/ui/self/arbitrary_self_type_mut_difference.stderr
+++ b/tests/ui/self/arbitrary_self_type_mut_difference.stderr
@@ -2,25 +2,33 @@ error[E0599]: no method named `x` found for struct `Pin<&S>` in the current scop
   --> $DIR/arbitrary_self_type_mut_difference.rs:11:18
    |
 LL |     Pin::new(&S).x();
-   |                  ^ help: there is a method with a similar name: `y`
+   |                  ^
    |
 note: method is available for `Pin<&mut S>`
   --> $DIR/arbitrary_self_type_mut_difference.rs:6:5
    |
 LL |     fn x(self: Pin<&mut Self>) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: there is a method `y` with a similar name
+   |
+LL |     Pin::new(&S).y();
+   |                  ~
 
 error[E0599]: no method named `y` found for struct `Pin<&mut S>` in the current scope
   --> $DIR/arbitrary_self_type_mut_difference.rs:12:22
    |
 LL |     Pin::new(&mut S).y();
-   |                      ^ help: there is a method with a similar name: `x`
+   |                      ^
    |
 note: method is available for `Pin<&S>`
   --> $DIR/arbitrary_self_type_mut_difference.rs:7:5
    |
 LL |     fn y(self: Pin<&Self>) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^
+help: there is a method `x` with a similar name
+   |
+LL |     Pin::new(&mut S).x();
+   |                      ~
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/shadowed/shadowed-trait-methods.stderr b/tests/ui/shadowed/shadowed-trait-methods.stderr
index 0bcf32790bc..2c990fababf 100644
--- a/tests/ui/shadowed/shadowed-trait-methods.stderr
+++ b/tests/ui/shadowed/shadowed-trait-methods.stderr
@@ -8,7 +8,7 @@ LL |     ().f()
    |        ^ method not found in `()`
    |
    = 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:
+help: trait `T` which provides `f` is implemented but not in scope; perhaps you want to import it
    |
 LL + use foo::T;
    |
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/dont-wrap-ambiguous-receivers.rs b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs
index baa2128eb8e..06aed9ac98f 100644
--- a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs
+++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.rs
@@ -1,5 +1,5 @@
 mod banana {
-    //~^ HELP the following traits are implemented but not in scope
+    //~^ HELP the following traits which provide `pick` are implemented but not in scope
     pub struct Chaenomeles;
 
     pub trait Apple {
diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr
index 974aedd13cf..41ca7d0f8ea 100644
--- a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr
+++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr
@@ -8,7 +8,7 @@ LL |     banana::Chaenomeles.pick()
    |                         ^^^^ method not found in `Chaenomeles`
    |
    = 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:
+help: the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them
    |
 LL + use banana::Apple;
    |
diff --git a/tests/ui/suggestions/import-trait-for-method-call.stderr b/tests/ui/suggestions/import-trait-for-method-call.stderr
index 3f54daf136f..58b07fe7a42 100644
--- a/tests/ui/suggestions/import-trait-for-method-call.stderr
+++ b/tests/ui/suggestions/import-trait-for-method-call.stderr
@@ -8,7 +8,7 @@ LL |     h.finish()
    = note: the method is available for `DefaultHasher` here
    |
    = 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:
+help: trait `Hasher` which provides `finish` is implemented but not in scope; perhaps you want to import it
    |
 LL + use std::hash::Hasher;
    |
diff --git a/tests/ui/suggestions/issue-109291.stderr b/tests/ui/suggestions/issue-109291.stderr
index c787be4de7c..a173bbbb490 100644
--- a/tests/ui/suggestions/issue-109291.stderr
+++ b/tests/ui/suggestions/issue-109291.stderr
@@ -2,10 +2,7 @@ error[E0599]: no function or associated item named `forced_capture` found for st
   --> $DIR/issue-109291.rs:2:65
    |
 LL |     println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capture());
-   |                                                                 ^^^^^^^^^^^^^^
-   |                                                                 |
-   |                                                                 function or associated item not found in `Backtrace`
-   |                                                                 help: there is an associated function with a similar name: `force_capture`
+   |                                                                 ^^^^^^^^^^^^^^ function or associated item not found in `Backtrace`
    |
 note: if you're trying to build a new `Backtrace` consider using one of the following associated functions:
       Backtrace::capture
@@ -13,6 +10,10 @@ note: if you're trying to build a new `Backtrace` consider using one of the foll
       Backtrace::disabled
       Backtrace::create
   --> $SRC_DIR/std/src/backtrace.rs:LL:COL
+help: there is an associated function `force_capture` with a similar name
+   |
+LL |     println!("Custom backtrace: {}", std::backtrace::Backtrace::force_capture());
+   |                                                                 ~~~~~~~~~~~~~
 
 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..5bacad8c6e8 100644
--- a/tests/ui/suggestions/suggest-methods.stderr
+++ b/tests/ui/suggestions/suggest-methods.stderr
@@ -1,29 +1,50 @@
 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`
+   |               ^^^^^^^^
+   |
+help: there is a method `is_empty` with a similar name
+   |
+LL |     let _ = s.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`
+   |                   ^^^^^^^^^
+   |
+help: there is a method `count_zeros` with a similar name
+   |
+LL |     let _ = 63u32.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`
+   |                   ^^^^^^^
+   |
+help: there is a method `count_ones` with a similar name
+   |
+LL |     let _ = 63u32.count_ones();
+   |                   ~~~~~~~~~~
 
 error: aborting due to 4 previous errors
 
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..db7c40101cd 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,17 +51,21 @@ 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
    |
    = 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
-help: the following trait is implemented but not in scope; perhaps add a `use` for it:
+help: trait `TryInto` which provides `try_into` is implemented but not in scope; perhaps you want to import it
    |
 LL + use std::convert::TryInto;
    |
+help: there is a method `into` with a similar name
+   |
+LL |     let _i: i16 = 0_i32.into().unwrap();
+   |                         ~~~~
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/suggestions/use-placement-typeck.stderr b/tests/ui/suggestions/use-placement-typeck.stderr
index d8f2d58a248..dc2bd96bb21 100644
--- a/tests/ui/suggestions/use-placement-typeck.stderr
+++ b/tests/ui/suggestions/use-placement-typeck.stderr
@@ -11,7 +11,7 @@ LL |     pub struct S;
    |     ------------ method `abc` not found for this struct
    |
    = 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:
+help: trait `Foo` which provides `abc` is implemented but not in scope; perhaps you want to import it
    |
 LL + use m::Foo;
    |
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..d08bb4745bf 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:
+help: trait `A` which provides `a` is implemented but not in scope; perhaps you want to import it
    |
 LL + use method::A;
    |
+help: there is a method `b` 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:
+help: trait `B` which provides `b` is implemented but not in scope; perhaps you want to import it
    |
 LL + use method::B;
    |
+help: there is a method `c` with a similar name
+   |
+LL |     S.c();
+   |       ~
 
 error[E0624]: method `a` is private
   --> $DIR/item-privacy.rs:72:7
@@ -50,7 +58,12 @@ LL |     S::a(&S);
    |        ^ function or associated item 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:
+help: there is an associated constant `B` with a similar name
+  --> $DIR/item-privacy.rs:29:9
+   |
+LL |         const B: u8 = 0;
+   |         ^^^^^^^^^^^
+help: trait `A` which provides `a` is implemented but not in scope; perhaps you want to import it
    |
 LL + use method::A;
    |
@@ -65,7 +78,12 @@ LL |     S::b(&S);
    |        ^ function or associated item 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:
+help: there is an associated constant `B` with a similar name
+  --> $DIR/item-privacy.rs:29:9
+   |
+LL |         const B: u8 = 0;
+   |         ^^^^^^^^^^^
+help: trait `B` which provides `b` is implemented but not in scope; perhaps you want to import it
    |
 LL + use method::B;
    |
@@ -89,10 +107,14 @@ LL |     S::A;
    |        ^ associated item 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:
+help: trait `A` which provides `A` is implemented but not in scope; perhaps you want to import it
    |
 LL + use assoc_const::A;
    |
+help: there is an associated constant `B` 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
@@ -104,10 +126,14 @@ LL |     S::B;
    |        ^ associated item 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:
+help: trait `B` which provides `B` is implemented but not in scope; perhaps you want to import it
    |
 LL + use assoc_const::B;
    |
+help: there is a method `b` with a similar name
+   |
+LL |     S::b;
+   |        ~
 
 error[E0624]: associated constant `A` is private
   --> $DIR/item-privacy.rs:101:14
diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr
index d19f0bc086b..274767331bd 100644
--- a/tests/ui/traits/method-private.stderr
+++ b/tests/ui/traits/method-private.stderr
@@ -8,7 +8,7 @@ LL |     foo.method();
    |         ^^^^^^ private method
    |
    = 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:
+help: trait `Bar` which provides `method` is implemented but not in scope; perhaps you want to import it
    |
 LL + use inner::Bar;
    |
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
index 918159e845b..0408be6986b 100644
--- a/tests/ui/traits/trait-upcasting/subtrait-method.stderr
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
@@ -2,7 +2,7 @@ error[E0599]: no method named `c` found for reference `&dyn Bar` in the current
   --> $DIR/subtrait-method.rs:55:9
    |
 LL |     bar.c();
-   |         ^ help: there is a method with a similar name: `a`
+   |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
@@ -10,12 +10,16 @@ note: `Baz` defines an item `c`, perhaps you need to implement it
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
+help: there is a method `a` with a similar name
+   |
+LL |     bar.a();
+   |         ~
 
 error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
   --> $DIR/subtrait-method.rs:59:9
    |
 LL |     foo.b();
-   |         ^ help: there is a method with a similar name: `a`
+   |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `b`, perhaps you need to implement it
@@ -23,12 +27,16 @@ note: `Bar` defines an item `b`, perhaps you need to implement it
    |
 LL | trait Bar: Foo {
    | ^^^^^^^^^^^^^^
+help: there is a method `a` with a similar name
+   |
+LL |     foo.a();
+   |         ~
 
 error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
   --> $DIR/subtrait-method.rs:61:9
    |
 LL |     foo.c();
-   |         ^ help: there is a method with a similar name: `a`
+   |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
@@ -36,12 +44,16 @@ note: `Baz` defines an item `c`, perhaps you need to implement it
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
+help: there is a method `a` with a similar name
+   |
+LL |     foo.a();
+   |         ~
 
 error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
   --> $DIR/subtrait-method.rs:65:9
    |
 LL |     foo.b();
-   |         ^ help: there is a method with a similar name: `a`
+   |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `b`, perhaps you need to implement it
@@ -49,12 +61,16 @@ note: `Bar` defines an item `b`, perhaps you need to implement it
    |
 LL | trait Bar: Foo {
    | ^^^^^^^^^^^^^^
+help: there is a method `a` with a similar name
+   |
+LL |     foo.a();
+   |         ~
 
 error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
   --> $DIR/subtrait-method.rs:67:9
    |
 LL |     foo.c();
-   |         ^ help: there is a method with a similar name: `a`
+   |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
@@ -62,6 +78,10 @@ note: `Baz` defines an item `c`, perhaps you need to implement it
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
+help: there is a method `a` with a similar name
+   |
+LL |     foo.a();
+   |         ~
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/typeck/issue-43189.stderr b/tests/ui/typeck/issue-43189.stderr
index 2e12651699d..8432cbeca2a 100644
--- a/tests/ui/typeck/issue-43189.stderr
+++ b/tests/ui/typeck/issue-43189.stderr
@@ -10,7 +10,7 @@ LL |     fn a(&self) {}
    |        - the method is available for `()` here
    |
    = 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:
+help: trait `A` which provides `a` is implemented but not in scope; perhaps you want to import it
    |
 LL + use xcrate_issue_43189_b::xcrate_issue_43189_a::A;
    |
diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr
index 7fa47c82de2..e1c5e45b3eb 100644
--- a/tests/ui/ufcs/bad-builder.stderr
+++ b/tests/ui/ufcs/bad-builder.stderr
@@ -2,10 +2,7 @@ error[E0599]: no function or associated item named `mew` found for struct `Vec<Q
   --> $DIR/bad-builder.rs:2:15
    |
 LL |     Vec::<Q>::mew()
-   |               ^^^
-   |               |
-   |               function or associated item not found in `Vec<Q>`
-   |               help: there is an associated function with a similar name: `new`
+   |               ^^^ function or associated item not found in `Vec<Q>`
    |
 note: if you're trying to build a new `Vec<Q>` consider using one of the following associated functions:
       Vec::<T>::new
@@ -14,6 +11,10 @@ note: if you're trying to build a new `Vec<Q>` consider using one of the followi
       Vec::<T, A>::new_in
       and 2 others
   --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+help: there is an associated function `new` with a similar name
+   |
+LL |     Vec::<Q>::new()
+   |               ~~~
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/underscore-imports/shadow.stderr b/tests/ui/underscore-imports/shadow.stderr
index da263163892..4743d14dfb9 100644
--- a/tests/ui/underscore-imports/shadow.stderr
+++ b/tests/ui/underscore-imports/shadow.stderr
@@ -5,7 +5,7 @@ LL |         x.deref();
    |           ^^^^^ method not found in `&()`
    |
    = 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:
+help: trait `Deref` which provides `deref` is implemented but not in scope; perhaps you want to import it
    |
 LL +     use std::ops::Deref;
    |