Skip to main content

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::{
17    Applicability, Diag, MultiSpan, StashKey, StringPart, listify, pluralize, struct_span_code_err,
18};
19use rustc_hir::attrs::diagnostic::CustomDiagnostic;
20use rustc_hir::def::{CtorKind, DefKind, Res};
21use rustc_hir::def_id::DefId;
22use rustc_hir::intravisit::{self, Visitor};
23use rustc_hir::lang_items::LangItem;
24use rustc_hir::{
25    self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr, is_range_literal,
26};
27use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin};
28use rustc_middle::bug;
29use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type};
30use rustc_middle::ty::print::{
31    PrintTraitRefExt as _, with_crate_prefix, with_forced_trimmed_paths,
32    with_no_visible_paths_if_doc_hidden,
33};
34use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt};
35use rustc_span::def_id::DefIdSet;
36use rustc_span::{
37    DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, edit_distance,
38    kw, sym,
39};
40use rustc_trait_selection::error_reporting::traits::DefIdOrName;
41use rustc_trait_selection::infer::InferCtxtExt;
42use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
43use rustc_trait_selection::traits::{
44    FulfillmentError, Obligation, ObligationCauseCode, supertraits,
45};
46use tracing::{debug, info, instrument};
47
48use super::probe::{AutorefOrPtrAdjustment, IsSuggestion, Mode, ProbeScope};
49use super::{CandidateSource, MethodError, NoMatchData};
50use crate::errors::{self, CandidateTraitNote, NoAssociatedItem};
51use crate::method::probe::UnsatisfiedPredicates;
52use crate::{Expectation, FnCtxt};
53
54/// Tracks trait bounds and detects duplicates between ref and non-ref versions of self types.
55/// This is used to condense error messages when the same trait bound appears for both
56/// `T` and `&T` (or `&mut T`).
57struct TraitBoundDuplicateTracker {
58    trait_def_ids: FxIndexSet<DefId>,
59    seen_ref: FxIndexSet<DefId>,
60    seen_non_ref: FxIndexSet<DefId>,
61    has_ref_dupes: bool,
62}
63
64impl TraitBoundDuplicateTracker {
65    fn new() -> Self {
66        Self {
67            trait_def_ids: FxIndexSet::default(),
68            seen_ref: FxIndexSet::default(),
69            seen_non_ref: FxIndexSet::default(),
70            has_ref_dupes: false,
71        }
72    }
73
74    /// Track a trait bound. `is_ref` indicates whether the self type is a reference.
75    fn track(&mut self, def_id: DefId, is_ref: bool) {
76        self.trait_def_ids.insert(def_id);
77        if is_ref {
78            if self.seen_non_ref.contains(&def_id) {
79                self.has_ref_dupes = true;
80            }
81            self.seen_ref.insert(def_id);
82        } else {
83            if self.seen_ref.contains(&def_id) {
84                self.has_ref_dupes = true;
85            }
86            self.seen_non_ref.insert(def_id);
87        }
88    }
89
90    fn has_ref_dupes(&self) -> bool {
91        self.has_ref_dupes
92    }
93
94    fn into_trait_def_ids(self) -> FxIndexSet<DefId> {
95        self.trait_def_ids
96    }
97}
98
99impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
100    fn is_slice_ty(&self, ty: Ty<'tcx>, span: Span) -> bool {
101        self.autoderef(span, ty)
102            .silence_errors()
103            .any(|(ty, _)| #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Slice(..) | ty::Array(..) => true,
    _ => false,
}matches!(ty.kind(), ty::Slice(..) | ty::Array(..)))
104    }
105
106    fn impl_into_iterator_should_be_iterator(
107        &self,
108        ty: Ty<'tcx>,
109        span: Span,
110        unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>,
111    ) -> bool {
112        fn predicate_bounds_generic_param<'tcx>(
113            predicate: ty::Predicate<'_>,
114            generics: &'tcx ty::Generics,
115            generic_param: &ty::GenericParamDef,
116            tcx: TyCtxt<'tcx>,
117        ) -> bool {
118            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
119                predicate.kind().as_ref().skip_binder()
120            {
121                let ty::TraitPredicate { trait_ref: ty::TraitRef { args, .. }, .. } = trait_pred;
122                if args.is_empty() {
123                    return false;
124                }
125                let Some(arg_ty) = args[0].as_type() else {
126                    return false;
127                };
128                let ty::Param(param) = *arg_ty.kind() else {
129                    return false;
130                };
131                // Is `generic_param` the same as the arg for this trait predicate?
132                generic_param.index == generics.type_param(param, tcx).index
133            } else {
134                false
135            }
136        }
137
138        let is_iterator_predicate = |predicate: ty::Predicate<'tcx>| -> bool {
139            if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
140                predicate.kind().as_ref().skip_binder()
141            {
142                self.tcx.is_diagnostic_item(sym::Iterator, trait_pred.trait_ref.def_id)
143                    // ignore unsatisfied predicates generated from trying to auto-ref ty (#127511)
144                    && trait_pred.trait_ref.self_ty() == ty
145            } else {
146                false
147            }
148        };
149
150        // Does the `ty` implement `IntoIterator`?
151        let Some(into_iterator_trait) = self.tcx.get_diagnostic_item(sym::IntoIterator) else {
152            return false;
153        };
154        let trait_ref = ty::TraitRef::new(self.tcx, into_iterator_trait, [ty]);
155        let obligation = Obligation::new(self.tcx, self.misc(span), self.param_env, trait_ref);
156        if !self.predicate_must_hold_modulo_regions(&obligation) {
157            return false;
158        }
159
160        match *ty.peel_refs().kind() {
161            ty::Param(param) => {
162                let generics = self.tcx.generics_of(self.body_id);
163                let generic_param = generics.type_param(param, self.tcx);
164                for unsatisfied in unsatisfied_predicates.iter() {
165                    // The parameter implements `IntoIterator`
166                    // but it has called a method that requires it to implement `Iterator`
167                    if predicate_bounds_generic_param(
168                        unsatisfied.0,
169                        generics,
170                        generic_param,
171                        self.tcx,
172                    ) && is_iterator_predicate(unsatisfied.0)
173                    {
174                        return true;
175                    }
176                }
177            }
178            ty::Slice(..)
179            | ty::Adt(..)
180            | ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) => {
181                for unsatisfied in unsatisfied_predicates.iter() {
182                    if is_iterator_predicate(unsatisfied.0) {
183                        return true;
184                    }
185                }
186            }
187            _ => return false,
188        }
189        false
190    }
191
192    #[allow(clippy :: suspicious_else_formatting)]
{
    let __tracing_attr_span;
    let __tracing_attr_guard;
    if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::DEBUG <=
                    ::tracing::level_filters::LevelFilter::current() ||
            { false } {
        __tracing_attr_span =
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("report_method_error",
                                    "rustc_hir_typeck::method::suggest",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/method/suggest.rs"),
                                    ::tracing_core::__macro_support::Option::Some(192u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::method::suggest"),
                                    ::tracing_core::field::FieldSet::new(&["call_id", "rcvr_ty",
                                                    "error", "expected", "trait_missing_method"],
                                        ::tracing_core::callsite::Identifier(&__CALLSITE)),
                                    ::tracing::metadata::Kind::SPAN)
                            };
                        ::tracing::callsite::DefaultCallsite::new(&META)
                    };
                let mut interest = ::tracing::subscriber::Interest::never();
                if ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::STATIC_MAX_LEVEL &&
                                ::tracing::Level::DEBUG <=
                                    ::tracing::level_filters::LevelFilter::current() &&
                            { interest = __CALLSITE.interest(); !interest.is_never() }
                        &&
                        ::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
                            interest) {
                    let meta = __CALLSITE.metadata();
                    ::tracing::Span::new(meta,
                        &{
                                #[allow(unused_imports)]
                                use ::tracing::field::{debug, display, Value};
                                let mut iter = meta.fields().iter();
                                meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&call_id)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rcvr_ty)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&error)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expected)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&trait_missing_method
                                                            as &dyn Value))])
                            })
                } else {
                    let span =
                        ::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
                    {};
                    span
                }
            };
        __tracing_attr_guard = __tracing_attr_span.enter();
    }

    #[warn(clippy :: suspicious_else_formatting)]
    {

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