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