Skip to main content

rustc_trait_selection/error_reporting/infer/
need_type_info.rs

1use std::borrow::Cow;
2use std::iter;
3use std::path::PathBuf;
4
5use rustc_errors::codes::*;
6use rustc_errors::{Diag, IntoDiagArg};
7use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_hir::intravisit::{self, Visitor};
10use rustc_hir::{
11    self as hir, Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource, PatKind,
12};
13use rustc_middle::bug;
14use rustc_middle::hir::nested_filter;
15use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind};
16use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
17use rustc_middle::ty::{
18    self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
19    Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults,
20};
21use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym};
22use tracing::{debug, instrument, warn};
23
24use super::nice_region_error::placeholder_error::Highlighted;
25use crate::error_reporting::TypeErrCtxt;
26use crate::errors::{
27    AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
28    SourceKindMultiSuggestion, SourceKindSubdiag,
29};
30use crate::infer::InferCtxt;
31
32pub enum TypeAnnotationNeeded {
33    /// ```compile_fail,E0282
34    /// let x;
35    /// ```
36    E0282,
37    /// An implementation cannot be chosen unambiguously because of lack of information.
38    /// ```compile_fail,E0790
39    /// let _ = Default::default();
40    /// ```
41    E0283,
42    /// ```compile_fail,E0284
43    /// let mut d: u64 = 2;
44    /// d = d % 1u32.into();
45    /// ```
46    E0284,
47}
48
49impl From<TypeAnnotationNeeded> for ErrCode {
50    fn from(val: TypeAnnotationNeeded) -> Self {
51        match val {
52            TypeAnnotationNeeded::E0282 => E0282,
53            TypeAnnotationNeeded::E0283 => E0283,
54            TypeAnnotationNeeded::E0284 => E0284,
55        }
56    }
57}
58
59/// Information about a constant or a type containing inference variables.
60pub struct InferenceDiagnosticsData {
61    pub name: String,
62    pub span: Option<Span>,
63    pub kind: UnderspecifiedArgKind,
64    pub parent: Option<InferenceDiagnosticsParentData>,
65}
66
67/// Data on the parent definition where a generic argument was declared.
68pub struct InferenceDiagnosticsParentData {
69    prefix: &'static str,
70    name: String,
71}
72
73#[derive(#[automatically_derived]
impl ::core::clone::Clone for UnderspecifiedArgKind {
    #[inline]
    fn clone(&self) -> UnderspecifiedArgKind {
        match self {
            UnderspecifiedArgKind::Type { prefix: __self_0 } =>
                UnderspecifiedArgKind::Type {
                    prefix: ::core::clone::Clone::clone(__self_0),
                },
            UnderspecifiedArgKind::Const { is_parameter: __self_0 } =>
                UnderspecifiedArgKind::Const {
                    is_parameter: ::core::clone::Clone::clone(__self_0),
                },
        }
    }
}Clone)]
74pub enum UnderspecifiedArgKind {
75    Type { prefix: Cow<'static, str> },
76    Const { is_parameter: bool },
77}
78
79impl InferenceDiagnosticsData {
80    fn can_add_more_info(&self) -> bool {
81        !(self.name == "_" && #[allow(non_exhaustive_omitted_patterns)] match self.kind {
    UnderspecifiedArgKind::Type { .. } => true,
    _ => false,
}matches!(self.kind, UnderspecifiedArgKind::Type { .. }))
82    }
83
84    fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
85        if in_type.is_ty_or_numeric_infer() {
86            ""
87        } else if self.name == "_" {
88            // FIXME: Consider specializing this message if there is a single `_`
89            // in the type.
90            "underscore"
91        } else {
92            "has_name"
93        }
94    }
95
96    /// Generate a label for a generic argument which can't be inferred. When not
97    /// much is known about the argument, `use_diag` may be used to describe the
98    /// labeled value.
99    fn make_bad_error(&self, span: Span) -> InferenceBadError<'_> {
100        let has_parent = self.parent.is_some();
101        let bad_kind = if self.can_add_more_info() { "more_info" } else { "other" };
102        let (parent_prefix, parent_name) = self
103            .parent
104            .as_ref()
105            .map(|parent| (parent.prefix, parent.name.clone()))
106            .unwrap_or_default();
107        InferenceBadError {
108            span,
109            bad_kind,
110            prefix_kind: self.kind.clone(),
111            prefix: self.kind.try_get_prefix().unwrap_or_default(),
112            name: self.name.clone(),
113            has_parent,
114            parent_prefix,
115            parent_name,
116        }
117    }
118}
119
120impl InferenceDiagnosticsParentData {
121    fn for_parent_def_id(
122        tcx: TyCtxt<'_>,
123        parent_def_id: DefId,
124    ) -> Option<InferenceDiagnosticsParentData> {
125        let parent_name =
126            tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
127
128        Some(InferenceDiagnosticsParentData {
129            prefix: tcx.def_descr(parent_def_id),
130            name: parent_name,
131        })
132    }
133
134    fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<InferenceDiagnosticsParentData> {
135        Self::for_parent_def_id(tcx, tcx.parent(def_id))
136    }
137}
138
139impl IntoDiagArg for UnderspecifiedArgKind {
140    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
141        let kind = match self {
142            Self::Type { .. } => "type",
143            Self::Const { is_parameter: true } => "const_with_param",
144            Self::Const { is_parameter: false } => "const",
145        };
146        rustc_errors::DiagArgValue::Str(kind.into())
147    }
148}
149
150impl UnderspecifiedArgKind {
151    fn try_get_prefix(&self) -> Option<&str> {
152        match self {
153            Self::Type { prefix } => Some(prefix.as_ref()),
154            Self::Const { .. } => None,
155        }
156    }
157}
158
159struct ClosureEraser<'a, 'tcx> {
160    infcx: &'a InferCtxt<'tcx>,
161}
162
163impl<'a, 'tcx> ClosureEraser<'a, 'tcx> {
164    fn new_infer(&mut self) -> Ty<'tcx> {
165        self.infcx.next_ty_var(DUMMY_SP)
166    }
167}
168
169impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
170    fn cx(&self) -> TyCtxt<'tcx> {
171        self.infcx.tcx
172    }
173
174    fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
175        match ty.kind() {
176            ty::Closure(_, args) => {
177                // For a closure type, we turn it into a function pointer so that it gets rendered
178                // as `fn(args) -> Ret`.
179                let closure_sig = args.as_closure().sig();
180                Ty::new_fn_ptr(
181                    self.cx(),
182                    self.cx().signature_unclosure(closure_sig, hir::Safety::Safe),
183                )
184            }
185            ty::Adt(_, args) if !args.iter().any(|a| a.has_infer()) => {
186                // We have a type that doesn't have any inference variables, so we replace
187                // the whole thing with `_`. The type system already knows about this type in
188                // its entirety and it is redundant to specify it for the user. The user only
189                // needs to specify the type parameters that we *couldn't* figure out.
190                self.new_infer()
191            }
192            ty::Adt(def, args) => {
193                let generics = self.cx().generics_of(def.did());
194                let generics: Vec<bool> = generics
195                    .own_params
196                    .iter()
197                    .map(|param| param.default_value(self.cx()).is_some())
198                    .collect();
199                let ty = Ty::new_adt(
200                    self.cx(),
201                    *def,
202                    self.cx().mk_args_from_iter(generics.into_iter().zip(args.iter()).map(
203                        |(has_default, arg)| {
204                            if arg.has_infer() {
205                                // This param has an unsubstituted type variable, meaning that this
206                                // type has a (potentially deeply nested) type parameter from the
207                                // corresponding type's definition. We have explicitly asked this
208                                // type to not be hidden. In either case, we keep the type and don't
209                                // substitute with `_` just yet.
210                                arg.fold_with(self)
211                            } else if has_default {
212                                // We have a type param that has a default type, like the allocator
213                                // in Vec. We decided to show `Vec` itself, because it hasn't yet
214                                // been replaced by an `_` `Infer`, but we want to ensure that the
215                                // type parameter with default types does *not* get replaced with
216                                // `_` because then we'd end up with `Vec<_, _>`, instead of
217                                // `Vec<_>`.
218                                arg
219                            } else if let GenericArgKind::Type(_) = arg.kind() {
220                                // We don't replace lifetime or const params, only type params.
221                                self.new_infer().into()
222                            } else {
223                                arg.fold_with(self)
224                            }
225                        },
226                    )),
227                );
228                ty
229            }
230            _ if ty.has_infer() => {
231                // This type has a (potentially nested) type parameter that we couldn't figure out.
232                // We will print this depth of type, so at least the type name and at least one of
233                // its type parameters.
234                ty.super_fold_with(self)
235            }
236            // We don't have an unknown type parameter anywhere, replace with `_`.
237            _ => self.new_infer(),
238        }
239    }
240
241    fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
242        // Avoid accidentally erasing the type of the const.
243        c
244    }
245}
246
247fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
248    let mut p = FmtPrinter::new(infcx.tcx, ns);
249    let ty_getter = move |ty_vid| {
250        if infcx.probe_ty_var(ty_vid).is_ok() {
251            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:251",
                        "rustc_trait_selection::error_reporting::infer::need_type_info",
                        ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                        ::tracing_core::__macro_support::Option::Some(251u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::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!("resolved ty var in error message")
                                            as &dyn Value))])
            });
    } else { ; }
};warn!("resolved ty var in error message");
252        }
253
254        let var_origin = infcx.type_var_origin(ty_vid);
255        if let Some(def_id) = var_origin.param_def_id
256            // The `Self` param of a trait has the def-id of the trait,
257            // since it's a synthetic parameter.
258            && infcx.tcx.def_kind(def_id) == DefKind::TyParam
259            && let name = infcx.tcx.item_name(def_id)
260            && !var_origin.span.from_expansion()
261        {
262            let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
263            let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
264            let generic_param_def = generics.param_at(idx as usize, infcx.tcx);
265            if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param_def.kind {
266                None
267            } else {
268                Some(name)
269            }
270        } else {
271            None
272        }
273    };
274    p.ty_infer_name_resolver = Some(Box::new(ty_getter));
275    let const_getter =
276        move |ct_vid| Some(infcx.tcx.item_name(infcx.const_var_origin(ct_vid)?.param_def_id?));
277    p.const_infer_name_resolver = Some(Box::new(const_getter));
278    p
279}
280
281fn ty_to_string<'tcx>(
282    infcx: &InferCtxt<'tcx>,
283    ty: Ty<'tcx>,
284    called_method_def_id: Option<DefId>,
285) -> String {
286    let mut p = fmt_printer(infcx, Namespace::TypeNS);
287    let ty = infcx.resolve_vars_if_possible(ty);
288    // We use `fn` ptr syntax for closures, but this only works when the closure does not capture
289    // anything. We also remove all type parameters that are fully known to the type system.
290    let ty = ty.fold_with(&mut ClosureEraser { infcx });
291
292    match (ty.kind(), called_method_def_id) {
293        // We don't want the regular output for `fn`s because it includes its path in
294        // invalid pseudo-syntax, we want the `fn`-pointer output instead.
295        (ty::FnDef(..), _) => {
296            ty.fn_sig(infcx.tcx).print(&mut p).unwrap();
297            p.into_buffer()
298        }
299        (_, Some(def_id))
300            if ty.is_ty_or_numeric_infer()
301                && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
302        {
303            "Vec<_>".to_string()
304        }
305        _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
306        _ => {
307            ty.print(&mut p).unwrap();
308            p.into_buffer()
309        }
310    }
311}
312
313/// We don't want to directly use `ty_to_string` for closures as their type isn't really
314/// something users are familiar with. Directly printing the `fn_sig` of closures also
315/// doesn't work as they actually use the "rust-call" API.
316fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
317    let ty::Closure(_, args) = ty.kind() else {
318        ::rustc_middle::util::bug::bug_fmt(format_args!("cannot convert non-closure to fn str in `closure_as_fn_str`"))bug!("cannot convert non-closure to fn str in `closure_as_fn_str`")
319    };
320    let fn_sig = args.as_closure().sig();
321    let args = fn_sig
322        .inputs()
323        .skip_binder()
324        .iter()
325        .next()
326        .map(|args| {
327            args.tuple_fields()
328                .iter()
329                .map(|arg| ty_to_string(infcx, arg, None))
330                .collect::<Vec<_>>()
331                .join(", ")
332        })
333        .unwrap_or_default();
334    let ret = if fn_sig.output().skip_binder().is_unit() {
335        String::new()
336    } else {
337        ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!(" -> {0}",
                ty_to_string(infcx, fn_sig.output().skip_binder(), None)))
    })format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
