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