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