rustc_hir_typeck/method/
suggest.rs

1//! Give useful errors and suggestions to users when an item can't be
2//! found or is otherwise invalid.
3
4// ignore-tidy-filelength
5
6use core::ops::ControlFlow;
7use std::borrow::Cow;
8use std::path::PathBuf;
9
10use hir::Expr;
11use rustc_ast::ast::Mutability;
12use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
13use rustc_data_structures::sorted_map::SortedMap;
14use rustc_data_structures::unord::UnordSet;
15use rustc_errors::codes::*;
16use rustc_errors::{Applicability, Diag, MultiSpan, StashKey, pluralize, struct_span_code_err};
17use rustc_hir::attrs::AttributeKind;
18use rustc_hir::def::{CtorKind, DefKind, Res};
19use rustc_hir::def_id::DefId;
20use rustc_hir::intravisit::{self, Visitor};
21use rustc_hir::lang_items::LangItem;
22use rustc_hir::{
23    self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr, is_range_literal,
24};
25use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
26use rustc_middle::bug;
27use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
28use rustc_middle::ty::print::{
29    PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths,
30    with_no_visible_paths_if_doc_hidden,
31};
32use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
33use rustc_span::def_id::DefIdSet;
34use rustc_span::{
35    DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, edit_distance,
36    kw, sym,
37};
38use rustc_trait_selection::error_reporting::traits::DefIdOrName;
39use rustc_trait_selection::error_reporting::traits::on_unimplemented::OnUnimplementedNote;
40use rustc_trait_selection::infer::InferCtxtExt;
41use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
42use rustc_trait_selection::traits::{
43    FulfillmentError, Obligation, ObligationCauseCode, supertraits,
44};
45use tracing::{debug, info, instrument};
46
47use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
48use super::{CandidateSource, MethodError, NoMatchData};
49use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
50use crate::method::probe::UnsatisfiedPredicates;
51use crate::{Expectation, FnCtxt};
52
53impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
54    fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
55        self.autoderef(span, ty)
56            .silence_errors()
57            .any(|(ty, _)| matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
58    }
59
60    fn impl_into_iterator_should_be_iterator(
61        &self,
62        ty: Ty<'tcx>,
63        span: Span,
64        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
65    ) -> bool {
66        fn predicate_bounds_generic_param<'tcx>(
67            predicate: ty::Predicate<'_>,
68            generics: &'tcx ty::Generics,
69            generic_param: &ty::GenericParamDef,
70            tcx: TyCtxt<'tcx>,
71        ) -> bool {
72            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
73                predicate.kind().as_ref().skip_binder()
74            {
75                let ty::TraitPredicate { trait_ref: ty::TraitRef { args, .. }, .. } = trait_pred;
76                if args.is_empty() {
77                    return false;
78                }
79                let Some(arg_ty) = args[0].as_type() else {
80                    return false;
81                };
82                let ty::Param(param) = *arg_ty.kind() else {
83                    return false;
84                };
85                // Is `generic_param` the same as the arg for this trait predicate?
86                generic_param.index == generics.type_param(param, tcx).index
87            } else {
88                false
89            }
90        }
91
92        let is_iterator_predicate = |predicate: ty::Predicate<'tcx>| -> bool {
93            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
94                predicate.kind().as_ref().skip_binder()
95            {
96                self.tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id)
97                    // ignore unsatisfied predicates generated from trying to auto-ref ty (#127511)
98                    && trait_pred.trait_ref.self_ty() == ty
99            } else {
100                false
101            }
102        };
103
104        // Does the `ty` implement `IntoIterator`?
105        let Some(into_iterator_trait) = self.tcx.get_diagnostic_item(sym::IntoIterator) else {
106            return false;
107        };
108        let trait_ref = ty::TraitRef::new(self.tcx, into_iterator_trait, [ty]);
109        let obligation = Obligation::new(self.tcx, self.misc(span), self.param_env, trait_ref);
110        if !self.predicate_must_hold_modulo_regions(&obligation) {
111            return false;
112        }
113
114        match *ty.peel_refs().kind() {
115            ty::Param(param) => {
116                let generics = self.tcx.generics_of(self.body_id);
117                let generic_param = generics.type_param(param, self.tcx);
118                for unsatisfied in unsatisfied_predicates.iter() {
119                    // The parameter implements `IntoIterator`
120                    // but it has called a method that requires it to implement `Iterator`
121                    if predicate_bounds_generic_param(
122                        unsatisfied.0,
123                        generics,
124                        generic_param,
125                        self.tcx,
126                    ) && is_iterator_predicate(unsatisfied.0)
127                    {
128                        return true;
129                    }
130                }
131            }
132            ty::Slice(..) | ty::Adt(..) | ty::Alias(ty::Opaque, _) => {
133                for unsatisfied in unsatisfied_predicates.iter() {
134                    if is_iterator_predicate(unsatisfied.0) {
135                        return true;
136                    }
137                }
138            }
139            _ => return false,
140        }
141        false
142    }
143
144    #[instrument(level = "debug", skip(self))]
145    pub(crate) fn report_method_error(
146        &self,
147        call_id: HirId,
148        rcvr_ty: Ty<'tcx>,
149        error: MethodError<'tcx>,
150        expected: Expectation<'tcx>,
151        trait_missing_method: bool,
152    ) -> ErrorGuaranteed {
153        // NOTE: Reporting a method error should also suppress any unused trait errors,
154        // since the method error is very possibly the reason why the trait wasn't used.
155        for &import_id in
156            self.tcx.in_scope_traits(call_id).into_iter().flatten().flat_map(|c| &c.import_ids)
157        {
158            self.typeck_results.borrow_mut().used_trait_imports.insert(import_id);
159        }
160
161        let (span, expr_span, source, item_name, args) = match self.tcx.hir_node(call_id) {
162            hir::Node::Expr(&hir::Expr {
163                kind: hir::ExprKind::MethodCall(segment, rcvr, args, _),
164                span,
165                ..
166            }) => {
167                (segment.ident.span, span, SelfSource::MethodCall(rcvr), segment.ident, Some(args))
168            }
169            hir::Node::Expr(&hir::Expr {
170                kind: hir::ExprKind::Path(QPath::TypeRelative(rcvr, segment)),
171                span,
172                ..
173            })
174            | hir::Node::PatExpr(&hir::PatExpr {
175                kind: hir::PatExprKind::Path(QPath::TypeRelative(rcvr, segment)),
176                span,
177                ..
178            })
179            | hir::Node::Pat(&hir::Pat {
180                kind:
181                    hir::PatKind::Struct(QPath::TypeRelative(rcvr, segment), ..)
182                    | hir::PatKind::TupleStruct(QPath::TypeRelative(rcvr, segment), ..),
183                span,
184                ..
185            }) => {
186                let args = match self.tcx.parent_hir_node(call_id) {
187                    hir::Node::Expr(&hir::Expr {
188                        kind: hir::ExprKind::Call(callee, args), ..
189                    }) if callee.hir_id == call_id => Some(args),
190                    _ => None,
191                };
192                (segment.ident.span, span, SelfSource::QPath(rcvr), segment.ident, args)
193            }
194            node => unreachable!("{node:?}"),
195        };
196
197        // Try to get the span of the identifier within the expression's syntax context
198        // (if that's different).
199        let within_macro_span = span.within_macro(expr_span, self.tcx.sess.source_map());
200
201        // Avoid suggestions when we don't know what's going on.
202        if let Err(guar) = rcvr_ty.error_reported() {
203            return guar;
204        }
205
206        match error {
207            MethodError::NoMatch(mut no_match_data) => self.report_no_match_method_error(
208                span,
209                rcvr_ty,
210                item_name,
211                call_id,
212                source,
213                args,
214                expr_span,
215                &mut no_match_data,
216                expected,
217                trait_missing_method,
218                within_macro_span,
219            ),
220
221            MethodError::Ambiguity(mut sources) => {
222                let mut err = struct_span_code_err!(
223                    self.dcx(),
224                    item_name.span,
225                    E0034,
226                    "multiple applicable items in scope"
227                );
228                err.span_label(item_name.span, format!("multiple `{item_name}` found"));
229                if let Some(within_macro_span) = within_macro_span {
230                    err.span_label(within_macro_span, "due to this macro variable");
231                }
232
233                self.note_candidates_on_method_error(
234                    rcvr_ty,
235                    item_name,
236                    source,
237                    args,
238                    span,
239                    &mut err,
240                    &mut sources,
241                    Some(expr_span),
242                );
243                err.emit()
244            }
245
246            MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => {
247                let kind = self.tcx.def_kind_descr(kind, def_id);
248                let mut err = struct_span_code_err!(
249                    self.dcx(),
250                    item_name.span,
251                    E0624,
252                    "{} `{}` is private",
253                    kind,
254                    item_name
255                );
256                err.span_label(item_name.span, format!("private {kind}"));
257                let sp =
258                    self.tcx.hir_span_if_local(def_id).unwrap_or_else(|| self.tcx.def_span(def_id));
259                err.span_label(sp, format!("private {kind} defined here"));
260                if let Some(within_macro_span) = within_macro_span {
261                    err.span_label(within_macro_span, "due to this macro variable");
262                }
263                self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true);
264                self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name);
265                err.emit()
266            }
267
268            MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => {
269                let msg = if needs_mut {
270                    with_forced_trimmed_paths!(format!(
271                        "the `{item_name}` method cannot be invoked on `{rcvr_ty}`"
272                    ))
273                } else {
274                    format!("the `{item_name}` method cannot be invoked on a trait object")
275                };
276                let mut err = self.dcx().struct_span_err(span, msg);
277                if !needs_mut {
278                    err.span_label(bound_span, "this has a `Sized` requirement");
279                }
280                if let Some(within_macro_span) = within_macro_span {
281                    err.span_label(within_macro_span, "due to this macro variable");
282                }
283                if !candidates.is_empty() {
284                    let help = format!(
285                        "{an}other candidate{s} {were} found in the following trait{s}",
286                        an = if candidates.len() == 1 { "an" } else { "" },
287                        s = pluralize!(candidates.len()),
288                        were = pluralize!("was", candidates.len()),
289                    );
290                    self.suggest_use_candidates(
291                        candidates,
292                        |accessible_sugg, inaccessible_sugg, span| {
293                            let suggest_for_access =
294                                |err: &mut Diag<'_>, mut msg: String, sugg: Vec<_>| {
295                                    msg += &format!(
296                                        ", perhaps add a `use` for {one_of_them}:",
297                                        one_of_them =
298                                            if sugg.len() == 1 { "it" } else { "one_of_them" },
299                                    );
300                                    err.span_suggestions(
301                                        span,
302                                        msg,
303                                        sugg,
304                                        Applicability::MaybeIncorrect,
305                                    );
306                                };
307                            let suggest_for_privacy =
308                                |err: &mut Diag<'_>, mut msg: String, suggs: Vec<String>| {
309                                    if let [sugg] = suggs.as_slice() {
310                                        err.help(format!("\
311                                            trait `{}` provides `{item_name}` is implemented but not reachable",
312                                            sugg.trim(),
313                                        ));
314                                    } else {
315                                        msg += &format!(" but {} not reachable", pluralize!("is", suggs.len()));
316                                        err.span_suggestions(
317                                            span,
318                                            msg,
319                                            suggs,
320                                            Applicability::MaybeIncorrect,
321                                        );
322                                    }
323                                };
324                            if accessible_sugg.is_empty() {
325                                // `inaccessible_sugg` must not be empty
326                                suggest_for_privacy(&mut err, help, inaccessible_sugg);
327                            } else if inaccessible_sugg.is_empty() {
328                                suggest_for_access(&mut err, help, accessible_sugg);
329                            } else {
330                                suggest_for_access(&mut err, help.clone(), accessible_sugg);
331                                suggest_for_privacy(&mut err, help, inaccessible_sugg);
332                            }
333                        },
334                    );
335                }
336                if let ty::Ref(region, t_type, mutability) = rcvr_ty.kind() {
337                    if needs_mut {
338                        let trait_type =
339                            Ty::new_ref(self.tcx, *region, *t_type, mutability.invert());
340                        let msg = format!("you need `{trait_type}` instead of `{rcvr_ty}`");
341                        let mut kind = &self_expr.kind;
342                        while let hir::ExprKind::AddrOf(_, _, expr)
343                        | hir::ExprKind::Unary(hir::UnOp::Deref, expr) = kind
344                        {
345                            kind = &expr.kind;
346                        }
347                        if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = kind
348                            && let hir::def::Res::Local(hir_id) = path.res
349                            && let hir::Node::Pat(b) = self.tcx.hir_node(hir_id)
350                            && let hir::Node::Param(p) = self.tcx.parent_hir_node(b.hir_id)
351                            && let Some(decl) = self.tcx.parent_hir_node(p.hir_id).fn_decl()
352                            && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span)
353                            && let hir::TyKind::Ref(_, mut_ty) = &ty.kind
354                            && let hir::Mutability::Not = mut_ty.mutbl
355                        {
356                            err.span_suggestion_verbose(
357                                mut_ty.ty.span.shrink_to_lo(),
358                                msg,
359                                "mut ",
360                                Applicability::MachineApplicable,
361                            );
362                        } else {
363                            err.help(msg);
364                        }
365                    }
366                }
367                err.emit()
368            }
369
370            MethodError::ErrorReported(guar) => guar,
371
372            MethodError::BadReturnType => bug!("no return type expectations but got BadReturnType"),
373        }
374    }
375
376    fn create_missing_writer_err(
377        &self,
378        rcvr_ty: Ty<'tcx>,
379        rcvr_expr: &hir::Expr<'tcx>,
380        mut long_ty_path: Option<PathBuf>,
381    ) -> Diag<'_> {
382        let mut err = struct_span_code_err!(
383            self.dcx(),
384            rcvr_expr.span,
385            E0599,
386            "cannot write into `{}`",
387            self.tcx.short_string(rcvr_ty, &mut long_ty_path),
388        );
389        *err.long_ty_path() = long_ty_path;
390        err.span_note(
391            rcvr_expr.span,
392            "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
393        );
394        if let ExprKind::Lit(_) = rcvr_expr.kind {
395            err.span_help(
396                rcvr_expr.span.shrink_to_lo(),
397                "a writer is needed before this format string",
398            );
399        };
400        err
401    }
402
403    fn create_no_assoc_err(
404        &self,
405        rcvr_ty: Ty<'tcx>,
406        item_ident: Ident,
407        item_kind: &'static str,
408        trait_missing_method: bool,
409        source: SelfSource<'tcx>,
410        is_method: bool,
411        sugg_span: Span,
412        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
413    ) -> Diag<'_> {
414        // Don't show expanded generic arguments when the method can't be found in any
415        // implementation (#81576).
416        let mut ty = rcvr_ty;
417        let span = item_ident.span;
418        if let ty::Adt(def, generics) = rcvr_ty.kind() {
419            if generics.len() > 0 {
420                let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
421                let candidate_found = autoderef.any(|(ty, _)| {
422                    if let ty::Adt(adt_def, _) = ty.kind() {
423                        self.tcx
424                            .inherent_impls(adt_def.did())
425                            .into_iter()
426                            .any(|def_id| self.associated_value(*def_id, item_ident).is_some())
427                    } else {
428                        false
429                    }
430                });
431                let has_deref = autoderef.step_count() > 0;
432                if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
433                    ty = self.tcx.at(span).type_of(def.did()).instantiate_identity();
434                }
435            }
436        }
437
438        let mut err = self.dcx().create_err(NoAssociatedItem {
439            span,
440            item_kind,
441            item_ident,
442            ty_prefix: if trait_missing_method {
443                // FIXME(mu001999) E0599 maybe not suitable here because it is for types
444                Cow::from("trait")
445            } else {
446                rcvr_ty.prefix_string(self.tcx)
447            },
448            ty,
449            trait_missing_method,
450        });
451
452        if is_method {
453            self.suggest_use_shadowed_binding_with_method(source, item_ident, rcvr_ty, &mut err);
454        }
455
456        let tcx = self.tcx;
457        // Check if we wrote `Self::Assoc(1)` as if it were a tuple ctor.
458        if let SelfSource::QPath(ty) = source
459            && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind
460            && let Res::SelfTyAlias { alias_to: impl_def_id, .. } = path.res
461            && let DefKind::Impl { .. } = self.tcx.def_kind(impl_def_id)
462            && let Some(candidate) = tcx.associated_items(impl_def_id).find_by_ident_and_kind(
463                self.tcx,
464                item_ident,
465                ty::AssocTag::Type,
466                impl_def_id,
467            )
468            && let Some(adt_def) = tcx.type_of(candidate.def_id).skip_binder().ty_adt_def()
469            && adt_def.is_struct()
470            && adt_def.non_enum_variant().ctor_kind() == Some(CtorKind::Fn)
471        {
472            let def_path = tcx.def_path_str(adt_def.did());
473            err.span_suggestion(
474                sugg_span,
475                format!("to construct a value of type `{}`, use the explicit path", def_path),
476                def_path,
477                Applicability::MachineApplicable,
478            );
479        }
480
481        err
482    }
483
484    fn suggest_use_shadowed_binding_with_method(
485        &self,
486        self_source: SelfSource<'tcx>,
487        method_name: Ident,
488        ty: Ty<'tcx>,
489        err: &mut Diag<'_>,
490    ) {
491        #[derive(Debug)]
492        struct LetStmt {
493            ty_hir_id_opt: Option<hir::HirId>,
494            binding_id: hir::HirId,
495            span: Span,
496            init_hir_id: hir::HirId,
497        }
498
499        // Used for finding suggest binding.
500        // ```rust
501        // earlier binding for suggesting:
502        // let y = vec![1, 2];
503        // now binding:
504        // if let Some(y) = x {
505        //     y.push(y);
506        // }
507        // ```
508        struct LetVisitor<'a, 'tcx> {
509            // Error binding which don't have `method_name`.
510            binding_name: Symbol,
511            binding_id: hir::HirId,
512            // Used for check if the suggest binding has `method_name`.
513            fcx: &'a FnCtxt<'a, 'tcx>,
514            call_expr: &'tcx Expr<'tcx>,
515            method_name: Ident,
516            // Suggest the binding which is shallowed.
517            sugg_let: Option<LetStmt>,
518        }
519
520        impl<'a, 'tcx> LetVisitor<'a, 'tcx> {
521            // Check scope of binding.
522            fn is_sub_scope(&self, sub_id: hir::ItemLocalId, super_id: hir::ItemLocalId) -> bool {
523                let scope_tree = self.fcx.tcx.region_scope_tree(self.fcx.body_id);
524                if let Some(sub_var_scope) = scope_tree.var_scope(sub_id)
525                    && let Some(super_var_scope) = scope_tree.var_scope(super_id)
526                    && scope_tree.is_subscope_of(sub_var_scope, super_var_scope)
527                {
528                    return true;
529                }
530                false
531            }
532
533            // Check if an earlier shadowed binding make `the receiver` of a MethodCall has the method.
534            // If it does, record the earlier binding for subsequent notes.
535            fn check_and_add_sugg_binding(&mut self, binding: LetStmt) -> bool {
536                if !self.is_sub_scope(self.binding_id.local_id, binding.binding_id.local_id) {
537                    return false;
538                }
539
540                // Get the earlier shadowed binding'ty and use it to check the method.
541                if let Some(ty_hir_id) = binding.ty_hir_id_opt
542                    && let Some(tyck_ty) = self.fcx.node_ty_opt(ty_hir_id)
543                {
544                    if self
545                        .fcx
546                        .lookup_probe_for_diagnostic(
547                            self.method_name,
548                            tyck_ty,
549                            self.call_expr,
550                            ProbeScope::TraitsInScope,
551                            None,
552                        )
553                        .is_ok()
554                    {
555                        self.sugg_let = Some(binding);
556                        return true;
557                    } else {
558                        return false;
559                    }
560                }
561
562                // If the shadowed binding has an initializer expression,
563                // use the initializer expression's ty to try to find the method again.
564                // For example like:  `let mut x = Vec::new();`,
565                // `Vec::new()` is the initializer expression.
566                if let Some(self_ty) = self.fcx.node_ty_opt(binding.init_hir_id)
567                    && self
568                        .fcx
569                        .lookup_probe_for_diagnostic(
570                            self.method_name,
571                            self_ty,
572                            self.call_expr,
573                            ProbeScope::TraitsInScope,
574                            None,
575                        )
576                        .is_ok()
577                {
578                    self.sugg_let = Some(binding);
579                    return true;
580                }
581                return false;
582            }
583        }
584
585        impl<'v> Visitor<'v> for LetVisitor<'_, '_> {
586            type Result = ControlFlow<()>;
587            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
588                if let hir::StmtKind::Let(&hir::LetStmt { pat, ty, init, .. }) = ex.kind
589                    && let hir::PatKind::Binding(_, binding_id, binding_name, ..) = pat.kind
590                    && let Some(init) = init
591                    && binding_name.name == self.binding_name
592                    && binding_id != self.binding_id
593                {
594                    if self.check_and_add_sugg_binding(LetStmt {
595                        ty_hir_id_opt: ty.map(|ty| ty.hir_id),
596                        binding_id,
597                        span: pat.span,
598                        init_hir_id: init.hir_id,
599                    }) {
600                        return ControlFlow::Break(());
601                    }
602                    ControlFlow::Continue(())
603                } else {
604                    hir::intravisit::walk_stmt(self, ex)
605                }
606            }
607
608            // Used for find the error binding.
609            // When the visitor reaches this point, all the shadowed bindings
610            // have been found, so the visitor ends.
611            fn visit_pat(&mut self, p: &'v hir::Pat<'v>) -> Self::Result {
612                match p.kind {
613                    hir::PatKind::Binding(_, binding_id, binding_name, _) => {
614                        if binding_name.name == self.binding_name && binding_id == self.binding_id {
615                            return ControlFlow::Break(());
616                        }
617                    }
618                    _ => {
619                        let _ = intravisit::walk_pat(self, p);
620                    }
621                }
622                ControlFlow::Continue(())
623            }
624        }
625
626        if let SelfSource::MethodCall(rcvr) = self_source
627            && let hir::ExprKind::Path(QPath::Resolved(_, path)) = rcvr.kind
628            && let hir::def::Res::Local(recv_id) = path.res
629            && let Some(segment) = path.segments.first()
630        {
631            let body = self.tcx.hir_body_owned_by(self.body_id);
632
633            if let Node::Expr(call_expr) = self.tcx.parent_hir_node(rcvr.hir_id) {
634                let mut let_visitor = LetVisitor {
635                    fcx: self,
636                    call_expr,
637                    binding_name: segment.ident.name,
638                    binding_id: recv_id,
639                    method_name,
640                    sugg_let: None,
641                };
642                let _ = let_visitor.visit_body(&body);
643                if let Some(sugg_let) = let_visitor.sugg_let
644                    && let Some(self_ty) = self.node_ty_opt(sugg_let.init_hir_id)
645                {
646                    let _sm = self.infcx.tcx.sess.source_map();
647                    let rcvr_name = segment.ident.name;
648                    let mut span = MultiSpan::from_span(sugg_let.span);
649                    span.push_span_label(sugg_let.span,
650                            format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));
651
652                    let ty = self.tcx.short_string(ty, err.long_ty_path());
653                    span.push_span_label(
654                        self.tcx.hir_span(recv_id),
655                        format!("earlier `{rcvr_name}` shadowed here with type `{ty}`"),
656                    );
657                    err.span_note(
658                        span,
659                        format!(
660                            "there's an earlier shadowed binding `{rcvr_name}` of type `{self_ty}` \
661                             that has method `{method_name}` available"
662                        ),
663                    );
664                }
665            }
666        }
667    }
668
669    fn suggest_method_call_annotation(
670        &self,
671        err: &mut Diag<'_>,
672        span: Span,
673        rcvr_ty: Ty<'tcx>,
674        item_ident: Ident,
675        mode: Mode,
676        source: SelfSource<'tcx>,
677        expected: Expectation<'tcx>,
678    ) {
679        if let Mode::MethodCall = mode
680            && let SelfSource::MethodCall(cal) = source
681        {
682            self.suggest_await_before_method(
683                err,
684                item_ident,
685                rcvr_ty,
686                cal,
687                span,
688                expected.only_has_type(self),
689            );
690        }
691
692        self.suggest_on_pointer_type(err, source, rcvr_ty, item_ident);
693
694        if let SelfSource::MethodCall(rcvr_expr) = source {
695            self.suggest_fn_call(err, rcvr_expr, rcvr_ty, |output_ty| {
696                let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id));
697                let probe = self.lookup_probe_for_diagnostic(
698                    item_ident,
699                    output_ty,
700                    call_expr,
701                    ProbeScope::AllTraits,
702                    expected.only_has_type(self),
703                );
704                probe.is_ok()
705            });
706            self.note_internal_mutation_in_method(
707                err,
708                rcvr_expr,
709                expected.to_option(self),
710                rcvr_ty,
711            );
712        }
713    }
714
715    fn suggest_static_method_candidates(
716        &self,
717        err: &mut Diag<'_>,
718        span: Span,
719        rcvr_ty: Ty<'tcx>,
720        item_ident: Ident,
721        source: SelfSource<'tcx>,
722        args: Option<&'tcx [hir::Expr<'tcx>]>,
723        sugg_span: Span,
724        no_match_data: &NoMatchData<'tcx>,
725    ) -> Vec<CandidateSource> {
726        let mut static_candidates = no_match_data.static_candidates.clone();
727
728        // `static_candidates` may have same candidates appended by
729        // inherent and extension, which may result in incorrect
730        // diagnostic.
731        static_candidates.dedup();
732
733        if !static_candidates.is_empty() {
734            err.note(
735                "found the following associated functions; to be used as methods, \
736                 functions must have a `self` parameter",
737            );
738            err.span_label(span, "this is an associated function, not a method");
739        }
740        if static_candidates.len() == 1 {
741            self.suggest_associated_call_syntax(
742                err,
743                &static_candidates,
744                rcvr_ty,
745                source,
746                item_ident,
747                args,
748                sugg_span,
749            );
750            self.note_candidates_on_method_error(
751                rcvr_ty,
752                item_ident,
753                source,
754                args,
755                span,
756                err,
757                &mut static_candidates,
758                None,
759            );
760        } else if static_candidates.len() > 1 {
761            self.note_candidates_on_method_error(
762                rcvr_ty,
763                item_ident,
764                source,
765                args,
766                span,
767                err,
768                &mut static_candidates,
769                Some(sugg_span),
770            );
771        }
772        static_candidates
773    }
774
775    fn suggest_unsatisfied_ty_or_trait(
776        &self,
777        err: &mut Diag<'_>,
778        span: Span,
779        rcvr_ty: Ty<'tcx>,
780        item_ident: Ident,
781        item_kind: &str,
782        source: SelfSource<'tcx>,
783        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
784        static_candidates: &[CandidateSource],
785    ) -> Result<(bool, bool, bool, bool, SortedMap<Span, Vec<String>>), ()> {
786        let mut restrict_type_params = false;
787        let mut suggested_derive = false;
788        let mut unsatisfied_bounds = false;
789        let mut custom_span_label = !static_candidates.is_empty();
790        let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
791        let tcx = self.tcx;
792
793        if item_ident.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
794            let msg = "consider using `len` instead";
795            if let SelfSource::MethodCall(_expr) = source {
796                err.span_suggestion_short(span, msg, "len", Applicability::MachineApplicable);
797            } else {
798                err.span_label(span, msg);
799            }
800            if let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) {
801                let iterator_trait = self.tcx.def_path_str(iterator_trait);
802                err.note(format!(
803                    "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
804                ));
805            }
806        } else if self.impl_into_iterator_should_be_iterator(rcvr_ty, span, unsatisfied_predicates)
807        {
808            err.span_label(span, format!("`{rcvr_ty}` is not an iterator"));
809            if !span.in_external_macro(self.tcx.sess.source_map()) {
810                err.multipart_suggestion_verbose(
811                    "call `.into_iter()` first",
812                    vec![(span.shrink_to_lo(), format!("into_iter()."))],
813                    Applicability::MaybeIncorrect,
814                );
815            }
816            // Report to emit the diagnostic
817            return Err(());
818        } else if !unsatisfied_predicates.is_empty() {
819            if matches!(rcvr_ty.kind(), ty::Param(_)) {
820                // We special case the situation where we are looking for `_` in
821                // `<TypeParam as _>::method` because otherwise the machinery will look for blanket
822                // implementations that have unsatisfied trait bounds to suggest, leading us to claim
823                // things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord`
824                // have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so
825                // that `impl<T: FnPtr> Ord for T` can apply", which is not what we want. We have a type
826                // parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict
827                // `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling
828                // `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates`
829                // suggestions.
830            } else {
831                self.handle_unsatisfied_predicates(
832                    err,
833                    rcvr_ty,
834                    item_ident,
835                    item_kind,
836                    span,
837                    unsatisfied_predicates,
838                    &mut restrict_type_params,
839                    &mut suggested_derive,
840                    &mut unsatisfied_bounds,
841                    &mut custom_span_label,
842                    &mut bound_spans,
843                );
844            }
845        } else if let ty::Adt(def, targs) = rcvr_ty.kind()
846            && let SelfSource::MethodCall(rcvr_expr) = source
847        {
848            // This is useful for methods on arbitrary self types that might have a simple
849            // mutability difference, like calling a method on `Pin<&mut Self>` that is on
850            // `Pin<&Self>`.
851            if targs.len() == 1 {
852                let mut item_segment = hir::PathSegment::invalid();
853                item_segment.ident = item_ident;
854                for t in [Ty::new_mut_ref, Ty::new_imm_ref, |_, _, t| t] {
855                    let new_args =
856                        tcx.mk_args_from_iter(targs.iter().map(|arg| match arg.as_type() {
857                            Some(ty) => ty::GenericArg::from(t(
858                                tcx,
859                                tcx.lifetimes.re_erased,
860                                ty.peel_refs(),
861                            )),
862                            _ => arg,
863                        }));
864                    let rcvr_ty = Ty::new_adt(tcx, *def, new_args);
865                    if let Ok(method) = self.lookup_method_for_diagnostic(
866                        rcvr_ty,
867                        &item_segment,
868                        span,
869                        tcx.parent_hir_node(rcvr_expr.hir_id).expect_expr(),
870                        rcvr_expr,
871                    ) {
872                        err.span_note(
873                            tcx.def_span(method.def_id),
874                            format!("{item_kind} is available for `{rcvr_ty}`"),
875                        );
876                    }
877                }
878            }
879        }
880        Ok((
881            restrict_type_params,
882            suggested_derive,
883            unsatisfied_bounds,
884            custom_span_label,
885            bound_spans,
886        ))
887    }
888
889    fn suggest_surround_method_call(
890        &self,
891        err: &mut Diag<'_>,
892        span: Span,
893        rcvr_ty: Ty<'tcx>,
894        item_ident: Ident,
895        source: SelfSource<'tcx>,
896        similar_candidate: &Option<ty::AssocItem>,
897    ) -> bool {
898        match source {
899            // If the method name is the name of a field with a function or closure type,
900            // give a helping note that it has to be called as `(x.f)(...)`.
901            SelfSource::MethodCall(expr) => {
902                !self.suggest_calling_field_as_fn(span, rcvr_ty, expr, item_ident, err)
903                    && similar_candidate.is_none()
904            }
905            _ => true,
906        }
907    }
908
909    fn find_possible_candidates_for_method(
910        &self,
911        err: &mut Diag<'_>,
912        span: Span,
913        rcvr_ty: Ty<'tcx>,
914        item_ident: Ident,
915        item_kind: &str,
916        mode: Mode,
917        source: SelfSource<'tcx>,
918        no_match_data: &NoMatchData<'tcx>,
919        expected: Expectation<'tcx>,
920        should_label_not_found: bool,
921        custom_span_label: bool,
922    ) {
923        let mut find_candidate_for_method = false;
924        let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
925
926        if should_label_not_found && !custom_span_label {
927            self.set_not_found_span_label(
928                err,
929                rcvr_ty,
930                item_ident,
931                item_kind,
932                mode,
933                source,
934                span,
935                unsatisfied_predicates,
936                &mut find_candidate_for_method,
937            );
938        }
939        if !find_candidate_for_method {
940            self.lookup_segments_chain_for_no_match_method(
941                err,
942                item_ident,
943                item_kind,
944                source,
945                no_match_data,
946            );
947        }
948
949        // Don't suggest (for example) `expr.field.clone()` if `expr.clone()`
950        // can't be called due to `typeof(expr): Clone` not holding.
951        if unsatisfied_predicates.is_empty() {
952            self.suggest_calling_method_on_field(
953                err,
954                source,
955                span,
956                rcvr_ty,
957                item_ident,
958                expected.only_has_type(self),
959            );
960        }
961    }
962
963    fn suggest_confusable_or_similarly_named_method(
964        &self,
965        err: &mut Diag<'_>,
966        span: Span,
967        rcvr_ty: Ty<'tcx>,
968        item_ident: Ident,
969        mode: Mode,
970        args: Option<&'tcx [hir::Expr<'tcx>]>,
971        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
972        similar_candidate: Option<ty::AssocItem>,
973    ) {
974        let confusable_suggested = self.confusable_method_name(
975            err,
976            rcvr_ty,
977            item_ident,
978            args.map(|args| {
979                args.iter()
980                    .map(|expr| {
981                        self.node_ty_opt(expr.hir_id).unwrap_or_else(|| self.next_ty_var(expr.span))
982                    })
983                    .collect()
984            }),
985        );
986        if let Some(similar_candidate) = similar_candidate {
987            // Don't emit a suggestion if we found an actual method
988            // that had unsatisfied trait bounds
989            if unsatisfied_predicates.is_empty()
990                // ...or if we already suggested that name because of `rustc_confusable` annotation
991                && Some(similar_candidate.name()) != confusable_suggested
992                // and if we aren't in an expansion.
993                && !span.from_expansion()
994            {
995                self.find_likely_intended_associated_item(err, similar_candidate, span, args, mode);
996            }
997        }
998    }
999
1000    fn suggest_method_not_found_because_of_unsatisfied_bounds(
1001        &self,
1002        err: &mut Diag<'_>,
1003        rcvr_ty: Ty<'tcx>,
1004        item_ident: Ident,
1005        item_kind: &str,
1006        bound_spans: SortedMap<Span, Vec<String>>,
1007    ) {
1008        let mut ty_span = match rcvr_ty.kind() {
1009            ty::Param(param_type) => {
1010                Some(param_type.span_from_generics(self.tcx, self.body_id.to_def_id()))
1011            }
1012            ty::Adt(def, _) if def.did().is_local() => Some(self.tcx.def_span(def.did())),
1013            _ => None,
1014        };
1015        for (span, mut bounds) in bound_spans {
1016            if !self.tcx.sess.source_map().is_span_accessible(span) {
1017                continue;
1018            }
1019            bounds.sort();
1020            bounds.dedup();
1021            let pre = if Some(span) == ty_span {
1022                ty_span.take();
1023                format!(
1024                    "{item_kind} `{item_ident}` not found for this {} because it ",
1025                    rcvr_ty.prefix_string(self.tcx)
1026                )
1027            } else {
1028                String::new()
1029            };
1030            let msg = match &bounds[..] {
1031                [bound] => format!("{pre}doesn't satisfy {bound}"),
1032                bounds if bounds.len() > 4 => format!("doesn't satisfy {} bounds", bounds.len()),
1033                [bounds @ .., last] => {
1034                    format!("{pre}doesn't satisfy {} or {last}", bounds.join(", "))
1035                }
1036                [] => unreachable!(),
1037            };
1038            err.span_label(span, msg);
1039        }
1040        if let Some(span) = ty_span {
1041            err.span_label(
1042                span,
1043                format!(
1044                    "{item_kind} `{item_ident}` not found for this {}",
1045                    rcvr_ty.prefix_string(self.tcx)
1046                ),
1047            );
1048        }
1049    }
1050
1051    fn report_no_match_method_error(
1052        &self,
1053        span: Span,
1054        rcvr_ty: Ty<'tcx>,
1055        item_ident: Ident,
1056        expr_id: hir::HirId,
1057        source: SelfSource<'tcx>,
1058        args: Option<&'tcx [hir::Expr<'tcx>]>,
1059        sugg_span: Span,
1060        no_match_data: &mut NoMatchData<'tcx>,
1061        expected: Expectation<'tcx>,
1062        trait_missing_method: bool,
1063        within_macro_span: Option<Span>,
1064    ) -> ErrorGuaranteed {
1065        let tcx = self.tcx;
1066        let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
1067
1068        if let Err(guar) = rcvr_ty.error_reported() {
1069            return guar;
1070        }
1071
1072        // We could pass the file for long types into these two, but it isn't strictly necessary
1073        // given how targeted they are.
1074        if let Err(guar) =
1075            self.report_failed_method_call_on_range_end(tcx, rcvr_ty, source, span, item_ident)
1076        {
1077            return guar;
1078        }
1079
1080        let mut ty_file = None;
1081        let mode = no_match_data.mode;
1082        let is_method = mode == Mode::MethodCall;
1083        let item_kind = if is_method {
1084            "method"
1085        } else if rcvr_ty.is_enum() {
1086            "variant or associated item"
1087        } else {
1088            match (item_ident.as_str().chars().next(), rcvr_ty.is_fresh_ty()) {
1089                (Some(name), false) if name.is_lowercase() => "function or associated item",
1090                (Some(_), false) => "associated item",
1091                (Some(_), true) | (None, false) => "variant or associated item",
1092                (None, true) => "variant",
1093            }
1094        };
1095
1096        if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
1097            tcx,
1098            rcvr_ty,
1099            source,
1100            span,
1101            item_kind,
1102            item_ident,
1103            &mut ty_file,
1104        ) {
1105            return guar;
1106        }
1107
1108        let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
1109        let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
1110            tcx.is_diagnostic_item(sym::write_macro, def_id)
1111                || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
1112        }) && item_ident.name == sym::write_fmt;
1113        let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
1114            self.create_missing_writer_err(rcvr_ty, rcvr_expr, ty_file)
1115        } else {
1116            self.create_no_assoc_err(
1117                rcvr_ty,
1118                item_ident,
1119                item_kind,
1120                trait_missing_method,
1121                source,
1122                is_method,
1123                sugg_span,
1124                unsatisfied_predicates,
1125            )
1126        };
1127
1128        self.set_label_for_method_error(
1129            &mut err,
1130            source,
1131            rcvr_ty,
1132            item_ident,
1133            expr_id,
1134            item_ident.span,
1135            sugg_span,
1136            within_macro_span,
1137            args,
1138        );
1139
1140        self.suggest_method_call_annotation(
1141            &mut err,
1142            item_ident.span,
1143            rcvr_ty,
1144            item_ident,
1145            mode,
1146            source,
1147            expected,
1148        );
1149
1150        let static_candidates = self.suggest_static_method_candidates(
1151            &mut err,
1152            item_ident.span,
1153            rcvr_ty,
1154            item_ident,
1155            source,
1156            args,
1157            sugg_span,
1158            &no_match_data,
1159        );
1160
1161        let Ok((
1162            restrict_type_params,
1163            suggested_derive,
1164            unsatisfied_bounds,
1165            custom_span_label,
1166            bound_spans,
1167        )) = self.suggest_unsatisfied_ty_or_trait(
1168            &mut err,
1169            item_ident.span,
1170            rcvr_ty,
1171            item_ident,
1172            item_kind,
1173            source,
1174            unsatisfied_predicates,
1175            &static_candidates,
1176        )
1177        else {
1178            return err.emit();
1179        };
1180
1181        let similar_candidate = no_match_data.similar_candidate;
1182        let should_label_not_found = self.suggest_surround_method_call(
1183            &mut err,
1184            item_ident.span,
1185            rcvr_ty,
1186            item_ident,
1187            source,
1188            &similar_candidate,
1189        );
1190
1191        self.find_possible_candidates_for_method(
1192            &mut err,
1193            item_ident.span,
1194            rcvr_ty,
1195            item_ident,
1196            item_kind,
1197            mode,
1198            source,
1199            no_match_data,
1200            expected,
1201            should_label_not_found,
1202            custom_span_label,
1203        );
1204
1205        self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_ident);
1206
1207        if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
1208            // skip suggesting traits to import
1209        } else {
1210            self.suggest_traits_to_import(
1211                &mut err,
1212                item_ident.span,
1213                rcvr_ty,
1214                item_ident,
1215                args.map(|args| args.len() + 1),
1216                source,
1217                no_match_data.out_of_scope_traits.clone(),
1218                &static_candidates,
1219                unsatisfied_bounds,
1220                expected.only_has_type(self),
1221                trait_missing_method,
1222            );
1223        }
1224
1225        self.suggest_enum_variant_for_method_call(
1226            &mut err,
1227            rcvr_ty,
1228            item_ident,
1229            item_ident.span,
1230            source,
1231            unsatisfied_predicates,
1232        );
1233
1234        self.suggest_confusable_or_similarly_named_method(
1235            &mut err,
1236            item_ident.span,
1237            rcvr_ty,
1238            item_ident,
1239            mode,
1240            args,
1241            unsatisfied_predicates,
1242            similar_candidate,
1243        );
1244
1245        self.suggest_method_not_found_because_of_unsatisfied_bounds(
1246            &mut err,
1247            rcvr_ty,
1248            item_ident,
1249            item_kind,
1250            bound_spans,
1251        );
1252
1253        self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected);
1254        self.suggest_bounds_for_range_to_method(&mut err, source, item_ident);
1255        err.emit()
1256    }
1257
1258    fn set_not_found_span_label(
1259        &self,
1260        err: &mut Diag<'_>,
1261        rcvr_ty: Ty<'tcx>,
1262        item_ident: Ident,
1263        item_kind: &str,
1264        mode: Mode,
1265        source: SelfSource<'tcx>,
1266        span: Span,
1267        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
1268        find_candidate_for_method: &mut bool,
1269    ) {
1270        let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
1271        if unsatisfied_predicates.is_empty() {
1272            err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
1273            let is_string_or_ref_str = match rcvr_ty.kind() {
1274                ty::Ref(_, ty, _) => {
1275                    ty.is_str()
1276                        || matches!(
1277                            ty.kind(),
1278                            ty::Adt(adt, _) if self.tcx.is_lang_item(adt.did(), LangItem::String)
1279                        )
1280                }
1281                ty::Adt(adt, _) => self.tcx.is_lang_item(adt.did(), LangItem::String),
1282                _ => false,
1283            };
1284            if is_string_or_ref_str && item_ident.name == sym::iter {
1285                err.span_suggestion_verbose(
1286                    item_ident.span,
1287                    "because of the in-memory representation of `&str`, to obtain \
1288                     an `Iterator` over each of its codepoint use method `chars`",
1289                    "chars",
1290                    Applicability::MachineApplicable,
1291                );
1292            }
1293            if let ty::Adt(adt, _) = rcvr_ty.kind() {
1294                let mut inherent_impls_candidate = self
1295                    .tcx
1296                    .inherent_impls(adt.did())
1297                    .into_iter()
1298                    .copied()
1299                    .filter(|def_id| {
1300                        if let Some(assoc) = self.associated_value(*def_id, item_ident) {
1301                            // Check for both mode is the same so we avoid suggesting
1302                            // incorrect associated item.
1303                            match (mode, assoc.is_method(), source) {
1304                                (Mode::MethodCall, true, SelfSource::MethodCall(_)) => {
1305                                    // We check that the suggest type is actually
1306                                    // different from the received one
1307                                    // So we avoid suggestion method with Box<Self>
1308                                    // for instance
1309                                    self.tcx.at(span).type_of(*def_id).instantiate_identity()
1310                                        != rcvr_ty
1311                                }
1312                                (Mode::Path, false, _) => true,
1313                                _ => false,
1314                            }
1315                        } else {
1316                            false
1317                        }
1318                    })
1319                    .collect::<Vec<_>>();
1320                if !inherent_impls_candidate.is_empty() {
1321                    inherent_impls_candidate.sort_by_key(|id| self.tcx.def_path_str(id));
1322                    inherent_impls_candidate.dedup();
1323
1324                    // number of types to show at most
1325                    let limit = if inherent_impls_candidate.len() == 5 { 5 } else { 4 };
1326                    let type_candidates = inherent_impls_candidate
1327                        .iter()
1328                        .take(limit)
1329                        .map(|impl_item| {
1330                            format!(
1331                                "- `{}`",
1332                                self.tcx.at(span).type_of(*impl_item).instantiate_identity()
1333                            )
1334                        })
1335                        .collect::<Vec<_>>()
1336                        .join("\n");
1337                    let additional_types = if inherent_impls_candidate.len() > limit {
1338                        format!("\nand {} more types", inherent_impls_candidate.len() - limit)
1339                    } else {
1340                        "".to_string()
1341                    };
1342                    err.note(format!(
1343                        "the {item_kind} was found for\n{type_candidates}{additional_types}"
1344                    ));
1345                    *find_candidate_for_method = mode == Mode::MethodCall;
1346                }
1347            }
1348        } else {
1349            let ty_str = if ty_str.len() > 50 { String::new() } else { format!("on `{ty_str}` ") };
1350            err.span_label(
1351                span,
1352                format!("{item_kind} cannot be called {ty_str}due to unsatisfied trait bounds"),
1353            );
1354        }
1355    }
1356
1357    /// Suggest similar enum variant when method call fails
1358    fn suggest_enum_variant_for_method_call(
1359        &self,
1360        err: &mut Diag<'_>,
1361        rcvr_ty: Ty<'tcx>,
1362        item_ident: Ident,
1363        span: Span,
1364        source: SelfSource<'tcx>,
1365        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
1366    ) {
1367        // Don't emit a suggestion if we found an actual method that had unsatisfied trait bounds
1368        if !unsatisfied_predicates.is_empty() || !rcvr_ty.is_enum() {
1369            return;
1370        }
1371
1372        let tcx = self.tcx;
1373        let adt_def = rcvr_ty.ty_adt_def().expect("enum is not an ADT");
1374        if let Some(var_name) = edit_distance::find_best_match_for_name(
1375            &adt_def.variants().iter().map(|s| s.name).collect::<Vec<_>>(),
1376            item_ident.name,
1377            None,
1378        ) && let Some(variant) = adt_def.variants().iter().find(|s| s.name == var_name)
1379        {
1380            let mut suggestion = vec![(span, var_name.to_string())];
1381            if let SelfSource::QPath(ty) = source
1382                && let hir::Node::Expr(ref path_expr) = tcx.parent_hir_node(ty.hir_id)
1383                && let hir::ExprKind::Path(_) = path_expr.kind
1384                && let hir::Node::Stmt(&hir::Stmt { kind: hir::StmtKind::Semi(parent), .. })
1385                | hir::Node::Expr(parent) = tcx.parent_hir_node(path_expr.hir_id)
1386            {
1387                // We want to replace the parts that need to go, like `()` and `{}`.
1388                let replacement_span = match parent.kind {
1389                    hir::ExprKind::Call(callee, _) if callee.hir_id == path_expr.hir_id => {
1390                        span.with_hi(parent.span.hi())
1391                    }
1392                    hir::ExprKind::Struct(..) => span.with_hi(parent.span.hi()),
1393                    _ => span,
1394                };
1395                match (variant.ctor, parent.kind) {
1396                    (None, hir::ExprKind::Struct(..)) => {
1397                        // We want a struct and we have a struct. We won't suggest changing
1398                        // the fields (at least for now).
1399                        suggestion = vec![(span, var_name.to_string())];
1400                    }
1401                    (None, _) => {
1402                        // struct
1403                        suggestion = vec![(
1404                            replacement_span,
1405                            if variant.fields.is_empty() {
1406                                format!("{var_name} {{}}")
1407                            } else {
1408                                format!(
1409                                    "{var_name} {{ {} }}",
1410                                    variant
1411                                        .fields
1412                                        .iter()
1413                                        .map(|f| format!("{}: /* value */", f.name))
1414                                        .collect::<Vec<_>>()
1415                                        .join(", ")
1416                                )
1417                            },
1418                        )];
1419                    }
1420                    (Some((hir::def::CtorKind::Const, _)), _) => {
1421                        // unit, remove the `()`.
1422                        suggestion = vec![(replacement_span, var_name.to_string())];
1423                    }
1424                    (Some((hir::def::CtorKind::Fn, def_id)), hir::ExprKind::Call(rcvr, args)) => {
1425                        let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
1426                        let inputs = fn_sig.inputs().skip_binder();
1427                        // FIXME: reuse the logic for "change args" suggestion to account for types
1428                        // involved and detect things like substitution.
1429                        match (inputs, args) {
1430                            (inputs, []) => {
1431                                // Add arguments.
1432                                suggestion.push((
1433                                    rcvr.span.shrink_to_hi().with_hi(parent.span.hi()),
1434                                    format!(
1435                                        "({})",
1436                                        inputs
1437                                            .iter()
1438                                            .map(|i| format!("/* {i} */"))
1439                                            .collect::<Vec<String>>()
1440                                            .join(", ")
1441                                    ),
1442                                ));
1443                            }
1444                            (_, [arg]) if inputs.len() != args.len() => {
1445                                // Replace arguments.
1446                                suggestion.push((
1447                                    arg.span,
1448                                    inputs
1449                                        .iter()
1450                                        .map(|i| format!("/* {i} */"))
1451                                        .collect::<Vec<String>>()
1452                                        .join(", "),
1453                                ));
1454                            }
1455                            (_, [arg_start, .., arg_end]) if inputs.len() != args.len() => {
1456                                // Replace arguments.
1457                                suggestion.push((
1458                                    arg_start.span.to(arg_end.span),
1459                                    inputs
1460                                        .iter()
1461                                        .map(|i| format!("/* {i} */"))
1462                                        .collect::<Vec<String>>()
1463                                        .join(", "),
1464                                ));
1465                            }
1466                            // Argument count is the same, keep as is.
1467                            _ => {}
1468                        }
1469                    }
1470                    (Some((hir::def::CtorKind::Fn, def_id)), _) => {
1471                        let fn_sig = tcx.fn_sig(def_id).instantiate_identity();
1472                        let inputs = fn_sig.inputs().skip_binder();
1473                        suggestion = vec![(
1474                            replacement_span,
1475                            format!(
1476                                "{var_name}({})",
1477                                inputs
1478                                    .iter()
1479                                    .map(|i| format!("/* {i} */"))
1480                                    .collect::<Vec<String>>()
1481                                    .join(", ")
1482                            ),
1483                        )];
1484                    }
1485                }
1486            }
1487            err.multipart_suggestion_verbose(
1488                "there is a variant with a similar name",
1489                suggestion,
1490                Applicability::HasPlaceholders,
1491            );
1492        }
1493    }
1494
1495    fn handle_unsatisfied_predicates(
1496        &self,
1497        err: &mut Diag<'_>,
1498        rcvr_ty: Ty<'tcx>,
1499        item_ident: Ident,
1500        item_kind: &str,
1501        span: Span,
1502        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
1503        restrict_type_params: &mut bool,
1504        suggested_derive: &mut bool,
1505        unsatisfied_bounds: &mut bool,
1506        custom_span_label: &mut bool,
1507        bound_spans: &mut SortedMap<Span, Vec<String>>,
1508    ) {
1509        let tcx = self.tcx;
1510        let mut type_params = FxIndexMap::default();
1511
1512        // Pick out the list of unimplemented traits on the receiver.
1513        // This is used for custom error messages with the `#[rustc_on_unimplemented]` attribute.
1514        let mut unimplemented_traits = FxIndexMap::default();
1515
1516        let mut unimplemented_traits_only = true;
1517        for (predicate, _parent_pred, cause) in unsatisfied_predicates {
1518            if let (ty::PredicateKind::Clause(ty::ClauseKind::Trait(p)), Some(cause)) =
1519                (predicate.kind().skip_binder(), cause.as_ref())
1520            {
1521                if p.trait_ref.self_ty() != rcvr_ty {
1522                    // This is necessary, not just to keep the errors clean, but also
1523                    // because our derived obligations can wind up with a trait ref that
1524                    // requires a different param_env to be correctly compared.
1525                    continue;
1526                }
1527                unimplemented_traits.entry(p.trait_ref.def_id).or_insert((
1528                    predicate.kind().rebind(p),
1529                    Obligation {
1530                        cause: cause.clone(),
1531                        param_env: self.param_env,
1532                        predicate: *predicate,
1533                        recursion_depth: 0,
1534                    },
1535                ));
1536            }
1537        }
1538
1539        // Make sure that, if any traits other than the found ones were involved,
1540        // we don't report an unimplemented trait.
1541        // We don't want to say that `iter::Cloned` is not an iterator, just
1542        // because of some non-Clone item being iterated over.
1543        for (predicate, _parent_pred, _cause) in unsatisfied_predicates {
1544            match predicate.kind().skip_binder() {
1545                ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))
1546                    if unimplemented_traits.contains_key(&p.trait_ref.def_id) => {}
1547                _ => {
1548                    unimplemented_traits_only = false;
1549                    break;
1550                }
1551            }
1552        }
1553
1554        let mut collect_type_param_suggestions =
1555            |self_ty: Ty<'tcx>, parent_pred: ty::Predicate<'tcx>, obligation: &str| {
1556                // We don't care about regions here, so it's fine to skip the binder here.
1557                if let (ty::Param(_), ty::PredicateKind::Clause(ty::ClauseKind::Trait(p))) =
1558                    (self_ty.kind(), parent_pred.kind().skip_binder())
1559                {
1560                    let node = match p.trait_ref.self_ty().kind() {
1561                        ty::Param(_) => {
1562                            // Account for `fn` items like in `issue-35677.rs` to
1563                            // suggest restricting its type params.
1564                            Some(self.tcx.hir_node_by_def_id(self.body_id))
1565                        }
1566                        ty::Adt(def, _) => {
1567                            def.did().as_local().map(|def_id| self.tcx.hir_node_by_def_id(def_id))
1568                        }
1569                        _ => None,
1570                    };
1571                    if let Some(hir::Node::Item(hir::Item { kind, .. })) = node
1572                        && let Some(g) = kind.generics()
1573                    {
1574                        let key = (
1575                            g.tail_span_for_predicate_suggestion(),
1576                            g.add_where_or_trailing_comma(),
1577                        );
1578                        type_params
1579                            .entry(key)
1580                            .or_insert_with(UnordSet::default)
1581                            .insert(obligation.to_owned());
1582                        return true;
1583                    }
1584                }
1585                false
1586            };
1587        let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| {
1588            let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation });
1589            match self_ty.kind() {
1590                // Point at the type that couldn't satisfy the bound.
1591                ty::Adt(def, _) => {
1592                    bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg)
1593                }
1594                // Point at the trait object that couldn't satisfy the bound.
1595                ty::Dynamic(preds, _) => {
1596                    for pred in preds.iter() {
1597                        match pred.skip_binder() {
1598                            ty::ExistentialPredicate::Trait(tr) => {
1599                                bound_spans
1600                                    .get_mut_or_insert_default(tcx.def_span(tr.def_id))
1601                                    .push(msg.clone());
1602                            }
1603                            ty::ExistentialPredicate::Projection(_)
1604                            | ty::ExistentialPredicate::AutoTrait(_) => {}
1605                        }
1606                    }
1607                }
1608                // Point at the closure that couldn't satisfy the bound.
1609                ty::Closure(def_id, _) => {
1610                    bound_spans
1611                        .get_mut_or_insert_default(tcx.def_span(*def_id))
1612                        .push(format!("`{quiet}`"));
1613                }
1614                _ => {}
1615            }
1616        };
1617
1618        let mut format_pred = |pred: ty::Predicate<'tcx>| {
1619            let bound_predicate = pred.kind();
1620            match bound_predicate.skip_binder() {
1621                ty::PredicateKind::Clause(ty::ClauseKind::Projection(pred)) => {
1622                    let pred = bound_predicate.rebind(pred);
1623                    // `<Foo as Iterator>::Item = String`.
1624                    let projection_term = pred.skip_binder().projection_term;
1625                    let quiet_projection_term = projection_term
1626                        .with_replaced_self_ty(tcx, Ty::new_var(tcx, ty::TyVid::ZERO));
1627
1628                    let term = pred.skip_binder().term;
1629
1630                    let obligation = format!("{projection_term} = {term}");
1631                    let quiet =
1632                        with_forced_trimmed_paths!(format!("{} = {}", quiet_projection_term, term));
1633
1634                    bound_span_label(projection_term.self_ty(), &obligation, &quiet);
1635                    Some((obligation, projection_term.self_ty()))
1636                }
1637                ty::PredicateKind::Clause(ty::ClauseKind::Trait(poly_trait_ref)) => {
1638                    let p = poly_trait_ref.trait_ref;
1639                    let self_ty = p.self_ty();
1640                    let path = p.print_only_trait_path();
1641                    let obligation = format!("{self_ty}: {path}");
1642                    let quiet = with_forced_trimmed_paths!(format!("_: {}", path));
1643                    bound_span_label(self_ty, &obligation, &quiet);
1644                    Some((obligation, self_ty))
1645                }
1646                _ => None,
1647            }
1648        };
1649
1650        // Find all the requirements that come from a local `impl` block.
1651        let mut skip_list: UnordSet<_> = Default::default();
1652        let mut spanned_predicates = FxIndexMap::default();
1653        for (p, parent_p, cause) in unsatisfied_predicates {
1654            // Extract the predicate span and parent def id of the cause,
1655            // if we have one.
1656            let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) {
1657                Some(ObligationCauseCode::ImplDerived(data)) => {
1658                    (data.impl_or_alias_def_id, data.span)
1659                }
1660                Some(
1661                    ObligationCauseCode::WhereClauseInExpr(def_id, span, _, _)
1662                    | ObligationCauseCode::WhereClause(def_id, span),
1663                ) if !span.is_dummy() => (*def_id, *span),
1664                _ => continue,
1665            };
1666
1667            // Don't point out the span of `WellFormed` predicates.
1668            if !matches!(
1669                p.kind().skip_binder(),
1670                ty::PredicateKind::Clause(
1671                    ty::ClauseKind::Projection(..) | ty::ClauseKind::Trait(..)
1672                )
1673            ) {
1674                continue;
1675            }
1676
1677            match self.tcx.hir_get_if_local(item_def_id) {
1678                // Unmet obligation comes from a `derive` macro, point at it once to
1679                // avoid multiple span labels pointing at the same place.
1680                Some(Node::Item(hir::Item {
1681                    kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, .. }),
1682                    ..
1683                })) if matches!(
1684                    self_ty.span.ctxt().outer_expn_data().kind,
1685                    ExpnKind::Macro(MacroKind::Derive, _)
1686                ) || matches!(
1687                    of_trait.map(|t| t.trait_ref.path.span.ctxt().outer_expn_data().kind),
1688                    Some(ExpnKind::Macro(MacroKind::Derive, _))
1689                ) =>
1690                {
1691                    let span = self_ty.span.ctxt().outer_expn_data().call_site;
1692                    let entry = spanned_predicates.entry(span);
1693                    let entry = entry.or_insert_with(|| {
1694                        (FxIndexSet::default(), FxIndexSet::default(), Vec::new())
1695                    });
1696                    entry.0.insert(span);
1697                    entry.1.insert((
1698                        span,
1699                        "unsatisfied trait bound introduced in this `derive` macro",
1700                    ));
1701                    entry.2.push(p);
1702                    skip_list.insert(p);
1703                }
1704
1705                // Unmet obligation coming from an `impl`.
1706                Some(Node::Item(hir::Item {
1707                    kind: hir::ItemKind::Impl(hir::Impl { of_trait, self_ty, generics, .. }),
1708                    span: item_span,
1709                    ..
1710                })) => {
1711                    let sized_pred =
1712                        unsatisfied_predicates.iter().any(|(pred, _, _)| {
1713                            match pred.kind().skip_binder() {
1714                                ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
1715                                    self.tcx.is_lang_item(pred.def_id(), LangItem::Sized)
1716                                        && pred.polarity == ty::PredicatePolarity::Positive
1717                                }
1718                                _ => false,
1719                            }
1720                        });
1721                    for param in generics.params {
1722                        if param.span == cause_span && sized_pred {
1723                            let (sp, sugg) = match param.colon_span {
1724                                Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
1725                                None => (param.span.shrink_to_hi(), ": ?Sized"),
1726                            };
1727                            err.span_suggestion_verbose(
1728                                sp,
1729                                "consider relaxing the type parameter's implicit `Sized` bound",
1730                                sugg,
1731                                Applicability::MachineApplicable,
1732                            );
1733                        }
1734                    }
1735                    if let Some(pred) = parent_p {
1736                        // Done to add the "doesn't satisfy" `span_label`.
1737                        let _ = format_pred(*pred);
1738                    }
1739                    skip_list.insert(p);
1740                    let entry = spanned_predicates.entry(self_ty.span);
1741                    let entry = entry.or_insert_with(|| {
1742                        (FxIndexSet::default(), FxIndexSet::default(), Vec::new())
1743                    });
1744                    entry.2.push(p);
1745                    if cause_span != *item_span {
1746                        entry.0.insert(cause_span);
1747                        entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
1748                    } else {
1749                        if let Some(of_trait) = of_trait {
1750                            entry.0.insert(of_trait.trait_ref.path.span);
1751                        }
1752                        entry.0.insert(self_ty.span);
1753                    };
1754                    if let Some(of_trait) = of_trait {
1755                        entry.1.insert((of_trait.trait_ref.path.span, ""));
1756                    }
1757                    entry.1.insert((self_ty.span, ""));
1758                }
1759                Some(Node::Item(hir::Item {
1760                    kind: hir::ItemKind::Trait(_, rustc_ast::ast::IsAuto::Yes, ..),
1761                    span: item_span,
1762                    ..
1763                })) => {
1764                    self.dcx().span_delayed_bug(
1765                        *item_span,
1766                        "auto trait is invoked with no method error, but no error reported?",
1767                    );
1768                }
1769                Some(
1770                    Node::Item(hir::Item {
1771                        kind:
1772                            hir::ItemKind::Trait(_, _, _, ident, ..)
1773                            | hir::ItemKind::TraitAlias(_, ident, ..),
1774                        ..
1775                    })
1776                    // We may also encounter unsatisfied GAT or method bounds
1777                    | Node::TraitItem(hir::TraitItem { ident, .. })
1778                    | Node::ImplItem(hir::ImplItem { ident, .. })
1779                ) => {
1780                    skip_list.insert(p);
1781                    let entry = spanned_predicates.entry(ident.span);
1782                    let entry = entry.or_insert_with(|| {
1783                        (FxIndexSet::default(), FxIndexSet::default(), Vec::new())
1784                    });
1785                    entry.0.insert(cause_span);
1786                    entry.1.insert((ident.span, ""));
1787                    entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
1788                    entry.2.push(p);
1789                }
1790                _ => {
1791                    // It's possible to use well-formedness clauses to get obligations
1792                    // which point arbitrary items like ADTs, so there's no use in ICEing
1793                    // here if we find that the obligation originates from some other
1794                    // node that we don't handle.
1795                }
1796            }
1797        }
1798        let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect();
1799        spanned_predicates.sort_by_key(|(span, _)| *span);
1800        for (_, (primary_spans, span_labels, predicates)) in spanned_predicates {
1801            let mut preds: Vec<_> = predicates
1802                .iter()
1803                .filter_map(|pred| format_pred(**pred))
1804                .map(|(p, _)| format!("`{p}`"))
1805                .collect();
1806            preds.sort();
1807            preds.dedup();
1808            let msg = if let [pred] = &preds[..] {
1809                format!("trait bound {pred} was not satisfied")
1810            } else {
1811                format!("the following trait bounds were not satisfied:\n{}", preds.join("\n"),)
1812            };
1813            let mut span: MultiSpan = primary_spans.into_iter().collect::<Vec<_>>().into();
1814            for (sp, label) in span_labels {
1815                span.push_span_label(sp, label);
1816            }
1817            err.span_note(span, msg);
1818            *unsatisfied_bounds = true;
1819        }
1820
1821        let mut suggested_bounds = UnordSet::default();
1822        // The requirements that didn't have an `impl` span to show.
1823        let mut bound_list = unsatisfied_predicates
1824            .iter()
1825            .filter_map(|(pred, parent_pred, _cause)| {
1826                let mut suggested = false;
1827                format_pred(*pred).map(|(p, self_ty)| {
1828                    if let Some(parent) = parent_pred
1829                        && suggested_bounds.contains(parent)
1830                    {
1831                        // We don't suggest `PartialEq` when we already suggest `Eq`.
1832                    } else if !suggested_bounds.contains(pred)
1833                        && collect_type_param_suggestions(self_ty, *pred, &p)
1834                    {
1835                        suggested = true;
1836                        suggested_bounds.insert(pred);
1837                    }
1838                    (
1839                        match parent_pred {
1840                            None => format!("`{p}`"),
1841                            Some(parent_pred) => match format_pred(*parent_pred) {
1842                                None => format!("`{p}`"),
1843                                Some((parent_p, _)) => {
1844                                    if !suggested
1845                                        && !suggested_bounds.contains(pred)
1846                                        && !suggested_bounds.contains(parent_pred)
1847                                        && collect_type_param_suggestions(self_ty, *parent_pred, &p)
1848                                    {
1849                                        suggested_bounds.insert(pred);
1850                                    }
1851                                    format!("`{p}`\nwhich is required by `{parent_p}`")
1852                                }
1853                            },
1854                        },
1855                        *pred,
1856                    )
1857                })
1858            })
1859            .filter(|(_, pred)| !skip_list.contains(&pred))
1860            .map(|(t, _)| t)
1861            .enumerate()
1862            .collect::<Vec<(usize, String)>>();
1863
1864        if !matches!(rcvr_ty.peel_refs().kind(), ty::Param(_)) {
1865            for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
1866                *restrict_type_params = true;
1867                // #74886: Sort here so that the output is always the same.
1868                let obligations = obligations.into_sorted_stable_ord();
1869                err.span_suggestion_verbose(
1870                    span,
1871                    format!(
1872                        "consider restricting the type parameter{s} to satisfy the trait \
1873                         bound{s}",
1874                        s = pluralize!(obligations.len())
1875                    ),
1876                    format!("{} {}", add_where_or_comma, obligations.join(", ")),
1877                    Applicability::MaybeIncorrect,
1878                );
1879            }
1880        }
1881
1882        bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
1883        bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677
1884        bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order.
1885
1886        if !bound_list.is_empty() || !skip_list.is_empty() {
1887            let bound_list =
1888                bound_list.into_iter().map(|(_, path)| path).collect::<Vec<_>>().join("\n");
1889            let actual_prefix = rcvr_ty.prefix_string(self.tcx);
1890            info!("unimplemented_traits.len() == {}", unimplemented_traits.len());
1891            let (primary_message, label, notes) = if unimplemented_traits.len() == 1
1892                && unimplemented_traits_only
1893            {
1894                unimplemented_traits
1895                    .into_iter()
1896                    .next()
1897                    .map(|(_, (trait_ref, obligation))| {
1898                        if trait_ref.self_ty().references_error() || rcvr_ty.references_error() {
1899                            // Avoid crashing.
1900                            return (None, None, Vec::new());
1901                        }
1902                        let OnUnimplementedNote { message, label, notes, .. } = self
1903                            .err_ctxt()
1904                            .on_unimplemented_note(trait_ref, &obligation, err.long_ty_path());
1905                        (message, label, notes)
1906                    })
1907                    .unwrap()
1908            } else {
1909                (None, None, Vec::new())
1910            };
1911            let primary_message = primary_message.unwrap_or_else(|| {
1912                let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
1913                format!(
1914                    "the {item_kind} `{item_ident}` exists for {actual_prefix} `{ty_str}`, \
1915                     but its trait bounds were not satisfied"
1916                )
1917            });
1918            err.primary_message(primary_message);
1919            if let Some(label) = label {
1920                *custom_span_label = true;
1921                err.span_label(span, label);
1922            }
1923            if !bound_list.is_empty() {
1924                err.note(format!("the following trait bounds were not satisfied:\n{bound_list}"));
1925            }
1926            for note in notes {
1927                err.note(note);
1928            }
1929
1930            if let ty::Adt(adt_def, _) = rcvr_ty.kind() {
1931                unsatisfied_predicates.iter().find(|(pred, _parent, _cause)| {
1932                    if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) =
1933                        pred.kind().skip_binder()
1934                    {
1935                        self.suggest_hashmap_on_unsatisfied_hashset_buildhasher(
1936                            err, &pred, *adt_def,
1937                        )
1938                    } else {
1939                        false
1940                    }
1941                });
1942            }
1943
1944            *suggested_derive = self.suggest_derive(err, unsatisfied_predicates);
1945            *unsatisfied_bounds = true;
1946        }
1947    }
1948
1949    /// If an appropriate error source is not found, check method chain for possible candidates
1950    fn lookup_segments_chain_for_no_match_method(
1951        &self,
1952        err: &mut Diag<'_>,
1953        item_name: Ident,
1954        item_kind: &str,
1955        source: SelfSource<'tcx>,
1956        no_match_data: &NoMatchData<'tcx>,
1957    ) {
1958        if no_match_data.unsatisfied_predicates.is_empty()
1959            && let Mode::MethodCall = no_match_data.mode
1960            && let SelfSource::MethodCall(mut source_expr) = source
1961        {
1962            let mut stack_methods = vec![];
1963            while let hir::ExprKind::MethodCall(_path_segment, rcvr_expr, _args, method_span) =
1964                source_expr.kind
1965            {
1966                // Pop the matching receiver, to align on it's notional span
1967                if let Some(prev_match) = stack_methods.pop() {
1968                    err.span_label(
1969                        method_span,
1970                        format!("{item_kind} `{item_name}` is available on `{prev_match}`"),
1971                    );
1972                }
1973                let rcvr_ty = self.resolve_vars_if_possible(
1974                    self.typeck_results
1975                        .borrow()
1976                        .expr_ty_adjusted_opt(rcvr_expr)
1977                        .unwrap_or(Ty::new_misc_error(self.tcx)),
1978                );
1979
1980                let Ok(candidates) = self.probe_for_name_many(
1981                    Mode::MethodCall,
1982                    item_name,
1983                    None,
1984                    IsSuggestion(true),
1985                    rcvr_ty,
1986                    source_expr.hir_id,
1987                    ProbeScope::TraitsInScope,
1988                ) else {
1989                    return;
1990                };
1991
1992                // FIXME: `probe_for_name_many` searches for methods in inherent implementations,
1993                // so it may return a candidate that doesn't belong to this `revr_ty`. We need to
1994                // check whether the instantiated type matches the received one.
1995                for _matched_method in candidates {
1996                    // found a match, push to stack
1997                    stack_methods.push(rcvr_ty);
1998                }
1999                source_expr = rcvr_expr;
2000            }
2001            // If there is a match at the start of the chain, add a label for it too!
2002            if let Some(prev_match) = stack_methods.pop() {
2003                err.span_label(
2004                    source_expr.span,
2005                    format!("{item_kind} `{item_name}` is available on `{prev_match}`"),
2006                );
2007            }
2008        }
2009    }
2010
2011    fn find_likely_intended_associated_item(
2012        &self,
2013        err: &mut Diag<'_>,
2014        similar_candidate: ty::AssocItem,
2015        span: Span,
2016        args: Option<&'tcx [hir::Expr<'tcx>]>,
2017        mode: Mode,
2018    ) {
2019        let tcx = self.tcx;
2020        let def_kind = similar_candidate.as_def_kind();
2021        let an = self.tcx.def_kind_descr_article(def_kind, similar_candidate.def_id);
2022        let similar_candidate_name = similar_candidate.name();
2023        let msg = format!(
2024            "there is {an} {} `{}` with a similar name",
2025            self.tcx.def_kind_descr(def_kind, similar_candidate.def_id),
2026            similar_candidate_name,
2027        );
2028        // Methods are defined within the context of a struct and their first parameter
2029        // is always `self`, which represents the instance of the struct the method is
2030        // being called on Associated functions don’t take self as a parameter and they are
2031        // not methods because they don’t have an instance of the struct to work with.
2032        if def_kind == DefKind::AssocFn {
2033            let ty_args = self.infcx.fresh_args_for_item(span, similar_candidate.def_id);
2034            let fn_sig = tcx.fn_sig(similar_candidate.def_id).instantiate(tcx, ty_args);
2035            let fn_sig = self.instantiate_binder_with_fresh_vars(
2036                span,
2037                BoundRegionConversionTime::FnCall,
2038                fn_sig,
2039            );
2040            if similar_candidate.is_method() {
2041                if let Some(args) = args
2042                    && fn_sig.inputs()[1..].len() == args.len()
2043                {
2044                    // We found a method with the same number of arguments as the method
2045                    // call expression the user wrote.
2046                    err.span_suggestion_verbose(
2047                        span,
2048                        msg,
2049                        similar_candidate_name,
2050                        Applicability::MaybeIncorrect,
2051                    );
2052                } else {
2053                    // We found a method but either the expression is not a method call or
2054                    // the argument count didn't match.
2055                    err.span_help(
2056                        tcx.def_span(similar_candidate.def_id),
2057                        format!(
2058                            "{msg}{}",
2059                            if let None = args { "" } else { ", but with different arguments" },
2060                        ),
2061                    );
2062                }
2063            } else if let Some(args) = args
2064                && fn_sig.inputs().len() == args.len()
2065            {
2066                // We have fn call expression and the argument count match the associated
2067                // function we found.
2068                err.span_suggestion_verbose(
2069                    span,
2070                    msg,
2071                    similar_candidate_name,
2072                    Applicability::MaybeIncorrect,
2073                );
2074            } else {
2075                err.span_help(tcx.def_span(similar_candidate.def_id), msg);
2076            }
2077        } else if let Mode::Path = mode
2078            && args.unwrap_or(&[]).is_empty()
2079        {
2080            // We have an associated item syntax and we found something that isn't an fn.
2081            err.span_suggestion_verbose(
2082                span,
2083                msg,
2084                similar_candidate_name,
2085                Applicability::MaybeIncorrect,
2086            );
2087        } else {
2088            // The expression is a function or method call, but the item we found is an
2089            // associated const or type.
2090            err.span_help(tcx.def_span(similar_candidate.def_id), msg);
2091        }
2092    }
2093
2094    pub(crate) fn confusable_method_name(
2095        &self,
2096        err: &mut Diag<'_>,
2097        rcvr_ty: Ty<'tcx>,
2098        item_name: Ident,
2099        call_args: Option<Vec<Ty<'tcx>>>,
2100    ) -> Option<Symbol> {
2101        if let ty::Adt(adt, adt_args) = rcvr_ty.kind() {
2102            for inherent_impl_did in self.tcx.inherent_impls(adt.did()).into_iter() {
2103                for inherent_method in
2104                    self.tcx.associated_items(inherent_impl_did).in_definition_order()
2105                {
2106                    if let Some(candidates) = find_attr!(self.tcx.get_all_attrs(inherent_method.def_id), AttributeKind::Confusables{symbols, ..} => symbols)
2107                        && candidates.contains(&item_name.name)
2108                        && inherent_method.is_fn()
2109                    {
2110                        let args =
2111                            ty::GenericArgs::identity_for_item(self.tcx, inherent_method.def_id)
2112                                .rebase_onto(
2113                                    self.tcx,
2114                                    inherent_method.container_id(self.tcx),
2115                                    adt_args,
2116                                );
2117                        let fn_sig =
2118                            self.tcx.fn_sig(inherent_method.def_id).instantiate(self.tcx, args);
2119                        let fn_sig = self.instantiate_binder_with_fresh_vars(
2120                            item_name.span,
2121                            BoundRegionConversionTime::FnCall,
2122                            fn_sig,
2123                        );
2124                        let name = inherent_method.name();
2125                        if let Some(ref args) = call_args
2126                            && fn_sig.inputs()[1..]
2127                                .iter()
2128                                .eq_by(args, |expected, found| self.may_coerce(*expected, *found))
2129                        {
2130                            err.span_suggestion_verbose(
2131                                item_name.span,
2132                                format!("you might have meant to use `{}`", name),
2133                                name,
2134                                Applicability::MaybeIncorrect,
2135                            );
2136                            return Some(name);
2137                        } else if let None = call_args {
2138                            err.span_note(
2139                                self.tcx.def_span(inherent_method.def_id),
2140                                format!("you might have meant to use method `{}`", name),
2141                            );
2142                            return Some(name);
2143                        }
2144                    }
2145                }
2146            }
2147        }
2148        None
2149    }
2150    fn note_candidates_on_method_error(
2151        &self,
2152        rcvr_ty: Ty<'tcx>,
2153        item_name: Ident,
2154        self_source: SelfSource<'tcx>,
2155        args: Option<&'tcx [hir::Expr<'tcx>]>,
2156        span: Span,
2157        err: &mut Diag<'_>,
2158        sources: &mut Vec<CandidateSource>,
2159        sugg_span: Option<Span>,
2160    ) {
2161        sources.sort_by_key(|source| match source {
2162            CandidateSource::Trait(id) => (0, self.tcx.def_path_str(id)),
2163            CandidateSource::Impl(id) => (1, self.tcx.def_path_str(id)),
2164        });
2165        sources.dedup();
2166        // Dynamic limit to avoid hiding just one candidate, which is silly.
2167        let limit = if sources.len() == 5 { 5 } else { 4 };
2168
2169        let mut suggs = vec![];
2170        for (idx, source) in sources.iter().take(limit).enumerate() {
2171            match *source {
2172                CandidateSource::Impl(impl_did) => {
2173                    // Provide the best span we can. Use the item, if local to crate, else
2174                    // the impl, if local to crate (item may be defaulted), else nothing.
2175                    let Some(item) = self.associated_value(impl_did, item_name).or_else(|| {
2176                        let impl_trait_id = self.tcx.impl_opt_trait_id(impl_did)?;
2177                        self.associated_value(impl_trait_id, item_name)
2178                    }) else {
2179                        continue;
2180                    };
2181
2182                    let note_span = if item.def_id.is_local() {
2183                        Some(self.tcx.def_span(item.def_id))
2184                    } else if impl_did.is_local() {
2185                        Some(self.tcx.def_span(impl_did))
2186                    } else {
2187                        None
2188                    };
2189
2190                    let impl_ty = self.tcx.at(span).type_of(impl_did).instantiate_identity();
2191
2192                    let insertion = match self.tcx.impl_opt_trait_ref(impl_did) {
2193                        None => String::new(),
2194                        Some(trait_ref) => {
2195                            format!(
2196                                " of the trait `{}`",
2197                                self.tcx.def_path_str(trait_ref.skip_binder().def_id)
2198                            )
2199                        }
2200                    };
2201
2202                    let (note_str, idx) = if sources.len() > 1 {
2203                        (
2204                            format!(
2205                                "candidate #{} is defined in an impl{} for the type `{}`",
2206                                idx + 1,
2207                                insertion,
2208                                impl_ty,
2209                            ),
2210                            Some(idx + 1),
2211                        )
2212                    } else {
2213                        (
2214                            format!(
2215                                "the candidate is defined in an impl{insertion} for the type `{impl_ty}`",
2216                            ),
2217                            None,
2218                        )
2219                    };
2220                    if let Some(note_span) = note_span {
2221                        // We have a span pointing to the method. Show note with snippet.
2222                        err.span_note(note_span, note_str);
2223                    } else {
2224                        err.note(note_str);
2225                    }
2226                    if let Some(sugg_span) = sugg_span
2227                        && let Some(trait_ref) = self.tcx.impl_opt_trait_ref(impl_did)
2228                        && let Some(sugg) = print_disambiguation_help(
2229                            self.tcx,
2230                            err,
2231                            self_source,
2232                            args,
2233                            trait_ref
2234                                .instantiate(
2235                                    self.tcx,
2236                                    self.fresh_args_for_item(sugg_span, impl_did),
2237                                )
2238                                .with_replaced_self_ty(self.tcx, rcvr_ty),
2239                            idx,
2240                            sugg_span,
2241                            item,
2242                        )
2243                    {
2244                        suggs.push(sugg);
2245                    }
2246                }
2247                CandidateSource::Trait(trait_did) => {
2248                    let Some(item) = self.associated_value(trait_did, item_name) else { continue };
2249                    let item_span = self.tcx.def_span(item.def_id);
2250                    let idx = if sources.len() > 1 {
2251                        let msg = format!(
2252                            "candidate #{} is defined in the trait `{}`",
2253                            idx + 1,
2254                            self.tcx.def_path_str(trait_did)
2255                        );
2256                        err.span_note(item_span, msg);
2257                        Some(idx + 1)
2258                    } else {
2259                        let msg = format!(
2260                            "the candidate is defined in the trait `{}`",
2261                            self.tcx.def_path_str(trait_did)
2262                        );
2263                        err.span_note(item_span, msg);
2264                        None
2265                    };
2266                    if let Some(sugg_span) = sugg_span
2267                        && let Some(sugg) = print_disambiguation_help(
2268                            self.tcx,
2269                            err,
2270                            self_source,
2271                            args,
2272                            ty::TraitRef::new_from_args(
2273                                self.tcx,
2274                                trait_did,
2275                                self.fresh_args_for_item(sugg_span, trait_did),
2276                            )
2277                            .with_replaced_self_ty(self.tcx, rcvr_ty),
2278                            idx,
2279                            sugg_span,
2280                            item,
2281                        )
2282                    {
2283                        suggs.push(sugg);
2284                    }
2285                }
2286            }
2287        }
2288        if !suggs.is_empty()
2289            && let Some(span) = sugg_span
2290        {
2291            suggs.sort();
2292            err.span_suggestions(
2293                span.with_hi(item_name.span.lo()),
2294                "use fully-qualified syntax to disambiguate",
2295                suggs,
2296                Applicability::MachineApplicable,
2297            );
2298        }
2299        if sources.len() > limit {
2300            err.note(format!("and {} others", sources.len() - limit));
2301        }
2302    }
2303
2304    /// Look at all the associated functions without receivers in the type's inherent impls
2305    /// to look for builders that return `Self`, `Option<Self>` or `Result<Self, _>`.
2306    fn find_builder_fn(&self, err: &mut Diag<'_>, rcvr_ty: Ty<'tcx>, expr_id: hir::HirId) {
2307        let ty::Adt(adt_def, _) = rcvr_ty.kind() else {
2308            return;
2309        };
2310        let mut items = self
2311            .tcx
2312            .inherent_impls(adt_def.did())
2313            .iter()
2314            .flat_map(|i| self.tcx.associated_items(i).in_definition_order())
2315            // Only assoc fn with no receivers and only if
2316            // they are resolvable
2317            .filter(|item| {
2318                matches!(item.kind, ty::AssocKind::Fn { has_self: false, .. })
2319                    && self
2320                        .probe_for_name(
2321                            Mode::Path,
2322                            item.ident(self.tcx),
2323                            None,
2324                            IsSuggestion(true),
2325                            rcvr_ty,
2326                            expr_id,
2327                            ProbeScope::TraitsInScope,
2328                        )
2329                        .is_ok()
2330            })
2331            .filter_map(|item| {
2332                // Only assoc fns that return `Self`, `Option<Self>` or `Result<Self, _>`.
2333                let ret_ty = self
2334                    .tcx
2335                    .fn_sig(item.def_id)
2336                    .instantiate(self.tcx, self.fresh_args_for_item(DUMMY_SP, item.def_id))
2337                    .output();
2338                let ret_ty = self.tcx.instantiate_bound_regions_with_erased(ret_ty);
2339                let ty::Adt(def, args) = ret_ty.kind() else {
2340                    return None;
2341                };
2342                // Check for `-> Self`
2343                if self.can_eq(self.param_env, ret_ty, rcvr_ty) {
2344                    return Some((item.def_id, ret_ty));
2345                }
2346                // Check for `-> Option<Self>` or `-> Result<Self, _>`
2347                if ![self.tcx.lang_items().option_type(), self.tcx.get_diagnostic_item(sym::Result)]
2348                    .contains(&Some(def.did()))
2349                {
2350                    return None;
2351                }
2352                let arg = args.get(0)?.expect_ty();
2353                if self.can_eq(self.param_env, rcvr_ty, arg) {
2354                    Some((item.def_id, ret_ty))
2355                } else {
2356                    None
2357                }
2358            })
2359            .collect::<Vec<_>>();
2360        let post = if items.len() > 5 {
2361            let items_len = items.len();
2362            items.truncate(4);
2363            format!("\nand {} others", items_len - 4)
2364        } else {
2365            String::new()
2366        };
2367        match &items[..] {
2368            [] => {}
2369            [(def_id, ret_ty)] => {
2370                err.span_note(
2371                    self.tcx.def_span(def_id),
2372                    format!(
2373                        "if you're trying to build a new `{rcvr_ty}`, consider using `{}` which \
2374                         returns `{ret_ty}`",
2375                        self.tcx.def_path_str(def_id),
2376                    ),
2377                );
2378            }
2379            _ => {
2380                let span: MultiSpan = items
2381                    .iter()
2382                    .map(|(def_id, _)| self.tcx.def_span(def_id))
2383                    .collect::<Vec<Span>>()
2384                    .into();
2385                err.span_note(
2386                    span,
2387                    format!(
2388                        "if you're trying to build a new `{rcvr_ty}` consider using one of the \
2389                         following associated functions:\n{}{post}",
2390                        items
2391                            .iter()
2392                            .map(|(def_id, _ret_ty)| self.tcx.def_path_str(def_id))
2393                            .collect::<Vec<String>>()
2394                            .join("\n")
2395                    ),
2396                );
2397            }
2398        }
2399    }
2400
2401    /// Suggest calling `Ty::method` if `.method()` isn't found because the method
2402    /// doesn't take a `self` receiver.
2403    fn suggest_associated_call_syntax(
2404        &self,
2405        err: &mut Diag<'_>,
2406        static_candidates: &[CandidateSource],
2407        rcvr_ty: Ty<'tcx>,
2408        source: SelfSource<'tcx>,
2409        item_name: Ident,
2410        args: Option<&'tcx [hir::Expr<'tcx>]>,
2411        sugg_span: Span,
2412    ) {
2413        let mut has_unsuggestable_args = false;
2414        let ty_str = if let Some(CandidateSource::Impl(impl_did)) = static_candidates.get(0) {
2415            // When the "method" is resolved through dereferencing, we really want the
2416            // original type that has the associated function for accurate suggestions.
2417            // (#61411)
2418            let impl_ty = self.tcx.type_of(*impl_did).instantiate_identity();
2419            let target_ty = self
2420                .autoderef(sugg_span, rcvr_ty)
2421                .silence_errors()
2422                .find(|(rcvr_ty, _)| {
2423                    DeepRejectCtxt::relate_rigid_infer(self.tcx).types_may_unify(*rcvr_ty, impl_ty)
2424                })
2425                .map_or(impl_ty, |(ty, _)| ty)
2426                .peel_refs();
2427            if let ty::Adt(def, args) = target_ty.kind() {
2428                // If there are any inferred arguments, (`{integer}`), we should replace
2429                // them with underscores to allow the compiler to infer them
2430                let infer_args = self.tcx.mk_args_from_iter(args.into_iter().map(|arg| {
2431                    if !arg.is_suggestable(self.tcx, true) {
2432                        has_unsuggestable_args = true;
2433                        match arg.kind() {
2434                            GenericArgKind::Lifetime(_) => {
2435                                self.next_region_var(RegionVariableOrigin::Misc(DUMMY_SP)).into()
2436                            }
2437                            GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
2438                            GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
2439                        }
2440                    } else {
2441                        arg
2442                    }
2443                }));
2444
2445                self.tcx.value_path_str_with_args(def.did(), infer_args)
2446            } else {
2447                self.ty_to_value_string(target_ty)
2448            }
2449        } else {
2450            self.ty_to_value_string(rcvr_ty.peel_refs())
2451        };
2452        if let SelfSource::MethodCall(_) = source {
2453            let first_arg = static_candidates.get(0).and_then(|candidate_source| {
2454                let (assoc_did, self_ty) = match candidate_source {
2455                    CandidateSource::Impl(impl_did) => {
2456                        (*impl_did, self.tcx.type_of(*impl_did).instantiate_identity())
2457                    }
2458                    CandidateSource::Trait(trait_did) => (*trait_did, rcvr_ty),
2459                };
2460
2461                let assoc = self.associated_value(assoc_did, item_name)?;
2462                if !assoc.is_fn() {
2463                    return None;
2464                }
2465
2466                // for CandidateSource::Impl, `Self` will be instantiated to a concrete type
2467                // but for CandidateSource::Trait, `Self` is still `Self`
2468                let sig = self.tcx.fn_sig(assoc.def_id).instantiate_identity();
2469                sig.inputs().skip_binder().get(0).and_then(|first| {
2470                    // if the type of first arg is the same as the current impl type, we should take the first arg into assoc function
2471                    let first_ty = first.peel_refs();
2472                    if first_ty == self_ty || first_ty == self.tcx.types.self_param {
2473                        Some(first.ref_mutability().map_or("", |mutbl| mutbl.ref_prefix_str()))
2474                    } else {
2475                        None
2476                    }
2477                })
2478            });
2479
2480            let mut applicability = Applicability::MachineApplicable;
2481            let args = if let SelfSource::MethodCall(receiver) = source
2482                && let Some(args) = args
2483            {
2484                // The first arg is the same kind as the receiver
2485                let explicit_args = if first_arg.is_some() {
2486                    std::iter::once(receiver).chain(args.iter()).collect::<Vec<_>>()
2487                } else {
2488                    // There is no `Self` kind to infer the arguments from
2489                    if has_unsuggestable_args {
2490                        applicability = Applicability::HasPlaceholders;
2491                    }
2492                    args.iter().collect()
2493                };
2494                format!(
2495                    "({}{})",
2496                    first_arg.unwrap_or(""),
2497                    explicit_args
2498                        .iter()
2499                        .map(|arg| self
2500                            .tcx
2501                            .sess
2502                            .source_map()
2503                            .span_to_snippet(arg.span)
2504                            .unwrap_or_else(|_| {
2505                                applicability = Applicability::HasPlaceholders;
2506                                "_".to_owned()
2507                            }))
2508                        .collect::<Vec<_>>()
2509                        .join(", "),
2510                )
2511            } else {
2512                applicability = Applicability::HasPlaceholders;
2513                "(...)".to_owned()
2514            };
2515            err.span_suggestion_verbose(
2516                sugg_span,
2517                "use associated function syntax instead",
2518                format!("{ty_str}::{item_name}{args}"),
2519                applicability,
2520            );
2521        } else {
2522            err.help(format!("try with `{ty_str}::{item_name}`",));
2523        }
2524    }
2525
2526    /// Suggest calling a field with a type that implements the `Fn*` traits instead of a method with
2527    /// the same name as the field i.e. `(a.my_fn_ptr)(10)` instead of `a.my_fn_ptr(10)`.
2528    fn suggest_calling_field_as_fn(
2529        &self,
2530        span: Span,
2531        rcvr_ty: Ty<'tcx>,
2532        expr: &hir::Expr<'_>,
2533        item_name: Ident,
2534        err: &mut Diag<'_>,
2535    ) -> bool {
2536        let tcx = self.tcx;
2537        let field_receiver =
2538            self.autoderef(span, rcvr_ty).silence_errors().find_map(|(ty, _)| match ty.kind() {
2539                ty::Adt(def, args) if !def.is_enum() => {
2540                    let variant = &def.non_enum_variant();
2541                    tcx.find_field_index(item_name, variant).map(|index| {
2542                        let field = &variant.fields[index];
2543                        let field_ty = field.ty(tcx, args);
2544                        (field, field_ty)
2545                    })
2546                }
2547                _ => None,
2548            });
2549        if let Some((field, field_ty)) = field_receiver {
2550            let scope = tcx.parent_module_from_def_id(self.body_id);
2551            let is_accessible = field.vis.is_accessible_from(scope, tcx);
2552
2553            if is_accessible {
2554                if let Some((what, _, _)) = self.extract_callable_info(field_ty) {
2555                    let what = match what {
2556                        DefIdOrName::DefId(def_id) => self.tcx.def_descr(def_id),
2557                        DefIdOrName::Name(what) => what,
2558                    };
2559                    let expr_span = expr.span.to(item_name.span);
2560                    err.multipart_suggestion(
2561                        format!(
2562                            "to call the {what} stored in `{item_name}`, \
2563                            surround the field access with parentheses",
2564                        ),
2565                        vec![
2566                            (expr_span.shrink_to_lo(), '('.to_string()),
2567                            (expr_span.shrink_to_hi(), ')'.to_string()),
2568                        ],
2569                        Applicability::MachineApplicable,
2570                    );
2571                } else {
2572                    let call_expr = tcx.hir_expect_expr(tcx.parent_hir_id(expr.hir_id));
2573
2574                    if let Some(span) = call_expr.span.trim_start(item_name.span) {
2575                        err.span_suggestion(
2576                            span,
2577                            "remove the arguments",
2578                            "",
2579                            Applicability::MaybeIncorrect,
2580                        );
2581                    }
2582                }
2583            }
2584
2585            let field_kind = if is_accessible { "field" } else { "private field" };
2586            err.span_label(item_name.span, format!("{field_kind}, not a method"));
2587            return true;
2588        }
2589        false
2590    }
2591
2592    /// Suggest possible range with adding parentheses, for example:
2593    /// when encountering `0..1.map(|i| i + 1)` suggest `(0..1).map(|i| i + 1)`.
2594    fn report_failed_method_call_on_range_end(
2595        &self,
2596        tcx: TyCtxt<'tcx>,
2597        actual: Ty<'tcx>,
2598        source: SelfSource<'tcx>,
2599        span: Span,
2600        item_name: Ident,
2601    ) -> Result<(), ErrorGuaranteed> {
2602        if let SelfSource::MethodCall(expr) = source {
2603            for (_, parent) in tcx.hir_parent_iter(expr.hir_id).take(5) {
2604                if let Node::Expr(parent_expr) = parent {
2605                    if !is_range_literal(parent_expr) {
2606                        continue;
2607                    }
2608                    let lang_item = match parent_expr.kind {
2609                        ExprKind::Struct(qpath, _, _) => match tcx.qpath_lang_item(*qpath) {
2610                            Some(
2611                                lang_item @ (LangItem::Range
2612                                | LangItem::RangeCopy
2613                                | LangItem::RangeInclusiveCopy
2614                                | LangItem::RangeTo
2615                                | LangItem::RangeToInclusive),
2616                            ) => Some(lang_item),
2617                            _ => None,
2618                        },
2619                        ExprKind::Call(func, _) => match func.kind {
2620                            // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
2621                            ExprKind::Path(qpath)
2622                                if tcx.qpath_is_lang_item(qpath, LangItem::RangeInclusiveNew) =>
2623                            {
2624                                Some(LangItem::RangeInclusiveStruct)
2625                            }
2626                            _ => None,
2627                        },
2628                        _ => None,
2629                    };
2630
2631                    if lang_item.is_none() {
2632                        continue;
2633                    }
2634
2635                    let span_included = match parent_expr.kind {
2636                        hir::ExprKind::Struct(_, eps, _) => {
2637                            eps.last().is_some_and(|ep| ep.span.contains(span))
2638                        }
2639                        // `..=` desugars into `::std::ops::RangeInclusive::new(...)`.
2640                        hir::ExprKind::Call(func, ..) => func.span.contains(span),
2641                        _ => false,
2642                    };
2643
2644                    if !span_included {
2645                        continue;
2646                    }
2647
2648                    let Some(range_def_id) =
2649                        lang_item.and_then(|lang_item| self.tcx.lang_items().get(lang_item))
2650                    else {
2651                        continue;
2652                    };
2653                    let range_ty =
2654                        self.tcx.type_of(range_def_id).instantiate(self.tcx, &[actual.into()]);
2655
2656                    let pick = self.lookup_probe_for_diagnostic(
2657                        item_name,
2658                        range_ty,
2659                        expr,
2660                        ProbeScope::AllTraits,
2661                        None,
2662                    );
2663                    if pick.is_ok() {
2664                        let range_span = parent_expr.span.with_hi(expr.span.hi());
2665                        return Err(self.dcx().emit_err(errors::MissingParenthesesInRange {
2666                            span,
2667                            ty: actual,
2668                            method_name: item_name.as_str().to_string(),
2669                            add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
2670                                func_name: item_name.name.as_str().to_string(),
2671                                left: range_span.shrink_to_lo(),
2672                                right: range_span.shrink_to_hi(),
2673                            }),
2674                        }));
2675                    }
2676                }
2677            }
2678        }
2679        Ok(())
2680    }
2681
2682    fn report_failed_method_call_on_numerical_infer_var(
2683        &self,
2684        tcx: TyCtxt<'tcx>,
2685        actual: Ty<'tcx>,
2686        source: SelfSource<'_>,
2687        span: Span,
2688        item_kind: &str,
2689        item_name: Ident,
2690        long_ty_path: &mut Option<PathBuf>,
2691    ) -> Result<(), ErrorGuaranteed> {
2692        let found_candidate = all_traits(self.tcx)
2693            .into_iter()
2694            .any(|info| self.associated_value(info.def_id, item_name).is_some());
2695        let found_assoc = |ty: Ty<'tcx>| {
2696            simplify_type(tcx, ty, TreatParams::InstantiateWithInfer)
2697                .and_then(|simp| {
2698                    tcx.incoherent_impls(simp)
2699                        .iter()
2700                        .find_map(|&id| self.associated_value(id, item_name))
2701                })
2702                .is_some()
2703        };
2704        let found_candidate = found_candidate
2705            || found_assoc(tcx.types.i8)
2706            || found_assoc(tcx.types.i16)
2707            || found_assoc(tcx.types.i32)
2708            || found_assoc(tcx.types.i64)
2709            || found_assoc(tcx.types.i128)
2710            || found_assoc(tcx.types.u8)
2711            || found_assoc(tcx.types.u16)
2712            || found_assoc(tcx.types.u32)
2713            || found_assoc(tcx.types.u64)
2714            || found_assoc(tcx.types.u128)
2715            || found_assoc(tcx.types.f32)
2716            || found_assoc(tcx.types.f64);
2717        if found_candidate
2718            && actual.is_numeric()
2719            && !actual.has_concrete_skeleton()
2720            && let SelfSource::MethodCall(expr) = source
2721        {
2722            let ty_str = self.tcx.short_string(actual, long_ty_path);
2723            let mut err = struct_span_code_err!(
2724                self.dcx(),
2725                span,
2726                E0689,
2727                "can't call {item_kind} `{item_name}` on ambiguous numeric type `{ty_str}`"
2728            );
2729            *err.long_ty_path() = long_ty_path.take();
2730            let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
2731            match expr.kind {
2732                ExprKind::Lit(lit) => {
2733                    // numeric literal
2734                    let snippet = tcx
2735                        .sess
2736                        .source_map()
2737                        .span_to_snippet(lit.span)
2738                        .unwrap_or_else(|_| "<numeric literal>".to_owned());
2739
2740                    // If this is a floating point literal that ends with '.',
2741                    // get rid of it to stop this from becoming a member access.
2742                    let snippet = snippet.trim_suffix('.');
2743                    err.span_suggestion(
2744                        lit.span,
2745                        format!(
2746                            "you must specify a concrete type for this numeric value, \
2747                                         like `{concrete_type}`"
2748                        ),
2749                        format!("{snippet}_{concrete_type}"),
2750                        Applicability::MaybeIncorrect,
2751                    );
2752                }
2753                ExprKind::Path(QPath::Resolved(_, path)) => {
2754                    // local binding
2755                    if let hir::def::Res::Local(hir_id) = path.res {
2756                        let span = tcx.hir_span(hir_id);
2757                        let filename = tcx.sess.source_map().span_to_filename(span);
2758
2759                        let parent_node = self.tcx.parent_hir_node(hir_id);
2760                        let msg = format!(
2761                            "you must specify a type for this binding, like `{concrete_type}`",
2762                        );
2763
2764                        // FIXME: Maybe FileName::Anon should also be handled,
2765                        // otherwise there would be no suggestion if the source is STDIN for example.
2766                        match (filename, parent_node) {
2767                            (
2768                                FileName::Real(_),
2769                                Node::LetStmt(hir::LetStmt {
2770                                    source: hir::LocalSource::Normal,
2771                                    ty,
2772                                    ..
2773                                }),
2774                            ) => {
2775                                let type_span = ty
2776                                    .map(|ty| ty.span.with_lo(span.hi()))
2777                                    .unwrap_or(span.shrink_to_hi());
2778                                err.span_suggestion(
2779                                    // account for `let x: _ = 42;`
2780                                    //                   ^^^
2781                                    type_span,
2782                                    msg,
2783                                    format!(": {concrete_type}"),
2784                                    Applicability::MaybeIncorrect,
2785                                );
2786                            }
2787                            // For closure parameters with reference patterns (e.g., |&v|), suggest the type annotation
2788                            // on the pattern itself, e.g., |&v: &i32|
2789                            (FileName::Real(_), Node::Pat(pat))
2790                                if let Node::Pat(binding_pat) = self.tcx.hir_node(hir_id)
2791                                    && let hir::PatKind::Binding(..) = binding_pat.kind
2792                                    && let Node::Pat(parent_pat) = parent_node
2793                                    && matches!(parent_pat.kind, hir::PatKind::Ref(..)) =>
2794                            {
2795                                err.span_label(span, "you must specify a type for this binding");
2796
2797                                let mut ref_muts = Vec::new();
2798                                let mut current_node = parent_node;
2799
2800                                while let Node::Pat(parent_pat) = current_node {
2801                                    if let hir::PatKind::Ref(_, _, mutability) = parent_pat.kind {
2802                                        ref_muts.push(mutability);
2803                                        current_node = self.tcx.parent_hir_node(parent_pat.hir_id);
2804                                    } else {
2805                                        break;
2806                                    }
2807                                }
2808
2809                                let mut type_annotation = String::new();
2810                                for mutability in ref_muts.iter().rev() {
2811                                    match mutability {
2812                                        hir::Mutability::Mut => type_annotation.push_str("&mut "),
2813                                        hir::Mutability::Not => type_annotation.push('&'),
2814                                    }
2815                                }
2816                                type_annotation.push_str(&concrete_type);
2817
2818                                err.span_suggestion_verbose(
2819                                    pat.span.shrink_to_hi(),
2820                                    "specify the type in the closure argument list",
2821                                    format!(": {type_annotation}"),
2822                                    Applicability::MaybeIncorrect,
2823                                );
2824                            }
2825                            _ => {
2826                                err.span_label(span, msg);
2827                            }
2828                        }
2829                    }
2830                }
2831                _ => {}
2832            }
2833            return Err(err.emit());
2834        }
2835        Ok(())
2836    }
2837
2838    /// For code `rect::area(...)`,
2839    /// if `rect` is a local variable and `area` is a valid assoc method for it,
2840    /// we try to suggest `rect.area()`
2841    pub(crate) fn suggest_assoc_method_call(&self, segs: &[PathSegment<'_>]) {
2842        debug!("suggest_assoc_method_call segs: {:?}", segs);
2843        let [seg1, seg2] = segs else {
2844            return;
2845        };
2846        self.dcx().try_steal_modify_and_emit_err(
2847            seg1.ident.span,
2848            StashKey::CallAssocMethod,
2849            |err| {
2850                let body = self.tcx.hir_body_owned_by(self.body_id);
2851                struct LetVisitor {
2852                    ident_name: Symbol,
2853                }
2854
2855                // FIXME: This really should be taking scoping, etc into account.
2856                impl<'v> Visitor<'v> for LetVisitor {
2857                    type Result = ControlFlow<Option<&'v hir::Expr<'v>>>;
2858                    fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result {
2859                        if let hir::StmtKind::Let(&hir::LetStmt { pat, init, .. }) = ex.kind
2860                            && let hir::PatKind::Binding(_, _, ident, ..) = pat.kind
2861                            && ident.name == self.ident_name
2862                        {
2863                            ControlFlow::Break(init)
2864                        } else {
2865                            hir::intravisit::walk_stmt(self, ex)
2866                        }
2867                    }
2868                }
2869
2870                if let Node::Expr(call_expr) = self.tcx.parent_hir_node(seg1.hir_id)
2871                    && let ControlFlow::Break(Some(expr)) =
2872                        (LetVisitor { ident_name: seg1.ident.name }).visit_body(body)
2873                    && let Some(self_ty) = self.node_ty_opt(expr.hir_id)
2874                {
2875                    let probe = self.lookup_probe_for_diagnostic(
2876                        seg2.ident,
2877                        self_ty,
2878                        call_expr,
2879                        ProbeScope::TraitsInScope,
2880                        None,
2881                    );
2882                    if probe.is_ok() {
2883                        let sm = self.infcx.tcx.sess.source_map();
2884                        err.span_suggestion_verbose(
2885                            sm.span_extend_while(seg1.ident.span.shrink_to_hi(), |c| c == ':')
2886                                .unwrap(),
2887                            "you may have meant to call an instance method",
2888                            ".",
2889                            Applicability::MaybeIncorrect,
2890                        );
2891                    }
2892                }
2893            },
2894        );
2895    }
2896
2897    /// Suggest calling a method on a field i.e. `a.field.bar()` instead of `a.bar()`
2898    fn suggest_calling_method_on_field(
2899        &self,
2900        err: &mut Diag<'_>,
2901        source: SelfSource<'tcx>,
2902        span: Span,
2903        actual: Ty<'tcx>,
2904        item_name: Ident,
2905        return_type: Option<Ty<'tcx>>,
2906    ) {
2907        if let SelfSource::MethodCall(expr) = source {
2908            let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
2909            for fields in self.get_field_candidates_considering_privacy_for_diag(
2910                span,
2911                actual,
2912                mod_id,
2913                expr.hir_id,
2914            ) {
2915                let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(expr.hir_id));
2916
2917                let lang_items = self.tcx.lang_items();
2918                let never_mention_traits = [
2919                    lang_items.clone_trait(),
2920                    lang_items.deref_trait(),
2921                    lang_items.deref_mut_trait(),
2922                    self.tcx.get_diagnostic_item(sym::AsRef),
2923                    self.tcx.get_diagnostic_item(sym::AsMut),
2924                    self.tcx.get_diagnostic_item(sym::Borrow),
2925                    self.tcx.get_diagnostic_item(sym::BorrowMut),
2926                ];
2927                let mut candidate_fields: Vec<_> = fields
2928                    .into_iter()
2929                    .filter_map(|candidate_field| {
2930                        self.check_for_nested_field_satisfying_condition_for_diag(
2931                            span,
2932                            &|_, field_ty| {
2933                                self.lookup_probe_for_diagnostic(
2934                                    item_name,
2935                                    field_ty,
2936                                    call_expr,
2937                                    ProbeScope::TraitsInScope,
2938                                    return_type,
2939                                )
2940                                .is_ok_and(|pick| {
2941                                    !never_mention_traits
2942                                        .iter()
2943                                        .flatten()
2944                                        .any(|def_id| self.tcx.parent(pick.item.def_id) == *def_id)
2945                                })
2946                            },
2947                            candidate_field,
2948                            vec![],
2949                            mod_id,
2950                            expr.hir_id,
2951                        )
2952                    })
2953                    .map(|field_path| {
2954                        field_path
2955                            .iter()
2956                            .map(|id| id.to_string())
2957                            .collect::<Vec<String>>()
2958                            .join(".")
2959                    })
2960                    .collect();
2961                candidate_fields.sort();
2962
2963                let len = candidate_fields.len();
2964                if len > 0 {
2965                    err.span_suggestions(
2966                        item_name.span.shrink_to_lo(),
2967                        format!(
2968                            "{} of the expressions' fields {} a method of the same name",
2969                            if len > 1 { "some" } else { "one" },
2970                            if len > 1 { "have" } else { "has" },
2971                        ),
2972                        candidate_fields.iter().map(|path| format!("{path}.")),
2973                        Applicability::MaybeIncorrect,
2974                    );
2975                }
2976            }
2977        }
2978    }
2979
2980    fn suggest_unwrapping_inner_self(
2981        &self,
2982        err: &mut Diag<'_>,
2983        source: SelfSource<'tcx>,
2984        actual: Ty<'tcx>,
2985        item_name: Ident,
2986    ) {
2987        let tcx = self.tcx;
2988        let SelfSource::MethodCall(expr) = source else {
2989            return;
2990        };
2991        let call_expr = tcx.hir_expect_expr(tcx.parent_hir_id(expr.hir_id));
2992
2993        let ty::Adt(kind, args) = actual.kind() else {
2994            return;
2995        };
2996        match kind.adt_kind() {
2997            ty::AdtKind::Enum => {
2998                let matching_variants: Vec<_> = kind
2999                    .variants()
3000                    .iter()
3001                    .flat_map(|variant| {
3002                        let [field] = &variant.fields.raw[..] else {
3003                            return None;
3004                        };
3005                        let field_ty = field.ty(tcx, args);
3006
3007                        // Skip `_`, since that'll just lead to ambiguity.
3008                        if self.resolve_vars_if_possible(field_ty).is_ty_var() {
3009                            return None;
3010                        }
3011
3012                        self.lookup_probe_for_diagnostic(
3013                            item_name,
3014                            field_ty,
3015                            call_expr,
3016                            ProbeScope::TraitsInScope,
3017                            None,
3018                        )
3019                        .ok()
3020                        .map(|pick| (variant, field, pick))
3021                    })
3022                    .collect();
3023
3024                let ret_ty_matches = |diagnostic_item| {
3025                    if let Some(ret_ty) = self
3026                        .ret_coercion
3027                        .as_ref()
3028                        .map(|c| self.resolve_vars_if_possible(c.borrow().expected_ty()))
3029                        && let ty::Adt(kind, _) = ret_ty.kind()
3030                        && tcx.get_diagnostic_item(diagnostic_item) == Some(kind.did())
3031                    {
3032                        true
3033                    } else {
3034                        false
3035                    }
3036                };
3037
3038                match &matching_variants[..] {
3039                    [(_, field, pick)] => {
3040                        let self_ty = field.ty(tcx, args);
3041                        err.span_note(
3042                            tcx.def_span(pick.item.def_id),
3043                            format!("the method `{item_name}` exists on the type `{self_ty}`"),
3044                        );
3045                        let (article, kind, variant, question) = if tcx.is_diagnostic_item(sym::Result, kind.did())
3046                            // Do not suggest `.expect()` in const context where it's not available. rust-lang/rust#149316
3047                            && !tcx.hir_is_inside_const_context(expr.hir_id)
3048                        {
3049                            ("a", "Result", "Err", ret_ty_matches(sym::Result))
3050                        } else if tcx.is_diagnostic_item(sym::Option, kind.did()) {
3051                            ("an", "Option", "None", ret_ty_matches(sym::Option))
3052                        } else {
3053                            return;
3054                        };
3055                        if question {
3056                            err.span_suggestion_verbose(
3057                                expr.span.shrink_to_hi(),
3058                                format!(
3059                                    "use the `?` operator to extract the `{self_ty}` value, propagating \
3060                                    {article} `{kind}::{variant}` value to the caller"
3061                                ),
3062                                "?",
3063                                Applicability::MachineApplicable,
3064                            );
3065                        } else {
3066                            err.span_suggestion_verbose(
3067                                expr.span.shrink_to_hi(),
3068                                format!(
3069                                    "consider using `{kind}::expect` to unwrap the `{self_ty}` value, \
3070                                    panicking if the value is {article} `{kind}::{variant}`"
3071                                ),
3072                                ".expect(\"REASON\")",
3073                                Applicability::HasPlaceholders,
3074                            );
3075                        }
3076                    }
3077                    // FIXME(compiler-errors): Support suggestions for other matching enum variants
3078                    _ => {}
3079                }
3080            }
3081            // Target wrapper types - types that wrap or pretend to wrap another type,
3082            // perhaps this inner type is meant to be called?
3083            ty::AdtKind::Struct | ty::AdtKind::Union => {
3084                let [first] = ***args else {
3085                    return;
3086                };
3087                let ty::GenericArgKind::Type(ty) = first.kind() else {
3088                    return;
3089                };
3090                let Ok(pick) = self.lookup_probe_for_diagnostic(
3091                    item_name,
3092                    ty,
3093                    call_expr,
3094                    ProbeScope::TraitsInScope,
3095                    None,
3096                ) else {
3097                    return;
3098                };
3099
3100                let name = self.ty_to_value_string(actual);
3101                let inner_id = kind.did();
3102                let mutable = if let Some(AutorefOrPtrAdjustment::Autoref { mutbl, .. }) =
3103                    pick.autoref_or_ptr_adjustment
3104                {
3105                    Some(mutbl)
3106                } else {
3107                    None
3108                };
3109
3110                if tcx.is_diagnostic_item(sym::LocalKey, inner_id) {
3111                    err.help("use `with` or `try_with` to access thread local storage");
3112                } else if tcx.is_lang_item(kind.did(), LangItem::MaybeUninit) {
3113                    err.help(format!(
3114                        "if this `{name}` has been initialized, \
3115                        use one of the `assume_init` methods to access the inner value"
3116                    ));
3117                } else if tcx.is_diagnostic_item(sym::RefCell, inner_id) {
3118                    let (suggestion, borrow_kind, panic_if) = match mutable {
3119                        Some(Mutability::Not) => (".borrow()", "borrow", "a mutable borrow exists"),
3120                        Some(Mutability::Mut) => {
3121                            (".borrow_mut()", "mutably borrow", "any borrows exist")
3122                        }
3123                        None => return,
3124                    };
3125                    err.span_suggestion_verbose(
3126                        expr.span.shrink_to_hi(),
3127                        format!(
3128                            "use `{suggestion}` to {borrow_kind} the `{ty}`, \
3129                            panicking if {panic_if}"
3130                        ),
3131                        suggestion,
3132                        Applicability::MaybeIncorrect,
3133                    );
3134                } else if tcx.is_diagnostic_item(sym::Mutex, inner_id) {
3135                    err.span_suggestion_verbose(
3136                        expr.span.shrink_to_hi(),
3137                        format!(
3138                            "use `.lock().unwrap()` to borrow the `{ty}`, \
3139                            blocking the current thread until it can be acquired"
3140                        ),
3141                        ".lock().unwrap()",
3142                        Applicability::MaybeIncorrect,
3143                    );
3144                } else if tcx.is_diagnostic_item(sym::RwLock, inner_id) {
3145                    let (suggestion, borrow_kind) = match mutable {
3146                        Some(Mutability::Not) => (".read().unwrap()", "borrow"),
3147                        Some(Mutability::Mut) => (".write().unwrap()", "mutably borrow"),
3148                        None => return,
3149                    };
3150                    err.span_suggestion_verbose(
3151                        expr.span.shrink_to_hi(),
3152                        format!(
3153                            "use `{suggestion}` to {borrow_kind} the `{ty}`, \
3154                            blocking the current thread until it can be acquired"
3155                        ),
3156                        suggestion,
3157                        Applicability::MaybeIncorrect,
3158                    );
3159                } else {
3160                    return;
3161                };
3162
3163                err.span_note(
3164                    tcx.def_span(pick.item.def_id),
3165                    format!("the method `{item_name}` exists on the type `{ty}`"),
3166                );
3167            }
3168        }
3169    }
3170
3171    pub(crate) fn note_unmet_impls_on_type(
3172        &self,
3173        err: &mut Diag<'_>,
3174        errors: &[FulfillmentError<'tcx>],
3175        suggest_derive: bool,
3176    ) {
3177        let preds: Vec<_> = errors
3178            .iter()
3179            .filter_map(|e| match e.obligation.predicate.kind().skip_binder() {
3180                ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
3181                    match pred.self_ty().kind() {
3182                        ty::Adt(_, _) => Some((e.root_obligation.predicate, pred)),
3183                        _ => None,
3184                    }
3185                }
3186                _ => None,
3187            })
3188            .collect();
3189
3190        // Note for local items and foreign items respectively.
3191        let (mut local_preds, mut foreign_preds): (Vec<_>, Vec<_>) =
3192            preds.iter().partition(|&(_, pred)| {
3193                if let ty::Adt(def, _) = pred.self_ty().kind() {
3194                    def.did().is_local()
3195                } else {
3196                    false
3197                }
3198            });
3199
3200        local_preds.sort_by_key(|(_, pred)| pred.trait_ref.to_string());
3201        let local_def_ids = local_preds
3202            .iter()
3203            .filter_map(|(_, pred)| match pred.self_ty().kind() {
3204                ty::Adt(def, _) => Some(def.did()),
3205                _ => None,
3206            })
3207            .collect::<FxIndexSet<_>>();
3208        let mut local_spans: MultiSpan = local_def_ids
3209            .iter()
3210            .filter_map(|def_id| {
3211                let span = self.tcx.def_span(*def_id);
3212                if span.is_dummy() { None } else { Some(span) }
3213            })
3214            .collect::<Vec<_>>()
3215            .into();
3216        for (_, pred) in &local_preds {
3217            if let ty::Adt(def, _) = pred.self_ty().kind() {
3218                local_spans.push_span_label(
3219                    self.tcx.def_span(def.did()),
3220                    format!("must implement `{}`", pred.trait_ref.print_trait_sugared()),
3221                );
3222            }
3223        }
3224        if local_spans.primary_span().is_some() {
3225            let msg = if let [(_, local_pred)] = local_preds.as_slice() {
3226                format!(
3227                    "an implementation of `{}` might be missing for `{}`",
3228                    local_pred.trait_ref.print_trait_sugared(),
3229                    local_pred.self_ty()
3230                )
3231            } else {
3232                format!(
3233                    "the following type{} would have to `impl` {} required trait{} for this \
3234                     operation to be valid",
3235                    pluralize!(local_def_ids.len()),
3236                    if local_def_ids.len() == 1 { "its" } else { "their" },
3237                    pluralize!(local_preds.len()),
3238                )
3239            };
3240            err.span_note(local_spans, msg);
3241        }
3242
3243        foreign_preds
3244            .sort_by_key(|(_, pred): &(_, ty::TraitPredicate<'_>)| pred.trait_ref.to_string());
3245
3246        for (_, pred) in &foreign_preds {
3247            let ty = pred.self_ty();
3248            let ty::Adt(def, _) = ty.kind() else { continue };
3249            let span = self.tcx.def_span(def.did());
3250            if span.is_dummy() {
3251                continue;
3252            }
3253            let mut mspan: MultiSpan = span.into();
3254            mspan.push_span_label(span, format!("`{ty}` is defined in another crate"));
3255            err.span_note(
3256                mspan,
3257                format!("`{ty}` does not implement `{}`", pred.trait_ref.print_trait_sugared()),
3258            );
3259
3260            foreign_preds.iter().find(|&(root_pred, pred)| {
3261                if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(root_pred)) =
3262                    root_pred.kind().skip_binder()
3263                    && let Some(root_adt) = root_pred.self_ty().ty_adt_def()
3264                {
3265                    self.suggest_hashmap_on_unsatisfied_hashset_buildhasher(err, pred, root_adt)
3266                } else {
3267                    false
3268                }
3269            });
3270        }
3271
3272        let preds: Vec<_> = errors
3273            .iter()
3274            .map(|e| (e.obligation.predicate, None, Some(e.obligation.cause.clone())))
3275            .collect();
3276        if suggest_derive {
3277            self.suggest_derive(err, &preds);
3278        } else {
3279            // The predicate comes from a binop where the lhs and rhs have different types.
3280            let _ = self.note_predicate_source_and_get_derives(err, &preds);
3281        }
3282    }
3283
3284    fn note_predicate_source_and_get_derives(
3285        &self,
3286        err: &mut Diag<'_>,
3287        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
3288    ) -> Vec<(String, Span, Symbol)> {
3289        let mut derives = Vec::new();
3290        let mut traits = Vec::new();
3291        for (pred, _, _) in unsatisfied_predicates {
3292            let Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred))) =
3293                pred.kind().no_bound_vars()
3294            else {
3295                continue;
3296            };
3297            let adt = match trait_pred.self_ty().ty_adt_def() {
3298                Some(adt) if adt.did().is_local() => adt,
3299                _ => continue,
3300            };
3301            if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
3302                let can_derive = match diagnostic_name {
3303                    sym::Default => !adt.is_enum(),
3304                    sym::Eq
3305                    | sym::PartialEq
3306                    | sym::Ord
3307                    | sym::PartialOrd
3308                    | sym::Clone
3309                    | sym::Copy
3310                    | sym::Hash
3311                    | sym::Debug => true,
3312                    _ => false,
3313                };
3314                if can_derive {
3315                    let self_name = trait_pred.self_ty().to_string();
3316                    let self_span = self.tcx.def_span(adt.did());
3317                    for super_trait in
3318                        supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
3319                    {
3320                        if let Some(parent_diagnostic_name) =
3321                            self.tcx.get_diagnostic_name(super_trait.def_id())
3322                        {
3323                            derives.push((self_name.clone(), self_span, parent_diagnostic_name));
3324                        }
3325                    }
3326                    derives.push((self_name, self_span, diagnostic_name));
3327                } else {
3328                    traits.push(trait_pred.def_id());
3329                }
3330            } else {
3331                traits.push(trait_pred.def_id());
3332            }
3333        }
3334        traits.sort_by_key(|id| self.tcx.def_path_str(id));
3335        traits.dedup();
3336
3337        let len = traits.len();
3338        if len > 0 {
3339            let span =
3340                MultiSpan::from_spans(traits.iter().map(|&did| self.tcx.def_span(did)).collect());
3341            let mut names = format!("`{}`", self.tcx.def_path_str(traits[0]));
3342            for (i, &did) in traits.iter().enumerate().skip(1) {
3343                if len > 2 {
3344                    names.push_str(", ");
3345                }
3346                if i == len - 1 {
3347                    names.push_str(" and ");
3348                }
3349                names.push('`');
3350                names.push_str(&self.tcx.def_path_str(did));
3351                names.push('`');
3352            }
3353            err.span_note(
3354                span,
3355                format!("the trait{} {} must be implemented", pluralize!(len), names),
3356            );
3357        }
3358
3359        derives
3360    }
3361
3362    pub(crate) fn suggest_derive(
3363        &self,
3364        err: &mut Diag<'_>,
3365        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
3366    ) -> bool {
3367        let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates);
3368        derives.sort();
3369        derives.dedup();
3370
3371        let mut derives_grouped = Vec::<(String, Span, String)>::new();
3372        for (self_name, self_span, trait_name) in derives.into_iter() {
3373            if let Some((last_self_name, _, last_trait_names)) = derives_grouped.last_mut() {
3374                if last_self_name == &self_name {
3375                    last_trait_names.push_str(format!(", {trait_name}").as_str());
3376                    continue;
3377                }
3378            }
3379            derives_grouped.push((self_name, self_span, trait_name.to_string()));
3380        }
3381
3382        for (self_name, self_span, traits) in &derives_grouped {
3383            err.span_suggestion_verbose(
3384                self_span.shrink_to_lo(),
3385                format!("consider annotating `{self_name}` with `#[derive({traits})]`"),
3386                format!("#[derive({traits})]\n"),
3387                Applicability::MaybeIncorrect,
3388            );
3389        }
3390        !derives_grouped.is_empty()
3391    }
3392
3393    fn note_derefed_ty_has_method(
3394        &self,
3395        err: &mut Diag<'_>,
3396        self_source: SelfSource<'tcx>,
3397        rcvr_ty: Ty<'tcx>,
3398        item_name: Ident,
3399        expected: Expectation<'tcx>,
3400    ) {
3401        let SelfSource::QPath(ty) = self_source else {
3402            return;
3403        };
3404        for (deref_ty, _) in self.autoderef(DUMMY_SP, rcvr_ty).silence_errors().skip(1) {
3405            if let Ok(pick) = self.probe_for_name(
3406                Mode::Path,
3407                item_name,
3408                expected.only_has_type(self),
3409                IsSuggestion(true),
3410                deref_ty,
3411                ty.hir_id,
3412                ProbeScope::TraitsInScope,
3413            ) {
3414                if deref_ty.is_suggestable(self.tcx, true)
3415                    // If this method receives `&self`, then the provided
3416                    // argument _should_ coerce, so it's valid to suggest
3417                    // just changing the path.
3418                    && pick.item.is_method()
3419                    && let Some(self_ty) =
3420                        self.tcx.fn_sig(pick.item.def_id).instantiate_identity().inputs().skip_binder().get(0)
3421                    && self_ty.is_ref()
3422                {
3423                    let suggested_path = match deref_ty.kind() {
3424                        ty::Bool
3425                        | ty::Char
3426                        | ty::Int(_)
3427                        | ty::Uint(_)
3428                        | ty::Float(_)
3429                        | ty::Adt(_, _)
3430                        | ty::Str
3431                        | ty::Alias(ty::Projection | ty::Inherent, _)
3432                        | ty::Param(_) => format!("{deref_ty}"),
3433                        // we need to test something like  <&[_]>::len or <(&[u32])>::len
3434                        // and Vec::function();
3435                        // <&[_]>::len or <&[u32]>::len doesn't need an extra "<>" between
3436                        // but for Adt type like Vec::function()
3437                        // we would suggest <[_]>::function();
3438                        _ if self
3439                            .tcx
3440                            .sess
3441                            .source_map()
3442                            .span_wrapped_by_angle_or_parentheses(ty.span) =>
3443                        {
3444                            format!("{deref_ty}")
3445                        }
3446                        _ => format!("<{deref_ty}>"),
3447                    };
3448                    err.span_suggestion_verbose(
3449                        ty.span,
3450                        format!("the function `{item_name}` is implemented on `{deref_ty}`"),
3451                        suggested_path,
3452                        Applicability::MaybeIncorrect,
3453                    );
3454                } else {
3455                    err.span_note(
3456                        ty.span,
3457                        format!("the function `{item_name}` is implemented on `{deref_ty}`"),
3458                    );
3459                }
3460                return;
3461            }
3462        }
3463    }
3464
3465    fn suggest_bounds_for_range_to_method(
3466        &self,
3467        err: &mut Diag<'_>,
3468        source: SelfSource<'tcx>,
3469        item_ident: Ident,
3470    ) {
3471        let SelfSource::MethodCall(rcvr_expr) = source else { return };
3472        let hir::ExprKind::Struct(qpath, fields, _) = rcvr_expr.kind else { return };
3473        let Some(lang_item) = self.tcx.qpath_lang_item(*qpath) else {
3474            return;
3475        };
3476        let is_inclusive = match lang_item {
3477            hir::LangItem::RangeTo => false,
3478            hir::LangItem::RangeToInclusive | hir::LangItem::RangeInclusiveCopy => true,
3479            _ => return,
3480        };
3481
3482        let Some(iterator_trait) = self.tcx.get_diagnostic_item(sym::Iterator) else { return };
3483        let Some(_) = self
3484            .tcx
3485            .associated_items(iterator_trait)
3486            .filter_by_name_unhygienic(item_ident.name)
3487            .next()
3488        else {
3489            return;
3490        };
3491
3492        let source_map = self.tcx.sess.source_map();
3493        let range_type = if is_inclusive { "RangeInclusive" } else { "Range" };
3494        let Some(end_field) = fields.iter().find(|f| f.ident.name == rustc_span::sym::end) else {
3495            return;
3496        };
3497
3498        let element_ty = self.typeck_results.borrow().expr_ty_opt(end_field.expr);
3499        let is_integral = element_ty.is_some_and(|ty| ty.is_integral());
3500        let end_is_negative = is_integral
3501            && matches!(end_field.expr.kind, hir::ExprKind::Unary(rustc_ast::UnOp::Neg, _));
3502
3503        let Ok(snippet) = source_map.span_to_snippet(rcvr_expr.span) else { return };
3504
3505        let offset = snippet
3506            .chars()
3507            .take_while(|&c| c == '(' || c.is_whitespace())
3508            .map(|c| c.len_utf8())
3509            .sum::<usize>();
3510
3511        let insert_span = rcvr_expr
3512            .span
3513            .with_lo(rcvr_expr.span.lo() + rustc_span::BytePos(offset as u32))
3514            .shrink_to_lo();
3515
3516        let (value, appl) = if is_integral && !end_is_negative {
3517            ("0", Applicability::MachineApplicable)
3518        } else {
3519            ("/* start */", Applicability::HasPlaceholders)
3520        };
3521
3522        err.span_suggestion_verbose(
3523            insert_span,
3524            format!("consider using a bounded `{range_type}` by adding a concrete starting value"),
3525            value,
3526            appl,
3527        );
3528    }
3529
3530    /// Print out the type for use in value namespace.
3531    fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
3532        match ty.kind() {
3533            ty::Adt(def, args) => self.tcx.def_path_str_with_args(def.did(), args),
3534            _ => self.ty_to_string(ty),
3535        }
3536    }
3537
3538    fn suggest_await_before_method(
3539        &self,
3540        err: &mut Diag<'_>,
3541        item_name: Ident,
3542        ty: Ty<'tcx>,
3543        call: &hir::Expr<'_>,
3544        span: Span,
3545        return_type: Option<Ty<'tcx>>,
3546    ) {
3547        let Some(output_ty) = self.err_ctxt().get_impl_future_output_ty(ty) else { return };
3548        let output_ty = self.resolve_vars_if_possible(output_ty);
3549        let method_exists =
3550            self.method_exists_for_diagnostic(item_name, output_ty, call.hir_id, return_type);
3551        debug!("suggest_await_before_method: is_method_exist={}", method_exists);
3552        if method_exists {
3553            err.span_suggestion_verbose(
3554                span.shrink_to_lo(),
3555                "consider `await`ing on the `Future` and calling the method on its `Output`",
3556                "await.",
3557                Applicability::MaybeIncorrect,
3558            );
3559        }
3560    }
3561
3562    fn set_label_for_method_error(
3563        &self,
3564        err: &mut Diag<'_>,
3565        source: SelfSource<'tcx>,
3566        rcvr_ty: Ty<'tcx>,
3567        item_ident: Ident,
3568        expr_id: hir::HirId,
3569        span: Span,
3570        sugg_span: Span,
3571        within_macro_span: Option<Span>,
3572        args: Option<&'tcx [hir::Expr<'tcx>]>,
3573    ) {
3574        let tcx = self.tcx;
3575        if tcx.sess.source_map().is_multiline(sugg_span) {
3576            err.span_label(sugg_span.with_hi(span.lo()), "");
3577        }
3578        if let Some(within_macro_span) = within_macro_span {
3579            err.span_label(within_macro_span, "due to this macro variable");
3580        }
3581
3582        if matches!(source, SelfSource::QPath(_)) && args.is_some() {
3583            self.find_builder_fn(err, rcvr_ty, expr_id);
3584        }
3585
3586        if tcx.ty_is_opaque_future(rcvr_ty) && item_ident.name == sym::poll {
3587            let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
3588            err.help(format!(
3589                "method `poll` found on `Pin<&mut {ty_str}>`, \
3590                see documentation for `std::pin::Pin`"
3591            ));
3592            err.help("self type must be pinned to call `Future::poll`, \
3593                see https://rust-lang.github.io/async-book/04_pinning/01_chapter.html#pinning-in-practice"
3594            );
3595        }
3596
3597        if let Some(span) =
3598            tcx.resolutions(()).confused_type_with_std_module.get(&span.with_parent(None))
3599        {
3600            err.span_suggestion(
3601                span.shrink_to_lo(),
3602                "you are looking for the module in `std`, not the primitive type",
3603                "std::",
3604                Applicability::MachineApplicable,
3605            );
3606        }
3607    }
3608
3609    fn suggest_on_pointer_type(
3610        &self,
3611        err: &mut Diag<'_>,
3612        source: SelfSource<'tcx>,
3613        rcvr_ty: Ty<'tcx>,
3614        item_ident: Ident,
3615    ) {
3616        let tcx = self.tcx;
3617        // on pointers, check if the method would exist on a reference
3618        if let SelfSource::MethodCall(rcvr_expr) = source
3619            && let ty::RawPtr(ty, ptr_mutbl) = *rcvr_ty.kind()
3620            && let Ok(pick) = self.lookup_probe_for_diagnostic(
3621                item_ident,
3622                Ty::new_ref(tcx, ty::Region::new_error_misc(tcx), ty, ptr_mutbl),
3623                self.tcx.hir_expect_expr(self.tcx.parent_hir_id(rcvr_expr.hir_id)),
3624                ProbeScope::TraitsInScope,
3625                None,
3626            )
3627            && let ty::Ref(_, _, sugg_mutbl) = *pick.self_ty.kind()
3628            && (sugg_mutbl.is_not() || ptr_mutbl.is_mut())
3629        {
3630            let (method, method_anchor) = match sugg_mutbl {
3631                Mutability::Not => {
3632                    let method_anchor = match ptr_mutbl {
3633                        Mutability::Not => "as_ref",
3634                        Mutability::Mut => "as_ref-1",
3635                    };
3636                    ("as_ref", method_anchor)
3637                }
3638                Mutability::Mut => ("as_mut", "as_mut"),
3639            };
3640            err.span_note(
3641                tcx.def_span(pick.item.def_id),
3642                format!("the method `{item_ident}` exists on the type `{ty}`", ty = pick.self_ty),
3643            );
3644            let mut_str = ptr_mutbl.ptr_str();
3645            err.note(format!(
3646                "you might want to use the unsafe method `<*{mut_str} T>::{method}` to get \
3647                an optional reference to the value behind the pointer"
3648            ));
3649            err.note(format!(
3650                "read the documentation for `<*{mut_str} T>::{method}` and ensure you satisfy its \
3651                safety preconditions before calling it to avoid undefined behavior: \
3652                https://doc.rust-lang.org/std/primitive.pointer.html#method.{method_anchor}"
3653            ));
3654        }
3655    }
3656
3657    fn suggest_use_candidates<F>(&self, candidates: Vec<DefId>, handle_candidates: F)
3658    where
3659        F: FnOnce(Vec<String>, Vec<String>, Span),
3660    {
3661        let parent_map = self.tcx.visible_parent_map(());
3662
3663        let scope = self.tcx.parent_module_from_def_id(self.body_id);
3664        let (accessible_candidates, inaccessible_candidates): (Vec<_>, Vec<_>) =
3665            candidates.into_iter().partition(|id| {
3666                let vis = self.tcx.visibility(*id);
3667                vis.is_accessible_from(scope, self.tcx)
3668            });
3669
3670        let sugg = |candidates: Vec<_>, visible| {
3671            // Separate out candidates that must be imported with a glob, because they are named `_`
3672            // and cannot be referred with their identifier.
3673            let (candidates, globs): (Vec<_>, Vec<_>) =
3674                candidates.into_iter().partition(|trait_did| {
3675                    if let Some(parent_did) = parent_map.get(trait_did) {
3676                        // If the item is re-exported as `_`, we should suggest a glob-import instead.
3677                        if *parent_did != self.tcx.parent(*trait_did)
3678                            && self
3679                                .tcx
3680                                .module_children(*parent_did)
3681                                .iter()
3682                                .filter(|child| child.res.opt_def_id() == Some(*trait_did))
3683                                .all(|child| child.ident.name == kw::Underscore)
3684                        {
3685                            return false;
3686                        }
3687                    }
3688
3689                    true
3690                });
3691
3692            let prefix = if visible { "use " } else { "" };
3693            let postfix = if visible { ";" } else { "" };
3694            let path_strings = candidates.iter().map(|trait_did| {
3695                format!(
3696                    "{prefix}{}{postfix}\n",
3697                    with_no_visible_paths_if_doc_hidden!(with_crate_prefix!(
3698                        self.tcx.def_path_str(*trait_did)
3699                    )),
3700                )
3701            });
3702
3703            let glob_path_strings = globs.iter().map(|trait_did| {
3704                let parent_did = parent_map.get(trait_did).unwrap();
3705                format!(
3706                    "{prefix}{}::*{postfix} // trait {}\n",
3707                    with_no_visible_paths_if_doc_hidden!(with_crate_prefix!(
3708                        self.tcx.def_path_str(*parent_did)
3709                    )),
3710                    self.tcx.item_name(*trait_did),
3711                )
3712            });
3713            let mut sugg: Vec<_> = path_strings.chain(glob_path_strings).collect();
3714            sugg.sort();
3715            sugg
3716        };
3717
3718        let accessible_sugg = sugg(accessible_candidates, true);
3719        let inaccessible_sugg = sugg(inaccessible_candidates, false);
3720
3721        let (module, _, _) = self.tcx.hir_get_module(scope);
3722        let span = module.spans.inject_use_span;
3723        handle_candidates(accessible_sugg, inaccessible_sugg, span);
3724    }
3725
3726    fn suggest_valid_traits(
3727        &self,
3728        err: &mut Diag<'_>,
3729        item_name: Ident,
3730        mut valid_out_of_scope_traits: Vec<DefId>,
3731        explain: bool,
3732    ) -> bool {
3733        valid_out_of_scope_traits.retain(|id| self.tcx.is_user_visible_dep(id.krate));
3734        if !valid_out_of_scope_traits.is_empty() {
3735            let mut candidates = valid_out_of_scope_traits;
3736            candidates.sort_by_key(|id| self.tcx.def_path_str(id));
3737            candidates.dedup();
3738
3739            // `TryFrom` and `FromIterator` have no methods
3740            let edition_fix = candidates
3741                .iter()
3742                .find(|did| self.tcx.is_diagnostic_item(sym::TryInto, **did))
3743                .copied();
3744
3745            if explain {
3746                err.help("items from traits can only be used if the trait is in scope");
3747            }
3748
3749            let msg = format!(
3750                "{this_trait_is} implemented but not in scope",
3751                this_trait_is = if candidates.len() == 1 {
3752                    format!(
3753                        "trait `{}` which provides `{item_name}` is",
3754                        self.tcx.item_name(candidates[0]),
3755                    )
3756                } else {
3757                    format!("the following traits which provide `{item_name}` are")
3758                }
3759            );
3760
3761            self.suggest_use_candidates(candidates, |accessible_sugg, inaccessible_sugg, span| {
3762                let suggest_for_access = |err: &mut Diag<'_>, mut msg: String, suggs: Vec<_>| {
3763                    msg += &format!(
3764                        "; perhaps you want to import {one_of}",
3765                        one_of = if suggs.len() == 1 { "it" } else { "one of them" },
3766                    );
3767                    err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect);
3768                };
3769                let suggest_for_privacy = |err: &mut Diag<'_>, suggs: Vec<String>| {
3770                    let msg = format!(
3771                        "{this_trait_is} implemented but not reachable",
3772                        this_trait_is = if let [sugg] = suggs.as_slice() {
3773                            format!("trait `{}` which provides `{item_name}` is", sugg.trim())
3774                        } else {
3775                            format!("the following traits which provide `{item_name}` are")
3776                        }
3777                    );
3778                    if suggs.len() == 1 {
3779                        err.help(msg);
3780                    } else {
3781                        err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect);
3782                    }
3783                };
3784                if accessible_sugg.is_empty() {
3785                    // `inaccessible_sugg` must not be empty
3786                    suggest_for_privacy(err, inaccessible_sugg);
3787                } else if inaccessible_sugg.is_empty() {
3788                    suggest_for_access(err, msg, accessible_sugg);
3789                } else {
3790                    suggest_for_access(err, msg, accessible_sugg);
3791                    suggest_for_privacy(err, inaccessible_sugg);
3792                }
3793            });
3794
3795            if let Some(did) = edition_fix {
3796                err.note(format!(
3797                    "'{}' is included in the prelude starting in Edition 2021",
3798                    with_crate_prefix!(self.tcx.def_path_str(did))
3799                ));
3800            }
3801
3802            true
3803        } else {
3804            false
3805        }
3806    }
3807
3808    fn suggest_traits_to_import(
3809        &self,
3810        err: &mut Diag<'_>,
3811        span: Span,
3812        rcvr_ty: Ty<'tcx>,
3813        item_name: Ident,
3814        inputs_len: Option<usize>,
3815        source: SelfSource<'tcx>,
3816        valid_out_of_scope_traits: Vec<DefId>,
3817        static_candidates: &[CandidateSource],
3818        unsatisfied_bounds: bool,
3819        return_type: Option<Ty<'tcx>>,
3820        trait_missing_method: bool,
3821    ) {
3822        let mut alt_rcvr_sugg = false;
3823        let mut trait_in_other_version_found = false;
3824        if let (SelfSource::MethodCall(rcvr), false) = (source, unsatisfied_bounds) {
3825            debug!(
3826                "suggest_traits_to_import: span={:?}, item_name={:?}, rcvr_ty={:?}, rcvr={:?}",
3827                span, item_name, rcvr_ty, rcvr
3828            );
3829            let skippable = [
3830                self.tcx.lang_items().clone_trait(),
3831                self.tcx.lang_items().deref_trait(),
3832                self.tcx.lang_items().deref_mut_trait(),
3833                self.tcx.lang_items().drop_trait(),
3834                self.tcx.get_diagnostic_item(sym::AsRef),
3835            ];
3836            // Try alternative arbitrary self types that could fulfill this call.
3837            // FIXME: probe for all types that *could* be arbitrary self-types, not
3838            // just this list.
3839            for (rcvr_ty, post, pin_call) in &[
3840                (rcvr_ty, "", None),
3841                (
3842                    Ty::new_mut_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
3843                    "&mut ",
3844                    Some("as_mut"),
3845                ),
3846                (
3847                    Ty::new_imm_ref(self.tcx, self.tcx.lifetimes.re_erased, rcvr_ty),
3848                    "&",
3849                    Some("as_ref"),
3850                ),
3851            ] {
3852                match self.lookup_probe_for_diagnostic(
3853                    item_name,
3854                    *rcvr_ty,
3855                    rcvr,
3856                    ProbeScope::AllTraits,
3857                    return_type,
3858                ) {
3859                    Ok(pick) => {
3860                        // If the method is defined for the receiver we have, it likely wasn't `use`d.
3861                        // We point at the method, but we just skip the rest of the check for arbitrary
3862                        // self types and rely on the suggestion to `use` the trait from
3863                        // `suggest_valid_traits`.
3864                        let did = Some(pick.item.container_id(self.tcx));
3865                        if skippable.contains(&did) {
3866                            continue;
3867                        }
3868                        trait_in_other_version_found = self
3869                            .detect_and_explain_multiple_crate_versions_of_trait_item(
3870                                err,
3871                                pick.item.def_id,
3872                                rcvr.hir_id,
3873                                Some(*rcvr_ty),
3874                            );
3875                        if pick.autoderefs == 0 && !trait_in_other_version_found {
3876                            err.span_label(
3877                                pick.item.ident(self.tcx).span,
3878                                format!("the method is available for `{rcvr_ty}` here"),
3879                            );
3880                        }
3881                        break;
3882                    }
3883                    Err(MethodError::Ambiguity(_)) => {
3884                        // If the method is defined (but ambiguous) for the receiver we have, it is also
3885                        // likely we haven't `use`d it. It may be possible that if we `Box`/`Pin`/etc.
3886                        // the receiver, then it might disambiguate this method, but I think these
3887                        // suggestions are generally misleading (see #94218).
3888                        break;
3889                    }
3890                    Err(_) => (),
3891                }
3892
3893                let Some(unpin_trait) = self.tcx.lang_items().unpin_trait() else {
3894                    return;
3895                };
3896                let pred = ty::TraitRef::new(self.tcx, unpin_trait, [*rcvr_ty]);
3897                let unpin = self.predicate_must_hold_considering_regions(&Obligation::new(
3898                    self.tcx,
3899                    self.misc(rcvr.span),
3900                    self.param_env,
3901                    pred,
3902                ));
3903                for (rcvr_ty, pre) in &[
3904                    (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::OwnedBox), "Box::new"),
3905                    (Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin), "Pin::new"),
3906                    (Ty::new_diagnostic_item(self.tcx, *rcvr_ty, sym::Arc), "Arc::new"),
3907                    (Ty::new_diagnostic_item(self.tcx, *rcvr_ty, sym::Rc), "Rc::new"),
3908                ] {
3909                    if let Some(new_rcvr_t) = *rcvr_ty
3910                        && let Ok(pick) = self.lookup_probe_for_diagnostic(
3911                            item_name,
3912                            new_rcvr_t,
3913                            rcvr,
3914                            ProbeScope::AllTraits,
3915                            return_type,
3916                        )
3917                    {
3918                        debug!("try_alt_rcvr: pick candidate {:?}", pick);
3919                        let did = pick.item.trait_container(self.tcx);
3920                        // We don't want to suggest a container type when the missing
3921                        // method is `.clone()` or `.deref()` otherwise we'd suggest
3922                        // `Arc::new(foo).clone()`, which is far from what the user wants.
3923                        // Explicitly ignore the `Pin::as_ref()` method as `Pin` does not
3924                        // implement the `AsRef` trait.
3925                        let skip = skippable.contains(&did)
3926                            || (("Pin::new" == *pre)
3927                                && ((sym::as_ref == item_name.name) || !unpin))
3928                            || inputs_len.is_some_and(|inputs_len| {
3929                                pick.item.is_fn()
3930                                    && self
3931                                        .tcx
3932                                        .fn_sig(pick.item.def_id)
3933                                        .skip_binder()
3934                                        .skip_binder()
3935                                        .inputs()
3936                                        .len()
3937                                        != inputs_len
3938                            });
3939                        // Make sure the method is defined for the *actual* receiver: we don't
3940                        // want to treat `Box<Self>` as a receiver if it only works because of
3941                        // an autoderef to `&self`
3942                        if pick.autoderefs == 0 && !skip {
3943                            err.span_label(
3944                                pick.item.ident(self.tcx).span,
3945                                format!("the method is available for `{new_rcvr_t}` here"),
3946                            );
3947                            err.multipart_suggestion(
3948                                "consider wrapping the receiver expression with the \
3949                                 appropriate type",
3950                                vec![
3951                                    (rcvr.span.shrink_to_lo(), format!("{pre}({post}")),
3952                                    (rcvr.span.shrink_to_hi(), ")".to_string()),
3953                                ],
3954                                Applicability::MaybeIncorrect,
3955                            );
3956                            // We don't care about the other suggestions.
3957                            alt_rcvr_sugg = true;
3958                        }
3959                    }
3960                }
3961                // We special case the situation where `Pin::new` wouldn't work, and instead
3962                // suggest using the `pin!()` macro instead.
3963                if let Some(new_rcvr_t) = Ty::new_lang_item(self.tcx, *rcvr_ty, LangItem::Pin)
3964                    // We didn't find an alternative receiver for the method.
3965                    && !alt_rcvr_sugg
3966                    // `T: !Unpin`
3967                    && !unpin
3968                    // Either `Pin::as_ref` or `Pin::as_mut`.
3969                    && let Some(pin_call) = pin_call
3970                    // Search for `item_name` as a method accessible on `Pin<T>`.
3971                    && let Ok(pick) = self.lookup_probe_for_diagnostic(
3972                        item_name,
3973                        new_rcvr_t,
3974                        rcvr,
3975                        ProbeScope::AllTraits,
3976                        return_type,
3977                    )
3978                    // We skip some common traits that we don't want to consider because autoderefs
3979                    // would take care of them.
3980                    && !skippable.contains(&Some(pick.item.container_id(self.tcx)))
3981                    // Do not suggest pinning when the method is directly on `Pin`.
3982                    && pick.item.impl_container(self.tcx).is_none_or(|did| {
3983                        match self.tcx.type_of(did).skip_binder().kind() {
3984                            ty::Adt(def, _) => Some(def.did()) != self.tcx.lang_items().pin_type(),
3985                            _ => true,
3986                        }
3987                    })
3988                    // We don't want to go through derefs.
3989                    && pick.autoderefs == 0
3990                    // Check that the method of the same name that was found on the new `Pin<T>`
3991                    // receiver has the same number of arguments that appear in the user's code.
3992                    && inputs_len.is_some_and(|inputs_len| pick.item.is_fn() && self.tcx.fn_sig(pick.item.def_id).skip_binder().skip_binder().inputs().len() == inputs_len)
3993                {
3994                    let indent = self
3995                        .tcx
3996                        .sess
3997                        .source_map()
3998                        .indentation_before(rcvr.span)
3999                        .unwrap_or_else(|| " ".to_string());
4000                    let mut expr = rcvr;
4001                    while let Node::Expr(call_expr) = self.tcx.parent_hir_node(expr.hir_id)
4002                        && let hir::ExprKind::MethodCall(hir::PathSegment { .. }, ..) =
4003                            call_expr.kind
4004                    {
4005                        expr = call_expr;
4006                    }
4007                    match self.tcx.parent_hir_node(expr.hir_id) {
4008                        Node::LetStmt(stmt)
4009                            if let Some(init) = stmt.init
4010                                && let Ok(code) =
4011                                    self.tcx.sess.source_map().span_to_snippet(rcvr.span) =>
4012                        {
4013                            // We need to take care to account for the existing binding when we
4014                            // suggest the code.
4015                            err.multipart_suggestion(
4016                                "consider pinning the expression",
4017                                vec![
4018                                    (
4019                                        stmt.span.shrink_to_lo(),
4020                                        format!(
4021                                            "let mut pinned = std::pin::pin!({code});\n{indent}"
4022                                        ),
4023                                    ),
4024                                    (
4025                                        init.span.until(rcvr.span.shrink_to_hi()),
4026                                        format!("pinned.{pin_call}()"),
4027                                    ),
4028                                ],
4029                                Applicability::MaybeIncorrect,
4030                            );
4031                        }
4032                        Node::Block(_) | Node::Stmt(_) => {
4033                            // There's no binding, so we can provide a slightly nicer looking
4034                            // suggestion.
4035                            err.multipart_suggestion(
4036                                "consider pinning the expression",
4037                                vec![
4038                                    (
4039                                        rcvr.span.shrink_to_lo(),
4040                                        "let mut pinned = std::pin::pin!(".to_string(),
4041                                    ),
4042                                    (
4043                                        rcvr.span.shrink_to_hi(),
4044                                        format!(");\n{indent}pinned.{pin_call}()"),
4045                                    ),
4046                                ],
4047                                Applicability::MaybeIncorrect,
4048                            );
4049                        }
4050                        _ => {
4051                            // We don't quite know what the users' code looks like, so we don't
4052                            // provide a pinning suggestion.
4053                            err.span_help(
4054                                rcvr.span,
4055                                "consider pinning the expression with `std::pin::pin!()` and \
4056                                 assigning that to a new binding",
4057                            );
4058                        }
4059                    }
4060                    // We don't care about the other suggestions.
4061                    alt_rcvr_sugg = true;
4062                }
4063            }
4064        }
4065
4066        if let SelfSource::QPath(ty) = source
4067            && !valid_out_of_scope_traits.is_empty()
4068            && let hir::TyKind::Path(path) = ty.kind
4069            && let hir::QPath::Resolved(..) = path
4070            && let Some(assoc) = self
4071                .tcx
4072                .associated_items(valid_out_of_scope_traits[0])
4073                .filter_by_name_unhygienic(item_name.name)
4074                .next()
4075        {
4076            // See if the `Type::function(val)` where `function` wasn't found corresponds to a
4077            // `Trait` that is imported directly, but `Type` came from a different version of the
4078            // same crate.
4079
4080            let rcvr_ty = self.node_ty_opt(ty.hir_id);
4081            trait_in_other_version_found = self
4082                .detect_and_explain_multiple_crate_versions_of_trait_item(
4083                    err,
4084                    assoc.def_id,
4085                    ty.hir_id,
4086                    rcvr_ty,
4087                );
4088        }
4089        if !trait_in_other_version_found
4090            && self.suggest_valid_traits(err, item_name, valid_out_of_scope_traits, true)
4091        {
4092            return;
4093        }
4094
4095        let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source);
4096
4097        let mut arbitrary_rcvr = vec![];
4098        // There are no traits implemented, so lets suggest some traits to
4099        // implement, by finding ones that have the item name, and are
4100        // legal to implement.
4101        let mut candidates = all_traits(self.tcx)
4102            .into_iter()
4103            // Don't issue suggestions for unstable traits since they're
4104            // unlikely to be implementable anyway
4105            .filter(|info| match self.tcx.lookup_stability(info.def_id) {
4106                Some(attr) => attr.level.is_stable(),
4107                None => true,
4108            })
4109            .filter(|info| {
4110                // Static candidates are already implemented, and known not to work
4111                // Do not suggest them again
4112                static_candidates.iter().all(|sc| match *sc {
4113                    CandidateSource::Trait(def_id) => def_id != info.def_id,
4114                    CandidateSource::Impl(def_id) => {
4115                        self.tcx.impl_opt_trait_id(def_id) != Some(info.def_id)
4116                    }
4117                })
4118            })
4119            .filter(|info| {
4120                // We approximate the coherence rules to only suggest
4121                // traits that are legal to implement by requiring that
4122                // either the type or trait is local. Multi-dispatch means
4123                // this isn't perfect (that is, there are cases when
4124                // implementing a trait would be legal but is rejected
4125                // here).
4126                (type_is_local || info.def_id.is_local())
4127                    && !self.tcx.trait_is_auto(info.def_id)
4128                    && self
4129                        .associated_value(info.def_id, item_name)
4130                        .filter(|item| {
4131                            if item.is_fn() {
4132                                let id = item
4133                                    .def_id
4134                                    .as_local()
4135                                    .map(|def_id| self.tcx.hir_node_by_def_id(def_id));
4136                                if let Some(hir::Node::TraitItem(hir::TraitItem {
4137                                    kind: hir::TraitItemKind::Fn(fn_sig, method),
4138                                    ..
4139                                })) = id
4140                                {
4141                                    let self_first_arg = match method {
4142                                        hir::TraitFn::Required([ident, ..]) => {
4143                                            matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
4144                                        }
4145                                        hir::TraitFn::Provided(body_id) => {
4146                                            self.tcx.hir_body(*body_id).params.first().is_some_and(
4147                                                |param| {
4148                                                    matches!(
4149                                                        param.pat.kind,
4150                                                        hir::PatKind::Binding(_, _, ident, _)
4151                                                            if ident.name == kw::SelfLower
4152                                                    )
4153                                                },
4154                                            )
4155                                        }
4156                                        _ => false,
4157                                    };
4158
4159                                    if !fn_sig.decl.implicit_self.has_implicit_self()
4160                                        && self_first_arg
4161                                    {
4162                                        if let Some(ty) = fn_sig.decl.inputs.get(0) {
4163                                            arbitrary_rcvr.push(ty.span);
4164                                        }
4165                                        return false;
4166                                    }
4167                                }
4168                            }
4169                            // We only want to suggest public or local traits (#45781).
4170                            item.visibility(self.tcx).is_public() || info.def_id.is_local()
4171                        })
4172                        .is_some()
4173            })
4174            .collect::<Vec<_>>();
4175        for span in &arbitrary_rcvr {
4176            err.span_label(
4177                *span,
4178                "the method might not be found because of this arbitrary self type",
4179            );
4180        }
4181        if alt_rcvr_sugg {
4182            return;
4183        }
4184
4185        if !candidates.is_empty() {
4186            // Sort local crate results before others
4187            candidates
4188                .sort_by_key(|&info| (!info.def_id.is_local(), self.tcx.def_path_str(info.def_id)));
4189            candidates.dedup();
4190
4191            let param_type = match *rcvr_ty.kind() {
4192                ty::Param(param) => Some(param),
4193                ty::Ref(_, ty, _) => match *ty.kind() {
4194                    ty::Param(param) => Some(param),
4195                    _ => None,
4196                },
4197                _ => None,
4198            };
4199            if !trait_missing_method {
4200                err.help(if param_type.is_some() {
4201                    "items from traits can only be used if the type parameter is bounded by the trait"
4202                } else {
4203                    "items from traits can only be used if the trait is implemented and in scope"
4204                });
4205            }
4206
4207            let candidates_len = candidates.len();
4208            let message = |action| {
4209                format!(
4210                    "the following {traits_define} an item `{name}`, perhaps you need to {action} \
4211                     {one_of_them}:",
4212                    traits_define =
4213                        if candidates_len == 1 { "trait defines" } else { "traits define" },
4214                    action = action,
4215                    one_of_them = if candidates_len == 1 { "it" } else { "one of them" },
4216                    name = item_name,
4217                )
4218            };
4219            // Obtain the span for `param` and use it for a structured suggestion.
4220            if let Some(param) = param_type {
4221                let generics = self.tcx.generics_of(self.body_id.to_def_id());
4222                let type_param = generics.type_param(param, self.tcx);
4223                let tcx = self.tcx;
4224                if let Some(def_id) = type_param.def_id.as_local() {
4225                    let id = tcx.local_def_id_to_hir_id(def_id);
4226                    // Get the `hir::Param` to verify whether it already has any bounds.
4227                    // We do this to avoid suggesting code that ends up as `T: FooBar`,
4228                    // instead we suggest `T: Foo + Bar` in that case.
4229                    match tcx.hir_node(id) {
4230                        Node::GenericParam(param) => {
4231                            enum Introducer {
4232                                Plus,
4233                                Colon,
4234                                Nothing,
4235                            }
4236                            let hir_generics = tcx.hir_get_generics(id.owner.def_id).unwrap();
4237                            let trait_def_ids: DefIdSet = hir_generics
4238                                .bounds_for_param(def_id)
4239                                .flat_map(|bp| bp.bounds.iter())
4240                                .filter_map(|bound| bound.trait_ref()?.trait_def_id())
4241                                .collect();
4242                            if candidates.iter().any(|t| trait_def_ids.contains(&t.def_id)) {
4243                                return;
4244                            }
4245                            let msg = message(format!(
4246                                "restrict type parameter `{}` with",
4247                                param.name.ident(),
4248                            ));
4249                            let bounds_span = hir_generics.bounds_span_for_suggestions(def_id);
4250                            let mut applicability = Applicability::MaybeIncorrect;
4251                            // Format the path of each suggested candidate, providing placeholders
4252                            // for any generic arguments without defaults.
4253                            let candidate_strs: Vec<_> = candidates
4254                                .iter()
4255                                .map(|cand| {
4256                                    let cand_path = tcx.def_path_str(cand.def_id);
4257                                    let cand_params = &tcx.generics_of(cand.def_id).own_params;
4258                                    let cand_args: String = cand_params
4259                                        .iter()
4260                                        .skip(1)
4261                                        .filter_map(|param| match param.kind {
4262                                            ty::GenericParamDefKind::Type {
4263                                                has_default: true,
4264                                                ..
4265                                            }
4266                                            | ty::GenericParamDefKind::Const {
4267                                                has_default: true,
4268                                                ..
4269                                            } => None,
4270                                            _ => Some(param.name.as_str()),
4271                                        })
4272                                        .intersperse(", ")
4273                                        .collect();
4274                                    if cand_args.is_empty() {
4275                                        cand_path
4276                                    } else {
4277                                        applicability = Applicability::HasPlaceholders;
4278                                        format!("{cand_path}</* {cand_args} */>")
4279                                    }
4280                                })
4281                                .collect();
4282
4283                            if rcvr_ty.is_ref()
4284                                && param.is_impl_trait()
4285                                && let Some((bounds_span, _)) = bounds_span
4286                            {
4287                                err.multipart_suggestions(
4288                                    msg,
4289                                    candidate_strs.iter().map(|cand| {
4290                                        vec![
4291                                            (param.span.shrink_to_lo(), "(".to_string()),
4292                                            (bounds_span, format!(" + {cand})")),
4293                                        ]
4294                                    }),
4295                                    applicability,
4296                                );
4297                                return;
4298                            }
4299
4300                            let (sp, introducer, open_paren_sp) =
4301                                if let Some((span, open_paren_sp)) = bounds_span {
4302                                    (span, Introducer::Plus, open_paren_sp)
4303                                } else if let Some(colon_span) = param.colon_span {
4304                                    (colon_span.shrink_to_hi(), Introducer::Nothing, None)
4305                                } else if param.is_impl_trait() {
4306                                    (param.span.shrink_to_hi(), Introducer::Plus, None)
4307                                } else {
4308                                    (param.span.shrink_to_hi(), Introducer::Colon, None)
4309                                };
4310
4311                            let all_suggs = candidate_strs.iter().map(|cand| {
4312                                let suggestion = format!(
4313                                    "{} {cand}",
4314                                    match introducer {
4315                                        Introducer::Plus => " +",
4316                                        Introducer::Colon => ":",
4317                                        Introducer::Nothing => "",
4318                                    },
4319                                );
4320
4321                                let mut suggs = vec![];
4322
4323                                if let Some(open_paren_sp) = open_paren_sp {
4324                                    suggs.push((open_paren_sp, "(".to_string()));
4325                                    suggs.push((sp, format!("){suggestion}")));
4326                                } else {
4327                                    suggs.push((sp, suggestion));
4328                                }
4329
4330                                suggs
4331                            });
4332
4333                            err.multipart_suggestions(msg, all_suggs, applicability);
4334
4335                            return;
4336                        }
4337                        Node::Item(hir::Item {
4338                            kind: hir::ItemKind::Trait(_, _, _, ident, _, bounds, _),
4339                            ..
4340                        }) => {
4341                            let (sp, sep, article) = if bounds.is_empty() {
4342                                (ident.span.shrink_to_hi(), ":", "a")
4343                            } else {
4344                                (bounds.last().unwrap().span().shrink_to_hi(), " +", "another")
4345                            };
4346                            err.span_suggestions(
4347                                sp,
4348                                message(format!("add {article} supertrait for")),
4349                                candidates
4350                                    .iter()
4351                                    .map(|t| format!("{} {}", sep, tcx.def_path_str(t.def_id),)),
4352                                Applicability::MaybeIncorrect,
4353                            );
4354                            return;
4355                        }
4356                        _ => {}
4357                    }
4358                }
4359            }
4360
4361            let (potential_candidates, explicitly_negative) = if param_type.is_some() {
4362                // FIXME: Even though negative bounds are not implemented, we could maybe handle
4363                // cases where a positive bound implies a negative impl.
4364                (candidates, Vec::new())
4365            } else if let Some(simp_rcvr_ty) =
4366                simplify_type(self.tcx, rcvr_ty, TreatParams::AsRigid)
4367            {
4368                let mut potential_candidates = Vec::new();
4369                let mut explicitly_negative = Vec::new();
4370                for candidate in candidates {
4371                    // Check if there's a negative impl of `candidate` for `rcvr_ty`
4372                    if self
4373                        .tcx
4374                        .all_impls(candidate.def_id)
4375                        .map(|imp_did| self.tcx.impl_trait_header(imp_did))
4376                        .filter(|header| header.polarity != ty::ImplPolarity::Positive)
4377                        .any(|header| {
4378                            let imp = header.trait_ref.instantiate_identity();
4379                            let imp_simp =
4380                                simplify_type(self.tcx, imp.self_ty(), TreatParams::AsRigid);
4381                            imp_simp.is_some_and(|s| s == simp_rcvr_ty)
4382                        })
4383                    {
4384                        explicitly_negative.push(candidate);
4385                    } else {
4386                        potential_candidates.push(candidate);
4387                    }
4388                }
4389                (potential_candidates, explicitly_negative)
4390            } else {
4391                // We don't know enough about `recv_ty` to make proper suggestions.
4392                (candidates, Vec::new())
4393            };
4394
4395            let impls_trait = |def_id: DefId| {
4396                let args = ty::GenericArgs::for_item(self.tcx, def_id, |param, _| {
4397                    if param.index == 0 {
4398                        rcvr_ty.into()
4399                    } else {
4400                        self.infcx.var_for_def(span, param)
4401                    }
4402                });
4403                self.infcx
4404                    .type_implements_trait(def_id, args, self.param_env)
4405                    .must_apply_modulo_regions()
4406                    && param_type.is_none()
4407            };
4408            match &potential_candidates[..] {
4409                [] => {}
4410                [trait_info] if trait_info.def_id.is_local() => {
4411                    if impls_trait(trait_info.def_id) {
4412                        self.suggest_valid_traits(err, item_name, vec![trait_info.def_id], false);
4413                    } else {
4414                        err.subdiagnostic(CandidateTraitNote {
4415                            span: self.tcx.def_span(trait_info.def_id),
4416                            trait_name: self.tcx.def_path_str(trait_info.def_id),
4417                            item_name,
4418                            action_or_ty: if trait_missing_method {
4419                                "NONE".to_string()
4420                            } else {
4421                                param_type.map_or_else(
4422                                    || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
4423                                    |p| p.to_string(),
4424                                )
4425                            },
4426                        });
4427                    }
4428                }
4429                trait_infos => {
4430                    let mut msg = message(param_type.map_or_else(
4431                        || "implement".to_string(), // FIXME: it might only need to be imported into scope, not implemented.
4432                        |param| format!("restrict type parameter `{param}` with"),
4433                    ));
4434                    for (i, trait_info) in trait_infos.iter().enumerate() {
4435                        if impls_trait(trait_info.def_id) {
4436                            self.suggest_valid_traits(
4437                                err,
4438                                item_name,
4439                                vec![trait_info.def_id],
4440                                false,
4441                            );
4442                        }
4443                        msg.push_str(&format!(
4444                            "\ncandidate #{}: `{}`",
4445                            i + 1,
4446                            self.tcx.def_path_str(trait_info.def_id),
4447                        ));
4448                    }
4449                    err.note(msg);
4450                }
4451            }
4452            match &explicitly_negative[..] {
4453                [] => {}
4454                [trait_info] => {
4455                    let msg = format!(
4456                        "the trait `{}` defines an item `{}`, but is explicitly unimplemented",
4457                        self.tcx.def_path_str(trait_info.def_id),
4458                        item_name
4459                    );
4460                    err.note(msg);
4461                }
4462                trait_infos => {
4463                    let mut msg = format!(
4464                        "the following traits define an item `{item_name}`, but are explicitly unimplemented:"
4465                    );
4466                    for trait_info in trait_infos {
4467                        msg.push_str(&format!("\n{}", self.tcx.def_path_str(trait_info.def_id)));
4468                    }
4469                    err.note(msg);
4470                }
4471            }
4472        }
4473    }
4474
4475    fn detect_and_explain_multiple_crate_versions_of_trait_item(
4476        &self,
4477        err: &mut Diag<'_>,
4478        item_def_id: DefId,
4479        hir_id: hir::HirId,
4480        rcvr_ty: Option<Ty<'tcx>>,
4481    ) -> bool {
4482        let hir_id = self.tcx.parent_hir_id(hir_id);
4483        let Some(traits) = self.tcx.in_scope_traits(hir_id) else { return false };
4484        if traits.is_empty() {
4485            return false;
4486        }
4487        let trait_def_id = self.tcx.parent(item_def_id);
4488        if !self.tcx.is_trait(trait_def_id) {
4489            return false;
4490        }
4491        let hir::Node::Expr(rcvr) = self.tcx.hir_node(hir_id) else {
4492            return false;
4493        };
4494        let trait_ref = ty::TraitRef::new(self.tcx, trait_def_id, rcvr_ty.into_iter());
4495        let trait_pred = ty::Binder::dummy(ty::TraitPredicate {
4496            trait_ref,
4497            polarity: ty::PredicatePolarity::Positive,
4498        });
4499        let obligation = Obligation::new(self.tcx, self.misc(rcvr.span), self.param_env, trait_ref);
4500        self.err_ctxt().note_different_trait_with_same_name(err, &obligation, trait_pred)
4501    }
4502
4503    /// issue #102320, for `unwrap_or` with closure as argument, suggest `unwrap_or_else`
4504    /// FIXME: currently not working for suggesting `map_or_else`, see #102408
4505    pub(crate) fn suggest_else_fn_with_closure(
4506        &self,
4507        err: &mut Diag<'_>,
4508        expr: &hir::Expr<'_>,
4509        found: Ty<'tcx>,
4510        expected: Ty<'tcx>,
4511    ) -> bool {
4512        let Some((_def_id_or_name, output, _inputs)) = self.extract_callable_info(found) else {
4513            return false;
4514        };
4515
4516        if !self.may_coerce(output, expected) {
4517            return false;
4518        }
4519
4520        if let Node::Expr(call_expr) = self.tcx.parent_hir_node(expr.hir_id)
4521            && let hir::ExprKind::MethodCall(
4522                hir::PathSegment { ident: method_name, .. },
4523                self_expr,
4524                args,
4525                ..,
4526            ) = call_expr.kind
4527            && let Some(self_ty) = self.typeck_results.borrow().expr_ty_opt(self_expr)
4528        {
4529            let new_name = Ident {
4530                name: Symbol::intern(&format!("{}_else", method_name.as_str())),
4531                span: method_name.span,
4532            };
4533            let probe = self.lookup_probe_for_diagnostic(
4534                new_name,
4535                self_ty,
4536                self_expr,
4537                ProbeScope::TraitsInScope,
4538                Some(expected),
4539            );
4540
4541            // check the method arguments number
4542            if let Ok(pick) = probe
4543                && let fn_sig = self.tcx.fn_sig(pick.item.def_id)
4544                && let fn_args = fn_sig.skip_binder().skip_binder().inputs()
4545                && fn_args.len() == args.len() + 1
4546            {
4547                err.span_suggestion_verbose(
4548                    method_name.span.shrink_to_hi(),
4549                    format!("try calling `{}` instead", new_name.name.as_str()),
4550                    "_else",
4551                    Applicability::MaybeIncorrect,
4552                );
4553                return true;
4554            }
4555        }
4556        false
4557    }
4558
4559    /// Checks whether there is a local type somewhere in the chain of
4560    /// autoderefs of `rcvr_ty`.
4561    fn type_derefs_to_local(
4562        &self,
4563        span: Span,
4564        rcvr_ty: Ty<'tcx>,
4565        source: SelfSource<'tcx>,
4566    ) -> bool {
4567        fn is_local(ty: Ty<'_>) -> bool {
4568            match ty.kind() {
4569                ty::Adt(def, _) => def.did().is_local(),
4570                ty::Foreign(did) => did.is_local(),
4571                ty::Dynamic(tr, ..) => tr.principal().is_some_and(|d| d.def_id().is_local()),
4572                ty::Param(_) => true,
4573
4574                // Everything else (primitive types, etc.) is effectively
4575                // non-local (there are "edge" cases, e.g., `(LocalType,)`, but
4576                // the noise from these sort of types is usually just really
4577                // annoying, rather than any sort of help).
4578                _ => false,
4579            }
4580        }
4581
4582        // This occurs for UFCS desugaring of `T::method`, where there is no
4583        // receiver expression for the method call, and thus no autoderef.
4584        if let SelfSource::QPath(_) = source {
4585            return is_local(rcvr_ty);
4586        }
4587
4588        self.autoderef(span, rcvr_ty).silence_errors().any(|(ty, _)| is_local(ty))
4589    }
4590
4591    fn suggest_hashmap_on_unsatisfied_hashset_buildhasher(
4592        &self,
4593        err: &mut Diag<'_>,
4594        pred: &ty::TraitPredicate<'_>,
4595        adt: ty::AdtDef<'_>,
4596    ) -> bool {
4597        if self.tcx.is_diagnostic_item(sym::HashSet, adt.did())
4598            && self.tcx.is_diagnostic_item(sym::BuildHasher, pred.def_id())
4599        {
4600            err.help("you might have intended to use a HashMap instead");
4601            true
4602        } else {
4603            false
4604        }
4605    }
4606}
4607
4608#[derive(Copy, Clone, Debug)]
4609enum SelfSource<'a> {
4610    QPath(&'a hir::Ty<'a>),
4611    MethodCall(&'a hir::Expr<'a> /* rcvr */),
4612}
4613
4614#[derive(Copy, Clone, PartialEq, Eq)]
4615pub(crate) struct TraitInfo {
4616    pub def_id: DefId,
4617}
4618
4619/// Retrieves all traits in this crate and any dependent crates,
4620/// and wraps them into `TraitInfo` for custom sorting.
4621pub(crate) fn all_traits(tcx: TyCtxt<'_>) -> Vec<TraitInfo> {
4622    tcx.all_traits_including_private().map(|def_id| TraitInfo { def_id }).collect()
4623}
4624
4625fn print_disambiguation_help<'tcx>(
4626    tcx: TyCtxt<'tcx>,
4627    err: &mut Diag<'_>,
4628    source: SelfSource<'tcx>,
4629    args: Option<&'tcx [hir::Expr<'tcx>]>,
4630    trait_ref: ty::TraitRef<'tcx>,
4631    candidate_idx: Option<usize>,
4632    span: Span,
4633    item: ty::AssocItem,
4634) -> Option<String> {
4635    let trait_impl_type = trait_ref.self_ty().peel_refs();
4636    let trait_ref = if item.is_method() {
4637        trait_ref.print_only_trait_name().to_string()
4638    } else {
4639        format!("<{} as {}>", trait_ref.args[0], trait_ref.print_only_trait_name())
4640    };
4641    Some(
4642        if item.is_fn()
4643            && let SelfSource::MethodCall(receiver) = source
4644            && let Some(args) = args
4645        {
4646            let def_kind_descr = tcx.def_kind_descr(item.as_def_kind(), item.def_id);
4647            let item_name = item.ident(tcx);
4648            let first_input =
4649                tcx.fn_sig(item.def_id).instantiate_identity().skip_binder().inputs().get(0);
4650            let (first_arg_type, rcvr_ref) = (
4651                first_input.map(|first| first.peel_refs()),
4652                first_input
4653                    .and_then(|ty| ty.ref_mutability())
4654                    .map_or("", |mutbl| mutbl.ref_prefix_str()),
4655            );
4656
4657            // If the type of first arg of this assoc function is `Self` or current trait impl type or `arbitrary_self_types`, we need to take the receiver as args. Otherwise, we don't.
4658            let args = if let Some(first_arg_type) = first_arg_type
4659                && (first_arg_type == tcx.types.self_param
4660                    || first_arg_type == trait_impl_type
4661                    || item.is_method())
4662            {
4663                Some(receiver)
4664            } else {
4665                None
4666            }
4667            .into_iter()
4668            .chain(args)
4669            .map(|arg| {
4670                tcx.sess.source_map().span_to_snippet(arg.span).unwrap_or_else(|_| "_".to_owned())
4671            })
4672            .collect::<Vec<_>>()
4673            .join(", ");
4674
4675            let args = format!("({}{})", rcvr_ref, args);
4676            err.span_suggestion_verbose(
4677                span,
4678                format!(
4679                    "disambiguate the {def_kind_descr} for {}",
4680                    if let Some(candidate) = candidate_idx {
4681                        format!("candidate #{candidate}")
4682                    } else {
4683                        "the candidate".to_string()
4684                    },
4685                ),
4686                format!("{trait_ref}::{item_name}{args}"),
4687                Applicability::HasPlaceholders,
4688            );
4689            return None;
4690        } else {
4691            format!("{trait_ref}::")
4692        },
4693    )
4694}