338    };
339    ::alloc::__export::must_use({
        ::alloc::fmt::format(format_args!("fn({0}){1}", args, ret))
    })format!("fn({args}){ret}")
340}
341
342impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
343    /// Extracts data used by diagnostic for either types or constants
344    /// which were stuck during inference.
345    pub fn extract_inference_diagnostics_data(
346        &self,
347        term: Term<'tcx>,
348        highlight: ty::print::RegionHighlightMode<'tcx>,
349    ) -> InferenceDiagnosticsData {
350        let tcx = self.tcx;
351        match term.kind() {
352            TermKind::Ty(ty) => {
353                if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
354                    let var_origin = self.infcx.type_var_origin(ty_vid);
355                    if let Some(def_id) = var_origin.param_def_id
356                        // The `Self` param of a trait has the def-id of the trait,
357                        // since it's a synthetic parameter.
358                        && self.tcx.def_kind(def_id) == DefKind::TyParam
359                        && !var_origin.span.from_expansion()
360                    {
361                        return InferenceDiagnosticsData {
362                            name: self.tcx.item_name(def_id).to_string(),
363                            span: Some(var_origin.span),
364                            kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into() },
365                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
366                        };
367                    }
368                }
369
370                InferenceDiagnosticsData {
371                    name: Highlighted { highlight, ns: Namespace::TypeNS, tcx, value: ty }
372                        .to_string(),
373                    span: None,
374                    kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
375                    parent: None,
376                }
377            }
378            TermKind::Const(ct) => {
379                if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
380                    let origin = self.const_var_origin(vid).expect("expected unresolved const var");
381                    if let Some(def_id) = origin.param_def_id {
382                        return InferenceDiagnosticsData {
383                            name: self.tcx.item_name(def_id).to_string(),
384                            span: Some(origin.span),
385                            kind: UnderspecifiedArgKind::Const { is_parameter: true },
386                            parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
387                        };
388                    }
389
390                    if true {
    if !!origin.span.is_dummy() {
        ::core::panicking::panic("assertion failed: !origin.span.is_dummy()")
    };
};debug_assert!(!origin.span.is_dummy());
391                    InferenceDiagnosticsData {
392                        name: Highlighted { highlight, ns: Namespace::ValueNS, tcx, value: ct }
393                            .to_string(),
394                        span: Some(origin.span),
395                        kind: UnderspecifiedArgKind::Const { is_parameter: false },
396                        parent: None,
397                    }
398                } else {
399                    // If we end up here the `FindInferSourceVisitor`
400                    // won't work, as its expected argument isn't an inference variable.
401                    //
402                    // FIXME: Ideally we should look into the generic constant
403                    // to figure out which inference var is actually unresolved so that
404                    // this path is unreachable.
405                    InferenceDiagnosticsData {
406                        name: Highlighted { highlight, ns: Namespace::ValueNS, tcx, value: ct }
407                            .to_string(),
408                        span: None,
409                        kind: UnderspecifiedArgKind::Const { is_parameter: false },
410                        parent: None,
411                    }
412                }
413            }
414        }
415    }
416
417    /// Used as a fallback in [TypeErrCtxt::emit_inference_failure_err]
418    /// in case we weren't able to get a better error.
419    fn bad_inference_failure_err(
420        &self,
421        span: Span,
422        arg_data: InferenceDiagnosticsData,
423        error_code: TypeAnnotationNeeded,
424    ) -> Diag<'a> {
425        let source_kind = "other";
426        let source_name = "";
427        let failure_span = None;
428        let infer_subdiags = Vec::new();
429        let multi_suggestions = Vec::new();
430        let bad_label = Some(arg_data.make_bad_error(span));
431        match error_code {
432            TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
433                span,
434                source_kind,
435                source_name,
436                failure_span,
437                infer_subdiags,
438                multi_suggestions,
439                bad_label,
440            }),
441            TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
442                span,
443                source_kind,
444                source_name,
445                failure_span,
446                infer_subdiags,
447                multi_suggestions,
448                bad_label,
449            }),
450            TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
451                span,
452                source_kind,
453                source_name,
454                failure_span,
455                infer_subdiags,
456                multi_suggestions,
457                bad_label,
458            }),
459        }
460    }
461
462    #[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("emit_inference_failure_err",
                                    "rustc_trait_selection::error_reporting::infer::need_type_info",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                                    ::tracing_core::__macro_support::Option::Some(462u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                                    ::tracing_core::field::FieldSet::new(&["body_def_id",
                                                    "failure_span", "term", "should_label_span"],
                                        ::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(&body_def_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(&failure_span)
                                                            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(&term)
                                                            as &dyn Value)),
                                                (&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
                                                    ::tracing::__macro_support::Option::Some(&should_label_span
                                                            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: Diag<'a> = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let term = self.resolve_vars_if_possible(term);
            let arg_data =
                self.extract_inference_diagnostics_data(term,
                    ty::print::RegionHighlightMode::default());
            let Some(typeck_results) =
                &self.typeck_results else {
                    return self.bad_inference_failure_err(failure_span,
                            arg_data, error_code);
                };
            let mut local_visitor =
                FindInferSourceVisitor::new(self, typeck_results, term);
            if let Some(body) =
                    self.tcx.hir_maybe_body_owned_by(self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local())
                {
                let expr = body.value;
                local_visitor.visit_expr(expr);
            }
            let Some(InferSource { span, kind }) =
                local_visitor.infer_source else {
                    let silence =
                        if let DefKind::AssocFn = self.tcx.def_kind(body_def_id) &&
                                                                let parent = self.tcx.parent(body_def_id.into()) &&
                                                            self.tcx.is_automatically_derived(parent) &&
                                                        let Some(parent) = parent.as_local() &&
                                                    let hir::Node::Item(item) =
                                                        self.tcx.hir_node_by_def_id(parent) &&
                                                let hir::ItemKind::Impl(imp) = item.kind &&
                                            let hir::TyKind::Path(hir::QPath::Resolved(_, path)) =
                                                imp.self_ty.kind &&
                                        let Res::Def(DefKind::Struct | DefKind::Enum |
                                            DefKind::Union, def_id) = path.res &&
                                    let Some(def_id) = def_id.as_local() &&
                                let hir::Node::Item(item) =
                                    self.tcx.hir_node_by_def_id(def_id) {
                            item.kind.recovered()
                        } else { false };
                    let mut err =
                        self.bad_inference_failure_err(failure_span, arg_data,
                            error_code);
                    if silence { err.downgrade_to_delayed_bug(); }
                    return err;
                };
            let (source_kind, name, long_ty_path) =
                kind.ty_localized_msg(self);
            let failure_span =
                if should_label_span && !failure_span.overlaps(span) {
                    Some(failure_span)
                } else { None };
            let mut infer_subdiags = Vec::new();
            let mut multi_suggestions = Vec::new();
            match kind {
                InferSourceKind::LetBinding {
                    insert_span, pattern_name, ty, def_id } => {
                    infer_subdiags.push(SourceKindSubdiag::LetLike {
                            span: insert_span,
                            name: pattern_name.map(|name|
                                        name.to_string()).unwrap_or_else(String::new),
                            x_kind: arg_data.where_x_is_kind(ty),
                            prefix_kind: arg_data.kind.clone(),
                            prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                            arg_name: arg_data.name,
                            kind: if pattern_name.is_some() {
                                "with_pattern"
                            } else { "other" },
                            type_name: ty_to_string(self, ty, def_id),
                        });
                }
                InferSourceKind::ClosureArg { insert_span, ty, .. } => {
                    infer_subdiags.push(SourceKindSubdiag::LetLike {
                            span: insert_span,
                            name: String::new(),
                            x_kind: arg_data.where_x_is_kind(ty),
                            prefix_kind: arg_data.kind.clone(),
                            prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
                            arg_name: arg_data.name,
                            kind: "closure",
                            type_name: ty_to_string(self, ty, None),
                        });
                }
                InferSourceKind::GenericArg {
                    insert_span,
                    argument_index,
                    generics_def_id,
                    def_id: _,
                    generic_args,
                    have_turbofish } => {
                    let generics = self.tcx.generics_of(generics_def_id);
                    let is_type = term.as_type().is_some();
                    let (parent_exists, parent_prefix, parent_name) =
                        InferenceDiagnosticsParentData::for_parent_def_id(self.tcx,
                                generics_def_id).map_or((false, String::new(),
                                String::new()),
                            |parent|
                                { (true, parent.prefix.to_string(), parent.name) });
                    infer_subdiags.push(SourceKindSubdiag::GenericLabel {
                            span,
                            is_type,
                            param_name: generics.own_params[argument_index].name.to_string(),
                            parent_exists,
                            parent_prefix,
                            parent_name,
                        });
                    let args =
                        if self.tcx.get_diagnostic_item(sym::iterator_collect_fn) ==
                                Some(generics_def_id) {
                            "Vec<_>".to_string()
                        } else {
                            let mut p = fmt_printer(self, Namespace::TypeNS);
                            p.comma_sep(generic_args.iter().copied().map(|arg|
                                            {
                                                if arg.is_suggestable(self.tcx, true) { return arg; }
                                                match arg.kind() {
                                                    GenericArgKind::Lifetime(_) =>
                                                        ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected lifetime")),
                                                    GenericArgKind::Type(_) =>
                                                        self.next_ty_var(DUMMY_SP).into(),
                                                    GenericArgKind::Const(_) =>
                                                        self.next_const_var(DUMMY_SP).into(),
                                                }
                                            })).unwrap();
                            p.into_buffer()
                        };
                    if !have_turbofish {
                        infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
                                span: insert_span,
                                arg_count: generic_args.len(),
                                args,
                            });
                    }
                }
                InferSourceKind::FullyQualifiedMethodCall {
                    receiver, successor, args, def_id } => {
                    let placeholder = Some(self.next_ty_var(DUMMY_SP));
                    if let Some(args) =
                            args.make_suggestable(self.infcx.tcx, true, placeholder) {
                        let mut p = fmt_printer(self, Namespace::ValueNS);
                        p.print_def_path(def_id, args).unwrap();
                        let def_path = p.into_buffer();
                        let adjustment =
                            match typeck_results.expr_adjustments(receiver) {
                                [Adjustment {
                                    kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ },
                                    .., Adjustment {
                                    kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ }] =>
                                    "",
                                [.., Adjustment {
                                    kind: Adjust::Borrow(AutoBorrow::Ref(mut_)), target: _ }] =>
                                    hir::Mutability::from(*mut_).ref_prefix_str(),
                                _ => "",
                            };
                        multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified(receiver.span,
                                def_path, adjustment, successor));
                    }
                }
                InferSourceKind::ClosureReturn { ty, data, should_wrap_expr }
                    => {
                    let placeholder = Some(self.next_ty_var(DUMMY_SP));
                    if let Some(ty) =
                            ty.make_suggestable(self.infcx.tcx, true, placeholder) {
                        let ty_info = ty_to_string(self, ty, None);
                        multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(ty_info,
                                data, should_wrap_expr));
                    }
                }
            }
            let mut err =
                match error_code {
                    TypeAnnotationNeeded::E0282 =>
                        self.dcx().create_err(AnnotationRequired {
                                span,
                                source_kind,
                                source_name: &name,
                                failure_span,
                                infer_subdiags,
                                multi_suggestions,
                                bad_label: None,
                            }),
                    TypeAnnotationNeeded::E0283 =>
                        self.dcx().create_err(AmbiguousImpl {
                                span,
                                source_kind,
                                source_name: &name,
                                failure_span,
                                infer_subdiags,
                                multi_suggestions,
                                bad_label: None,
                            }),
                    TypeAnnotationNeeded::E0284 =>
                        self.dcx().create_err(AmbiguousReturn {
                                span,
                                source_kind,
                                source_name: &name,
                                failure_span,
                                infer_subdiags,
                                multi_suggestions,
                                bad_label: None,
                            }),
                };
            *err.long_ty_path() = long_ty_path;
            if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } =
                    kind {
                err.downgrade_to_delayed_bug();
            }
            err
        }
    }
}#[instrument(level = "debug", skip(self, error_code))]
463    pub fn emit_inference_failure_err(
464        &self,
465        body_def_id: LocalDefId,
466        failure_span: Span,
467        term: Term<'tcx>,
468        error_code: TypeAnnotationNeeded,
469        should_label_span: bool,
470    ) -> Diag<'a> {
471        let term = self.resolve_vars_if_possible(term);
472        let arg_data = self
473            .extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default());
474
475        let Some(typeck_results) = &self.typeck_results else {
476            // If we don't have any typeck results we're outside
477            // of a body, so we won't be able to get better info
478            // here.
479            return self.bad_inference_failure_err(failure_span, arg_data, error_code);
480        };
481
482        let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term);
483        if let Some(body) = self.tcx.hir_maybe_body_owned_by(
484            self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
485        ) {
486            let expr = body.value;
487            local_visitor.visit_expr(expr);
488        }
489
490        let Some(InferSource { span, kind }) = local_visitor.infer_source else {
491            let silence = if let DefKind::AssocFn = self.tcx.def_kind(body_def_id)
492                && let parent = self.tcx.parent(body_def_id.into())
493                && self.tcx.is_automatically_derived(parent)
494                && let Some(parent) = parent.as_local()
495                && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(parent)
496                && let hir::ItemKind::Impl(imp) = item.kind
497                && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = imp.self_ty.kind
498                && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, def_id) = path.res
499                && let Some(def_id) = def_id.as_local()
500                && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(def_id)
501            {
502                // We have encountered an inference error within an automatically derived `impl`,
503                // from a `#[derive(..)]` on an item that had a parse error. Because the parse
504                // error might have caused the expanded code to be malformed, we silence the
505                // inference error.
506                item.kind.recovered()
507            } else {
508                false
509            };
510            let mut err = self.bad_inference_failure_err(failure_span, arg_data, error_code);
511            if silence {
512                err.downgrade_to_delayed_bug();
513            }
514            return err;
515        };
516
517        let (source_kind, name, long_ty_path) = kind.ty_localized_msg(self);
518        let failure_span = if should_label_span && !failure_span.overlaps(span) {
519            Some(failure_span)
520        } else {
521            None
522        };
523
524        let mut infer_subdiags = Vec::new();
525        let mut multi_suggestions = Vec::new();
526        match kind {
527            InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
528                infer_subdiags.push(SourceKindSubdiag::LetLike {
529                    span: insert_span,
530                    name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
531                    x_kind: arg_data.where_x_is_kind(ty),
532                    prefix_kind: arg_data.kind.clone(),
533                    prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
534                    arg_name: arg_data.name,
535                    kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
536                    type_name: ty_to_string(self, ty, def_id),
537                });
538            }
539            InferSourceKind::ClosureArg { insert_span, ty, .. } => {
540                infer_subdiags.push(SourceKindSubdiag::LetLike {
541                    span: insert_span,
542                    name: String::new(),
543                    x_kind: arg_data.where_x_is_kind(ty),
544                    prefix_kind: arg_data.kind.clone(),
545                    prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
546                    arg_name: arg_data.name,
547                    kind: "closure",
548                    type_name: ty_to_string(self, ty, None),
549                });
550            }
551            InferSourceKind::GenericArg {
552                insert_span,
553                argument_index,
554                generics_def_id,
555                def_id: _,
556                generic_args,
557                have_turbofish,
558            } => {
559                let generics = self.tcx.generics_of(generics_def_id);
560                let is_type = term.as_type().is_some();
561
562                let (parent_exists, parent_prefix, parent_name) =
563                    InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id)
564                        .map_or((false, String::new(), String::new()), |parent| {
565                            (true, parent.prefix.to_string(), parent.name)
566                        });
567
568                infer_subdiags.push(SourceKindSubdiag::GenericLabel {
569                    span,
570                    is_type,
571                    param_name: generics.own_params[argument_index].name.to_string(),
572                    parent_exists,
573                    parent_prefix,
574                    parent_name,
575                });
576
577                let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn)
578                    == Some(generics_def_id)
579                {
580                    "Vec<_>".to_string()
581                } else {
582                    let mut p = fmt_printer(self, Namespace::TypeNS);
583                    p.comma_sep(generic_args.iter().copied().map(|arg| {
584                        if arg.is_suggestable(self.tcx, true) {
585                            return arg;
586                        }
587
588                        match arg.kind() {
589                            GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
590                            GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
591                            GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
592                        }
593                    }))
594                    .unwrap();
595                    p.into_buffer()
596                };
597
598                if !have_turbofish {
599                    infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
600                        span: insert_span,
601                        arg_count: generic_args.len(),
602                        args,
603                    });
604                }
605            }
606            InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
607                let placeholder = Some(self.next_ty_var(DUMMY_SP));
608                if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
609                    let mut p = fmt_printer(self, Namespace::ValueNS);
610                    p.print_def_path(def_id, args).unwrap();
611                    let def_path = p.into_buffer();
612
613                    // We only care about whether we have to add `&` or `&mut ` for now.
614                    // This is the case if the last adjustment is a borrow and the
615                    // first adjustment was not a builtin deref.
616                    let adjustment = match typeck_results.expr_adjustments(receiver) {
617                        [
618                            Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ },
619                            ..,
620                            Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ },
621                        ] => "",
622                        [
623                            ..,
624                            Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mut_)), target: _ },
625                        ] => hir::Mutability::from(*mut_).ref_prefix_str(),
626                        _ => "",
627                    };
628
629                    multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified(
630                        receiver.span,
631                        def_path,
632                        adjustment,
633                        successor,
634                    ));
635                }
636            }
637            InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
638                let placeholder = Some(self.next_ty_var(DUMMY_SP));
639                if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
640                    let ty_info = ty_to_string(self, ty, None);
641                    multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
642                        ty_info,
643                        data,
644                        should_wrap_expr,
645                    ));
646                }
647            }
648        }
649        let mut err = match error_code {
650            TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
651                span,
652                source_kind,
653                source_name: &name,
654                failure_span,
655                infer_subdiags,
656                multi_suggestions,
657                bad_label: None,
658            }),
659            TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
660                span,
661                source_kind,
662                source_name: &name,
663                failure_span,
664                infer_subdiags,
665                multi_suggestions,
666                bad_label: None,
667            }),
668            TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
669                span,
670                source_kind,
671                source_name: &name,
672                failure_span,
673                infer_subdiags,
674                multi_suggestions,
675                bad_label: None,
676            }),
677        };
678        *err.long_ty_path() = long_ty_path;
679        if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } = kind {
680            // We will have already emitted an error about this pattern.
681            err.downgrade_to_delayed_bug();
682        }
683        err
684    }
685}
686
687#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InferSource<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field2_finish(f, "InferSource",
            "span", &self.span, "kind", &&self.kind)
    }
}Debug)]
688struct InferSource<'tcx> {
689    span: Span,
690    kind: InferSourceKind<'tcx>,
691}
692
693#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InferSourceKind<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            InferSourceKind::LetBinding {
                insert_span: __self_0,
                pattern_name: __self_1,
                ty: __self_2,
                def_id: __self_3 } =>
                ::core::fmt::Formatter::debug_struct_field4_finish(f,
                    "LetBinding", "insert_span", __self_0, "pattern_name",
                    __self_1, "ty", __self_2, "def_id", &__self_3),
            InferSourceKind::ClosureArg {
                insert_span: __self_0, ty: __self_1, kind: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "ClosureArg", "insert_span", __self_0, "ty", __self_1,
                    "kind", &__self_2),
            InferSourceKind::GenericArg {
                insert_span: __self_0,
                argument_index: __self_1,
                generics_def_id: __self_2,
                def_id: __self_3,
                generic_args: __self_4,
                have_turbofish: __self_5 } => {
                let names: &'static _ =
                    &["insert_span", "argument_index", "generics_def_id",
                                "def_id", "generic_args", "have_turbofish"];
                let values: &[&dyn ::core::fmt::Debug] =
                    &[__self_0, __self_1, __self_2, __self_3, __self_4,
                                &__self_5];
                ::core::fmt::Formatter::debug_struct_fields_finish(f,
                    "GenericArg", names, values)
            }
            InferSourceKind::FullyQualifiedMethodCall {
                receiver: __self_0,
                successor: __self_1,
                args: __self_2,
                def_id: __self_3 } =>
                ::core::fmt::Formatter::debug_struct_field4_finish(f,
                    "FullyQualifiedMethodCall", "receiver", __self_0,
                    "successor", __self_1, "args", __self_2, "def_id",
                    &__self_3),
            InferSourceKind::ClosureReturn {
                ty: __self_0, data: __self_1, should_wrap_expr: __self_2 } =>
                ::core::fmt::Formatter::debug_struct_field3_finish(f,
                    "ClosureReturn", "ty", __self_0, "data", __self_1,
                    "should_wrap_expr", &__self_2),
        }
    }
}Debug)]
694enum InferSourceKind<'tcx> {
695    LetBinding {
696        insert_span: Span,
697        pattern_name: Option<Ident>,
698        ty: Ty<'tcx>,
699        def_id: Option<DefId>,
700    },
701    ClosureArg {
702        insert_span: Span,
703        ty: Ty<'tcx>,
704        kind: PatKind<'tcx>,
705    },
706    GenericArg {
707        insert_span: Span,
708        argument_index: usize,
709        generics_def_id: DefId,
710        def_id: DefId,
711        generic_args: &'tcx [GenericArg<'tcx>],
712        have_turbofish: bool,
713    },
714    FullyQualifiedMethodCall {
715        receiver: &'tcx Expr<'tcx>,
716        /// If the method has other arguments, this is ", " and the start of the first argument,
717        /// while for methods without arguments this is ")" and the end of the method call.
718        successor: (&'static str, BytePos),
719        args: GenericArgsRef<'tcx>,
720        def_id: DefId,
721    },
722    ClosureReturn {
723        ty: Ty<'tcx>,
724        data: &'tcx FnRetTy<'tcx>,
725        should_wrap_expr: Option<Span>,
726    },
727}
728
729impl<'tcx> InferSource<'tcx> {
730    fn from_expansion(&self) -> bool {
731        let source_from_expansion = match self.kind {
732            InferSourceKind::LetBinding { insert_span, .. }
733            | InferSourceKind::ClosureArg { insert_span, .. }
734            | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(),
735            InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => {
736                receiver.span.from_expansion()
737            }
738            InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
739                data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
740            }
741        };
742        source_from_expansion || self.span.from_expansion()
743    }
744}
745
746impl<'tcx> InferSourceKind<'tcx> {
747    fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
748        let mut long_ty_path = None;
749        match *self {
750            InferSourceKind::LetBinding { ty, .. }
751            | InferSourceKind::ClosureArg { ty, .. }
752            | InferSourceKind::ClosureReturn { ty, .. } => {
753                if ty.is_closure() {
754                    ("closure", closure_as_fn_str(infcx, ty), long_ty_path)
755                } else if !ty.is_ty_or_numeric_infer() {
756                    ("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
757                } else {
758                    ("other", String::new(), long_ty_path)
759                }
760            }
761            // FIXME: We should be able to add some additional info here.
762            InferSourceKind::GenericArg { .. }
763            | InferSourceKind::FullyQualifiedMethodCall { .. } => {
764                ("other", String::new(), long_ty_path)
765            }
766        }
767    }
768}
769
770#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InsertableGenericArgs<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::debug_struct_field5_finish(f,
            "InsertableGenericArgs", "insert_span", &self.insert_span, "args",
            &self.args, "generics_def_id", &self.generics_def_id, "def_id",
            &self.def_id, "have_turbofish", &&self.have_turbofish)
    }
}Debug)]
771struct InsertableGenericArgs<'tcx> {
772    insert_span: Span,
773    args: GenericArgsRef<'tcx>,
774    generics_def_id: DefId,
775    def_id: DefId,
776    have_turbofish: bool,
777}
778
779/// A visitor which searches for the "best" spot to use in the inference error.
780///
781/// For this it walks over the hir body and tries to check all places where
782/// inference variables could be bound.
783///
784/// While doing so, the currently best spot is stored in `infer_source`.
785/// For details on how we rank spots, see [Self::source_cost]
786struct FindInferSourceVisitor<'a, 'tcx> {
787    tecx: &'a TypeErrCtxt<'a, 'tcx>,
788    typeck_results: &'a TypeckResults<'tcx>,
789
790    target: Term<'tcx>,
791
792    attempt: usize,
793    infer_source_cost: usize,
794    infer_source: Option<InferSource<'tcx>>,
795}
796
797impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
798    fn new(
799        tecx: &'a TypeErrCtxt<'a, 'tcx>,
800        typeck_results: &'a TypeckResults<'tcx>,
801        target: Term<'tcx>,
802    ) -> Self {
803        FindInferSourceVisitor {
804            tecx,
805            typeck_results,
806
807            target,
808
809            attempt: 0,
810            infer_source_cost: usize::MAX,
811            infer_source: None,
812        }
813    }
814
815    /// Computes cost for the given source.
816    ///
817    /// Sources with a small cost are prefer and should result
818    /// in a clearer and idiomatic suggestion.
819    fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
820        #[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for CostCtxt<'tcx> {
    #[inline]
    fn clone(&self) -> CostCtxt<'tcx> {
        let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
        *self
    }
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for CostCtxt<'tcx> { }Copy)]
821        struct CostCtxt<'tcx> {
822            tcx: TyCtxt<'tcx>,
823        }
824        impl<'tcx> CostCtxt<'tcx> {
825            fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
826                match arg.kind() {
827                    GenericArgKind::Lifetime(_) => 0, // erased
828                    GenericArgKind::Type(ty) => self.ty_cost(ty),
829                    GenericArgKind::Const(_) => 3, // some non-zero value
830                }
831            }
832            fn ty_cost(self, ty: Ty<'tcx>) -> usize {
833                match *ty.kind() {
834                    ty::Closure(..) => 1000,
835                    ty::FnDef(..) => 150,
836                    ty::FnPtr(..) => 30,
837                    ty::Adt(def, args) => {
838                        5 + self
839                            .tcx
840                            .generics_of(def.did())
841                            .own_args_no_defaults(self.tcx, args)
842                            .iter()
843                            .map(|&arg| self.arg_cost(arg))
844                            .sum::<usize>()
845                    }
846                    ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(),
847                    ty::Ref(_, ty, _) => 2 + self.ty_cost(ty),
848                    ty::Infer(..) => 0,
849                    _ => 1,
850                }
851            }
852        }
853
854        // The sources are listed in order of preference here.
855        let tcx = self.tecx.tcx;
856        let ctx = CostCtxt { tcx };
857        match source.kind {
858            InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
859            InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
860            InferSourceKind::GenericArg { def_id, generic_args, .. } => {
861                let variant_cost = match tcx.def_kind(def_id) {
862                    // `None::<u32>` and friends are ugly.
863                    DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15,
864                    _ => 10,
865                };
866                variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
867            }
868            InferSourceKind::FullyQualifiedMethodCall { args, .. } => {
869                20 + args.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
870            }
871            InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
872                30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
873            }
874        }
875    }
876
877    /// Uses `fn source_cost` to determine whether this inference source is preferable to
878    /// previous sources. We generally prefer earlier sources.
879    #[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("update_infer_source",
                                    "rustc_trait_selection::error_reporting::infer::need_type_info",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                                    ::tracing_core::__macro_support::Option::Some(879u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                                    ::tracing_core::field::FieldSet::new(&["new_source"],
                                        ::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(&new_source)
                                                            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: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            if new_source.from_expansion() { return; }
            let cost = self.source_cost(&new_source) + self.attempt;
            {
                use ::tracing::__macro_support::Callsite as _;
                static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                    {
                        static META: ::tracing::Metadata<'static> =
                            {
                                ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:886",
                                    "rustc_trait_selection::error_reporting::infer::need_type_info",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                                    ::tracing_core::__macro_support::Option::Some(886u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                                    ::tracing_core::field::FieldSet::new(&["cost"],
                                        ::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(&debug(&cost) as
                                                        &dyn Value))])
                        });
                } else { ; }
            };
            self.attempt += 1;
            if let Some(InferSource {
                            kind: InferSourceKind::GenericArg { def_id: did, .. }, .. })
                            = self.infer_source &&
                        let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..
                            } = new_source.kind && ty.is_ty_or_numeric_infer() {
                *def_id = Some(did);
            }
            if cost < self.infer_source_cost {
                self.infer_source_cost = cost;
                self.infer_source = Some(new_source);
            }
        }
    }
}#[instrument(level = "debug", skip(self))]
880    fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
881        if new_source.from_expansion() {
882            return;
883        }
884
885        let cost = self.source_cost(&new_source) + self.attempt;
886        debug!(?cost);
887        self.attempt += 1;
888        if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, .. }, .. }) =
889            self.infer_source
890            && let InferSourceKind::LetBinding { ref ty, ref mut def_id, .. } = new_source.kind
891            && ty.is_ty_or_numeric_infer()
892        {
893            // Customize the output so we talk about `let x: Vec<_> = iter.collect();` instead of
894            // `let x: _ = iter.collect();`, as this is a very common case.
895            *def_id = Some(did);
896        }
897
898        if cost < self.infer_source_cost {
899            self.infer_source_cost = cost;
900            self.infer_source = Some(new_source);
901        }
902    }
903
904    fn node_args_opt(&self, hir_id: HirId) -> Option<GenericArgsRef<'tcx>> {
905        let args = self.typeck_results.node_args_opt(hir_id);
906        self.tecx.resolve_vars_if_possible(args)
907    }
908
909    fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
910        let ty = self.typeck_results.node_type_opt(hir_id);
911        self.tecx.resolve_vars_if_possible(ty)
912    }
913
914    // Check whether this generic argument is the inference variable we
915    // are looking for.
916    fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool {
917        if arg == self.target.into() {
918            return true;
919        }
920
921        match (arg.kind(), self.target.kind()) {
922            (GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => {
923                use ty::{Infer, TyVar};
924                match (inner_ty.kind(), target_ty.kind()) {
925                    (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
926                        self.tecx.sub_unification_table_root_var(a_vid)
927                            == self.tecx.sub_unification_table_root_var(b_vid)
928                    }
929                    _ => false,
930                }
931            }
932            (GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => {
933                match (inner_ct.kind(), target_ct.kind()) {
934                    (
935                        ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
936                        ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
937                    ) => self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid),
938                    _ => false,
939                }
940            }
941            _ => false,
942        }
943    }
944
945    /// Does this generic argument contain our target inference variable
946    /// in a way which can be written by the user.
947    fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool {
948        let mut walker = arg.walk();
949        while let Some(inner) = walker.next() {
950            if self.generic_arg_is_target(inner) {
951                return true;
952            }
953            match inner.kind() {
954                GenericArgKind::Lifetime(_) => {}
955                GenericArgKind::Type(ty) => {
956                    if #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
    ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::CoroutineClosure(..) |
        ty::Coroutine(..) => true,
    _ => false,
}matches!(
957                        ty.kind(),
958                        ty::Alias(ty::Opaque, ..)
959                            | ty::Closure(..)
960                            | ty::CoroutineClosure(..)
961                            | ty::Coroutine(..)
962                    ) {
963                        // Opaque types can't be named by the user right now.
964                        //
965                        // Both the generic arguments of closures and coroutines can
966                        // also not be named. We may want to only look into the closure
967                        // signature in case it has no captures, as that can be represented
968                        // using `fn(T) -> R`.
969
970                        // FIXME(type_alias_impl_trait): These opaque types
971                        // can actually be named, so it would make sense to
972                        // adjust this case and add a test for it.
973                        walker.skip_current_subtree();
974                    }
975                }
976                GenericArgKind::Const(ct) => {
977                    if #[allow(non_exhaustive_omitted_patterns)] match ct.kind() {
    ty::ConstKind::Unevaluated(..) => true,
    _ => false,
}matches!(ct.kind(), ty::ConstKind::Unevaluated(..)) {
978                        // You can't write the generic arguments for
979                        // unevaluated constants.
980                        walker.skip_current_subtree();
981                    }
982                }
983            }
984        }
985        false
986    }
987
988    fn expr_inferred_arg_iter(
989        &self,
990        expr: &'tcx hir::Expr<'tcx>,
991    ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
992        let tcx = self.tecx.tcx;
993        match expr.kind {
994            hir::ExprKind::Path(ref path) => {
995                if let Some(args) = self.node_args_opt(expr.hir_id) {
996                    return self.path_inferred_arg_iter(expr.hir_id, args, path);
997                }
998            }
999            // FIXME(#98711): Ideally we would also deal with type relative
1000            // paths here, even if that is quite rare.
1001            //
1002            // See the `need_type_info/expr-struct-type-relative-gat.rs` test
1003            // for an example where that would be needed.
1004            //
1005            // However, the `type_dependent_def_id` for `Self::Output` in an
1006            // impl is currently the `DefId` of `Output` in the trait definition
1007            // which makes this somewhat difficult and prevents us from just
1008            // using `self.path_inferred_arg_iter` here.
1009            hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
1010            // FIXME(TaKO8Ki): Ideally we should support other kinds,
1011            // such as `TyAlias` or `AssocTy`. For that we have to map
1012            // back from the self type to the type alias though. That's difficult.
1013            //
1014            // See the `need_type_info/issue-103053.rs` test for
1015            // a example.
1016            if #[allow(non_exhaustive_omitted_patterns)] match path.res {
    Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => true,
    _ => false,
}matches!(path.res, Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) => {
1017                if let Some(ty) = self.opt_node_type(expr.hir_id)
1018                    && let ty::Adt(_, args) = ty.kind()
1019                {
1020                    return Box::new(self.resolved_path_inferred_arg_iter(path, args));
1021                }
1022            }
1023            hir::ExprKind::MethodCall(segment, ..) => {
1024                if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) {
1025                    let generics = tcx.generics_of(def_id);
1026                    let insertable = try {
1027                        if generics.has_impl_trait() {
1028                            None?
1029                        }
1030                        let args = self.node_args_opt(expr.hir_id)?;
1031                        let span = tcx.hir_span(segment.hir_id);
1032                        let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1033                        InsertableGenericArgs {
1034                            insert_span,
1035                            args,
1036                            generics_def_id: def_id,
1037                            def_id,
1038                            have_turbofish: false,
1039                        }
1040                    };
1041                    return Box::new(insertable.into_iter());
1042                }
1043            }
1044            _ => {}
1045        }
1046
1047        Box::new(iter::empty())
1048    }
1049
1050    fn resolved_path_inferred_arg_iter(
1051        &self,
1052        path: &'tcx hir::Path<'tcx>,
1053        args: GenericArgsRef<'tcx>,
1054    ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'tcx {
1055        let tcx = self.tecx.tcx;
1056        let have_turbofish = path.segments.iter().any(|segment| {
1057            segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
1058        });
1059        // The last segment of a path often has `Res::Err` and the
1060        // correct `Res` is the one of the whole path.
1061        //
1062        // FIXME: We deal with that one separately for now,
1063        // would be good to remove this special case.
1064        let last_segment_using_path_data = try {
1065            let generics_def_id = tcx.res_generics_def_id(path.res)?;
1066            let generics = tcx.generics_of(generics_def_id);
1067            if generics.has_impl_trait() {
1068                do yeet ();
1069            }
1070            let insert_span =
1071                path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi());
1072            InsertableGenericArgs {
1073                insert_span,
1074                args,
1075                generics_def_id,
1076                def_id: path.res.def_id(),
1077                have_turbofish,
1078            }
1079        };
1080
1081        path.segments
1082            .iter()
1083            .filter_map(move |segment| {
1084                let res = segment.res;
1085                let generics_def_id = tcx.res_generics_def_id(res)?;
1086                let generics = tcx.generics_of(generics_def_id);
1087                if generics.has_impl_trait() {
1088                    return None;
1089                }
1090                let span = tcx.hir_span(segment.hir_id);
1091                let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1092                Some(InsertableGenericArgs {
1093                    insert_span,
1094                    args,
1095                    generics_def_id,
1096                    def_id: res.def_id(),
1097                    have_turbofish,
1098                })
1099            })
1100            .chain(last_segment_using_path_data)
1101    }
1102
1103    fn path_inferred_arg_iter(
1104        &self,
1105        hir_id: HirId,
1106        args: GenericArgsRef<'tcx>,
1107        qpath: &'tcx hir::QPath<'tcx>,
1108    ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
1109        let tcx = self.tecx.tcx;
1110        match qpath {
1111            hir::QPath::Resolved(_self_ty, path) => {
1112                Box::new(self.resolved_path_inferred_arg_iter(path, args))
1113            }
1114            hir::QPath::TypeRelative(ty, segment) => {
1115                let Some(def_id) = self.typeck_results.type_dependent_def_id(hir_id) else {
1116                    return Box::new(iter::empty());
1117                };
1118
1119                let generics = tcx.generics_of(def_id);
1120                let segment = if !segment.infer_args || generics.has_impl_trait() {
1121                    None
1122                } else {
1123                    let span = tcx.hir_span(segment.hir_id);
1124                    let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1125                    Some(InsertableGenericArgs {
1126                        insert_span,
1127                        args,
1128                        generics_def_id: def_id,
1129                        def_id,
1130                        have_turbofish: false,
1131                    })
1132                };
1133
1134                let parent_def_id = generics.parent.unwrap();
1135                if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
1136                    let parent_ty = tcx.type_of(parent_def_id).instantiate(tcx, args);
1137                    match (parent_ty.kind(), &ty.kind) {
1138                        (
1139                            ty::Adt(def, args),
1140                            hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
1141                        ) => {
1142                            if tcx.res_generics_def_id(path.res) != Some(def.did()) {
1143                                match path.res {
1144                                    Res::Def(DefKind::TyAlias, _) => {
1145                                        // FIXME: Ideally we should support this. For that
1146                                        // we have to map back from the self type to the
1147                                        // type alias though. That's difficult.
1148                                        //
1149                                        // See the `need_type_info/type-alias.rs` test for
1150                                        // some examples.
1151                                    }
1152                                    // There cannot be inference variables in the self type,
1153                                    // so there's nothing for us to do here.
1154                                    Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
1155                                    _ => {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1155",
                        "rustc_trait_selection::error_reporting::infer::need_type_info",
                        ::tracing::Level::WARN,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                        ::tracing_core::__macro_support::Option::Some(1155u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                        ::tracing_core::field::FieldSet::new(&["message"],
                            ::tracing_core::callsite::Identifier(&__CALLSITE)),
                        ::tracing::metadata::Kind::EVENT)
                };
            ::tracing::callsite::DefaultCallsite::new(&META)
        };
    let enabled =
        ::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
                &&
                ::tracing::Level::WARN <=
                    ::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!("unexpected path: def={0:?} args={1:?} path={2:?}",
                                                    def, args, path) as &dyn Value))])
            });
    } else { ; }
}warn!(
1156                                        "unexpected path: def={:?} args={:?} path={:?}",
1157                                        def, args, path,
1158                                    ),
1159                                }
1160                            } else {
1161                                return Box::new(
1162                                    self.resolved_path_inferred_arg_iter(path, args).chain(segment),
1163                                );
1164                            }
1165                        }
1166                        _ => (),
1167                    }
1168                }
1169
1170                Box::new(segment.into_iter())
1171            }
1172        }
1173    }
1174}
1175
1176impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
1177    type NestedFilter = nested_filter::OnlyBodies;
1178
1179    fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
1180        self.tecx.tcx
1181    }
1182
1183    fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
1184        intravisit::walk_local(self, local);
1185
1186        if let Some(ty) = self.opt_node_type(local.hir_id) {
1187            if self.generic_arg_contains_target(ty.into()) {
1188                match local.source {
1189                    LocalSource::Normal if local.ty.is_none() => {
1190                        self.update_infer_source(InferSource {
1191                            span: local.pat.span,
1192                            kind: InferSourceKind::LetBinding {
1193                                insert_span: local.pat.span.shrink_to_hi(),
1194                                pattern_name: local.pat.simple_ident(),
1195                                ty,
1196                                def_id: None,
1197                            },
1198                        })
1199                    }
1200                    _ => {}
1201                }
1202            }
1203        }
1204    }
1205
1206    /// For closures, we first visit the parameters and then the content,
1207    /// as we prefer those.
1208    fn visit_body(&mut self, body: &Body<'tcx>) {
1209        for param in body.params {
1210            {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1210",
                        "rustc_trait_selection::error_reporting::infer::need_type_info",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                        ::tracing_core::__macro_support::Option::Some(1210u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                        ::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!("param: span {0:?}, ty_span {1:?}, pat.span {2:?}",
                                                    param.span, param.ty_span, param.pat.span) as &dyn Value))])
            });
    } else { ; }
};debug!(
1211                "param: span {:?}, ty_span {:?}, pat.span {:?}",
1212                param.span, param.ty_span, param.pat.span
1213            );
1214            if param.ty_span != param.pat.span {
1215                {
    use ::tracing::__macro_support::Callsite as _;
    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
        {
            static META: ::tracing::Metadata<'static> =
                {
                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1215",
                        "rustc_trait_selection::error_reporting::infer::need_type_info",
                        ::tracing::Level::DEBUG,
                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                        ::tracing_core::__macro_support::Option::Some(1215u32),
                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                        ::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!("skipping param: has explicit type")
                                            as &dyn Value))])
            });
    } else { ; }
};debug!("skipping param: has explicit type");
1216                continue;
1217            }
1218
1219            let Some(param_ty) = self.opt_node_type(param.hir_id) else { continue };
1220
1221            if self.generic_arg_contains_target(param_ty.into()) {
1222                self.update_infer_source(InferSource {
1223                    span: param.pat.span,
1224                    kind: InferSourceKind::ClosureArg {
1225                        insert_span: param.pat.span.shrink_to_hi(),
1226                        ty: param_ty,
1227                        kind: param.pat.kind,
1228                    },
1229                })
1230            }
1231        }
1232        intravisit::walk_body(self, body);
1233    }
1234
1235    #[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("visit_expr",
                                    "rustc_trait_selection::error_reporting::infer::need_type_info",
                                    ::tracing::Level::DEBUG,
                                    ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                                    ::tracing_core::__macro_support::Option::Some(1235u32),
                                    ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                                    ::tracing_core::field::FieldSet::new(&["expr"],
                                        ::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(&expr)
                                                            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: () = loop {};
            return __tracing_attr_fake_return;
        }
        {
            let tcx = self.tecx.tcx;
            match expr.kind {
                ExprKind::Call(func, args) => {
                    for arg in args { self.visit_expr(arg); }
                    self.visit_expr(func);
                }
                _ => intravisit::walk_expr(self, expr),
            }
            for args in self.expr_inferred_arg_iter(expr) {
                {
                    use ::tracing::__macro_support::Callsite as _;
                    static __CALLSITE: ::tracing::callsite::DefaultCallsite =
                        {
                            static META: ::tracing::Metadata<'static> =
                                {
                                    ::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1251",
                                        "rustc_trait_selection::error_reporting::infer::need_type_info",
                                        ::tracing::Level::DEBUG,
                                        ::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
                                        ::tracing_core::__macro_support::Option::Some(1251u32),
                                        ::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
                                        ::tracing_core::field::FieldSet::new(&["args"],
                                            ::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(&debug(&args) as
                                                            &dyn Value))])
                            });
                    } else { ; }
                };
                let InsertableGenericArgs {
                        insert_span, args, generics_def_id, def_id, have_turbofish
                        } = args;
                let generics = tcx.generics_of(generics_def_id);
                if let Some(mut argument_index) =
                        generics.own_args(args).iter().position(|&arg|
                                self.generic_arg_contains_target(arg)) {
                    if generics.has_own_self() { argument_index += 1; }
                    let args = self.tecx.resolve_vars_if_possible(args);
                    let generic_args =
                        &generics.own_args_no_defaults(tcx,
                                    args)[generics.own_counts().lifetimes..];
                    let span =
                        match expr.kind {
                            ExprKind::MethodCall(path, ..) => path.ident.span,
                            _ => expr.span,
                        };
                    self.update_infer_source(InferSource {
                            span,
                            kind: InferSourceKind::GenericArg {
                                insert_span,
                                argument_index,
                                generics_def_id,
                                def_id,
                                generic_args,
                                have_turbofish,
                            },
                        });
                }
            }
            if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
                if let (&ExprKind::Closure(&Closure {
                        fn_decl, body, fn_decl_span, .. }), ty::Closure(_, args)) =
                        (&expr.kind, node_ty.kind()) {
                    let output = args.as_closure().sig().output().skip_binder();
                    if self.generic_arg_contains_target(output.into()) {
                        let body = self.tecx.tcx.hir_body(body);
                        let should_wrap_expr =
                            if #[allow(non_exhaustive_omitted_patterns)] match body.value.kind
                                    {
                                    ExprKind::Block(..) => true,
                                    _ => false,
                                } {
                                None
                            } else { Some(body.value.span.shrink_to_hi()) };
                        self.update_infer_source(InferSource {
                                span: fn_decl_span,
                                kind: InferSourceKind::ClosureReturn {
                                    ty: output,
                                    data: &fn_decl.output,
                                    should_wrap_expr,
                                },
                            })
                    }
                }
            }
            let has_impl_trait =
                |def_id|
                    {
                        iter::successors(Some(tcx.generics_of(def_id)),
                                |generics|
                                    {
                                        generics.parent.map(|def_id| tcx.generics_of(def_id))
                                    }).any(|generics| generics.has_impl_trait())
                    };
            if let ExprKind::MethodCall(path, receiver, method_args, span) =
                                            expr.kind &&
                                        let Some(args) = self.node_args_opt(expr.hir_id) &&
                                    args.iter().any(|arg| self.generic_arg_contains_target(arg))
                                &&
                                let Some(def_id) =
                                    self.typeck_results.type_dependent_def_id(expr.hir_id) &&
                            self.tecx.tcx.trait_of_assoc(def_id).is_some() &&
                        !has_impl_trait(def_id) &&
                    tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
                {
                let successor =
                    method_args.get(0).map_or_else(|| (")", span.hi()),
                        |arg| (", ", arg.span.lo()));
                let args = self.tecx.resolve_vars_if_possible(args);
                self.update_infer_source(InferSource {
                        span: path.ident.span,
                        kind: InferSourceKind::FullyQualifiedMethodCall {
                            receiver,
                            successor,
                            args,
                            def_id,
                        },
                    })
            }
        }
    }
}#[instrument(level = "debug", skip(self))]
1236    fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
1237        let tcx = self.tecx.tcx;
1238        match expr.kind {
1239            // When encountering `func(arg)` first look into `arg` and then `func`,
1240            // as `arg` is "more specific".
1241            ExprKind::Call(func, args) => {
1242                for arg in args {
1243                    self.visit_expr(arg);
1244                }
1245                self.visit_expr(func);
1246            }
1247            _ => intravisit::walk_expr(self, expr),
1248        }
1249
1250        for args in self.expr_inferred_arg_iter(expr) {
1251            debug!(?args);
1252            let InsertableGenericArgs {
1253                insert_span,
1254                args,
1255                generics_def_id,
1256                def_id,
1257                have_turbofish,
1258            } = args;
1259            let generics = tcx.generics_of(generics_def_id);
1260            if let Some(mut argument_index) = generics
1261                .own_args(args)
1262                .iter()
1263                .position(|&arg| self.generic_arg_contains_target(arg))
1264            {
1265                if generics.has_own_self() {
1266                    argument_index += 1;
1267                }
1268                let args = self.tecx.resolve_vars_if_possible(args);
1269                let generic_args =
1270                    &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
1271                let span = match expr.kind {
1272                    ExprKind::MethodCall(path, ..) => path.ident.span,
1273                    _ => expr.span,
1274                };
1275
1276                self.update_infer_source(InferSource {
1277                    span,
1278                    kind: InferSourceKind::GenericArg {
1279                        insert_span,
1280                        argument_index,
1281                        generics_def_id,
1282                        def_id,
1283                        generic_args,
1284                        have_turbofish,
1285                    },
1286                });
1287            }
1288        }
1289
1290        if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
1291            if let (
1292                &ExprKind::Closure(&Closure { fn_decl, body, fn_decl_span, .. }),
1293                ty::Closure(_, args),
1294            ) = (&expr.kind, node_ty.kind())
1295            {
1296                let output = args.as_closure().sig().output().skip_binder();
1297                if self.generic_arg_contains_target(output.into()) {
1298                    let body = self.tecx.tcx.hir_body(body);
1299                    let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
1300                        None
1301                    } else {
1302                        Some(body.value.span.shrink_to_hi())
1303                    };
1304                    self.update_infer_source(InferSource {
1305                        span: fn_decl_span,
1306                        kind: InferSourceKind::ClosureReturn {
1307                            ty: output,
1308                            data: &fn_decl.output,
1309                            should_wrap_expr,
1310                        },
1311                    })
1312                }
1313            }
1314        }
1315
1316        let has_impl_trait = |def_id| {
1317            iter::successors(Some(tcx.generics_of(def_id)), |generics| {
1318                generics.parent.map(|def_id| tcx.generics_of(def_id))
1319            })
1320            .any(|generics| generics.has_impl_trait())
1321        };
1322        if let ExprKind::MethodCall(path, receiver, method_args, span) = expr.kind
1323            && let Some(args) = self.node_args_opt(expr.hir_id)
1324            && args.iter().any(|arg| self.generic_arg_contains_target(arg))
1325            && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
1326            && self.tecx.tcx.trait_of_assoc(def_id).is_some()
1327            && !has_impl_trait(def_id)
1328            // FIXME(fn_delegation): In delegation item argument spans are equal to last path
1329            // segment. This leads to ICE's when emitting `multipart_suggestion`.
1330            && tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
1331        {
1332            let successor =
1333                method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
1334            let args = self.tecx.resolve_vars_if_possible(args);
1335            self.update_infer_source(InferSource {
1336                span: path.ident.span,
1337                kind: InferSourceKind::FullyQualifiedMethodCall {
1338                    receiver,
1339                    successor,
1340                    args,
1341                    def_id,
1342                },
1343            })
1344        }
1345    }
1346}