1use std::borrow::Cow;
2use std::iter;
3use std::path::PathBuf;
4
5use rustc_errors::codes::*;
6use rustc_errors::{Diag, IntoDiagArg};
7use rustc_hir::def::{CtorOf, DefKind, Namespace, Res};
8use rustc_hir::def_id::{DefId, LocalDefId};
9use rustc_hir::intravisit::{self, Visitor};
10use rustc_hir::{
11 self as hir, Body, Closure, Expr, ExprKind, FnRetTy, HirId, LetStmt, LocalSource, PatKind,
12};
13use rustc_middle::bug;
14use rustc_middle::hir::nested_filter;
15use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, DerefAdjustKind};
16use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Print, Printer};
17use rustc_middle::ty::{
18 self, GenericArg, GenericArgKind, GenericArgsRef, InferConst, IsSuggestable, Term, TermKind,
19 Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, TypeckResults,
20};
21use rustc_span::{BytePos, DUMMY_SP, Ident, Span, sym};
22use tracing::{debug, instrument, warn};
23
24use super::nice_region_error::placeholder_error::Highlighted;
25use crate::error_reporting::TypeErrCtxt;
26use crate::errors::{
27 AmbiguousImpl, AmbiguousReturn, AnnotationRequired, InferenceBadError,
28 SourceKindMultiSuggestion, SourceKindSubdiag,
29};
30use crate::infer::InferCtxt;
31
32pub enum TypeAnnotationNeeded {
33 E0282,
37 E0283,
42 E0284,
47}
48
49impl From<TypeAnnotationNeeded> for ErrCode {
50 fn from(val: TypeAnnotationNeeded) -> Self {
51 match val {
52 TypeAnnotationNeeded::E0282 => E0282,
53 TypeAnnotationNeeded::E0283 => E0283,
54 TypeAnnotationNeeded::E0284 => E0284,
55 }
56 }
57}
58
59pub struct InferenceDiagnosticsData {
61 pub name: String,
62 pub span: Option<Span>,
63 pub kind: UnderspecifiedArgKind,
64 pub parent: Option<InferenceDiagnosticsParentData>,
65}
66
67pub struct InferenceDiagnosticsParentData {
69 prefix: &'static str,
70 name: String,
71}
72
73#[derive(#[automatically_derived]
impl ::core::clone::Clone for UnderspecifiedArgKind {
#[inline]
fn clone(&self) -> UnderspecifiedArgKind {
match self {
UnderspecifiedArgKind::Type { prefix: __self_0 } =>
UnderspecifiedArgKind::Type {
prefix: ::core::clone::Clone::clone(__self_0),
},
UnderspecifiedArgKind::Const { is_parameter: __self_0 } =>
UnderspecifiedArgKind::Const {
is_parameter: ::core::clone::Clone::clone(__self_0),
},
}
}
}Clone)]
74pub enum UnderspecifiedArgKind {
75 Type { prefix: Cow<'static, str> },
76 Const { is_parameter: bool },
77}
78
79impl InferenceDiagnosticsData {
80 fn can_add_more_info(&self) -> bool {
81 !(self.name == "_" && #[allow(non_exhaustive_omitted_patterns)] match self.kind {
UnderspecifiedArgKind::Type { .. } => true,
_ => false,
}matches!(self.kind, UnderspecifiedArgKind::Type { .. }))
82 }
83
84 fn where_x_is_kind(&self, in_type: Ty<'_>) -> &'static str {
85 if in_type.is_ty_or_numeric_infer() {
86 ""
87 } else if self.name == "_" {
88 "underscore"
91 } else {
92 "has_name"
93 }
94 }
95
96 fn make_bad_error(&self, span: Span) -> InferenceBadError<'_> {
100 let has_parent = self.parent.is_some();
101 let bad_kind = if self.can_add_more_info() { "more_info" } else { "other" };
102 let (parent_prefix, parent_name) = self
103 .parent
104 .as_ref()
105 .map(|parent| (parent.prefix, parent.name.clone()))
106 .unwrap_or_default();
107 InferenceBadError {
108 span,
109 bad_kind,
110 prefix_kind: self.kind.clone(),
111 prefix: self.kind.try_get_prefix().unwrap_or_default(),
112 name: self.name.clone(),
113 has_parent,
114 parent_prefix,
115 parent_name,
116 }
117 }
118}
119
120impl InferenceDiagnosticsParentData {
121 fn for_parent_def_id(
122 tcx: TyCtxt<'_>,
123 parent_def_id: DefId,
124 ) -> Option<InferenceDiagnosticsParentData> {
125 let parent_name =
126 tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
127
128 Some(InferenceDiagnosticsParentData {
129 prefix: tcx.def_descr(parent_def_id),
130 name: parent_name,
131 })
132 }
133
134 fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<InferenceDiagnosticsParentData> {
135 Self::for_parent_def_id(tcx, tcx.parent(def_id))
136 }
137}
138
139impl IntoDiagArg for UnderspecifiedArgKind {
140 fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
141 let kind = match self {
142 Self::Type { .. } => "type",
143 Self::Const { is_parameter: true } => "const_with_param",
144 Self::Const { is_parameter: false } => "const",
145 };
146 rustc_errors::DiagArgValue::Str(kind.into())
147 }
148}
149
150impl UnderspecifiedArgKind {
151 fn try_get_prefix(&self) -> Option<&str> {
152 match self {
153 Self::Type { prefix } => Some(prefix.as_ref()),
154 Self::Const { .. } => None,
155 }
156 }
157}
158
159struct ClosureEraser<'a, 'tcx> {
160 infcx: &'a InferCtxt<'tcx>,
161 depth: usize,
162}
163
164impl<'a, 'tcx> ClosureEraser<'a, 'tcx> {
165 fn new_infer(&mut self) -> Ty<'tcx> {
166 self.infcx.next_ty_var(DUMMY_SP)
167 }
168}
169
170impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
171 fn cx(&self) -> TyCtxt<'tcx> {
172 self.infcx.tcx
173 }
174
175 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
176 self.depth += 1;
177 let ty = match ty.kind() {
178 ty::Closure(_, args) => {
179 let closure_sig = args.as_closure().sig();
182 Ty::new_fn_ptr(
183 self.cx(),
184 self.cx().signature_unclosure(closure_sig, hir::Safety::Safe),
185 )
186 }
187 ty::Adt(_, args) if !args.iter().any(|a| a.has_infer()) => {
188 self.new_infer()
193 }
194 ty::Adt(def, args) => {
195 let generics = self.cx().generics_of(def.did());
196 let generics: Vec<bool> = generics
197 .own_params
198 .iter()
199 .map(|param| param.default_value(self.cx()).is_some())
200 .collect();
201 let ty = Ty::new_adt(
202 self.cx(),
203 *def,
204 self.cx().mk_args_from_iter(generics.into_iter().zip(args.iter()).map(
205 |(has_default, arg)| {
206 if arg.has_infer() {
207 arg.fold_with(self)
213 } else if has_default {
214 arg
221 } else if let GenericArgKind::Type(_) = arg.kind() {
222 self.new_infer().into()
224 } else {
225 arg.fold_with(self)
226 }
227 },
228 )),
229 );
230 ty
231 }
232 _ if ty.has_infer() => {
233 ty.super_fold_with(self)
237 }
238 _ if self.depth == 1 => ty.super_fold_with(self),
241 _ => self.new_infer(),
244 };
245 self.depth -= 1;
246 ty
247 }
248
249 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
250 c
252 }
253}
254
255fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
256 let mut p = FmtPrinter::new(infcx.tcx, ns);
257 let ty_getter = move |ty_vid| {
258 if infcx.try_resolve_ty_var(ty_vid).is_ok() {
259 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:259",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(259u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("resolved ty var in error message")
as &dyn Value))])
});
} else { ; }
};warn!("resolved ty var in error message");
260 }
261
262 let var_origin = infcx.type_var_origin(ty_vid);
263 if let Some(def_id) = var_origin.param_def_id
264 && infcx.tcx.def_kind(def_id) == DefKind::TyParam
267 && let name = infcx.tcx.item_name(def_id)
268 && !var_origin.span.from_expansion()
269 {
270 let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
271 let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
272 let generic_param_def = generics.param_at(idx as usize, infcx.tcx);
273 if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param_def.kind {
274 None
275 } else {
276 Some(name)
277 }
278 } else {
279 None
280 }
281 };
282 p.ty_infer_name_resolver = Some(Box::new(ty_getter));
283 let const_getter =
284 move |ct_vid| Some(infcx.tcx.item_name(infcx.const_var_origin(ct_vid)?.param_def_id?));
285 p.const_infer_name_resolver = Some(Box::new(const_getter));
286 p
287}
288
289fn ty_to_string<'tcx>(
290 infcx: &InferCtxt<'tcx>,
291 ty: Ty<'tcx>,
292 called_method_def_id: Option<DefId>,
293) -> String {
294 let mut p = fmt_printer(infcx, Namespace::TypeNS);
295 let ty = infcx.resolve_vars_if_possible(ty);
296 let ty = ty.fold_with(&mut ClosureEraser { infcx, depth: 0 });
299
300 match (ty.kind(), called_method_def_id) {
301 (ty::FnDef(..), _) => {
304 ty.fn_sig(infcx.tcx).print(&mut p).unwrap();
305 p.into_buffer()
306 }
307 (_, Some(def_id))
308 if ty.is_ty_or_numeric_infer()
309 && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
310 {
311 "Vec<_>".to_string()
312 }
313 _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
314 _ => {
315 ty.print(&mut p).unwrap();
316 p.into_buffer()
317 }
318 }
319}
320
321fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
325 let ty::Closure(_, args) = ty.kind() else {
326 ::rustc_middle::util::bug::bug_fmt(format_args!("cannot convert non-closure to fn str in `closure_as_fn_str`"))bug!("cannot convert non-closure to fn str in `closure_as_fn_str`")
327 };
328 let fn_sig = args.as_closure().sig();
329 let args = fn_sig
330 .inputs()
331 .skip_binder()
332 .iter()
333 .next()
334 .map(|args| {
335 args.tuple_fields()
336 .iter()
337 .map(|arg| ty_to_string(infcx, arg, None))
338 .collect::<Vec<_>>()
339 .join(", ")
340 })
341 .unwrap_or_default();
342 let ret = if fn_sig.output().skip_binder().is_unit() {
343 String::new()
344 } else {
345 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
ty_to_string(infcx, fn_sig.output().skip_binder(), None)))
})format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
346 };
347 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("fn({0}){1}", args, ret))
})format!("fn({args}){ret}")
348}
349
350impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
351 pub fn extract_inference_diagnostics_data(
354 &self,
355 term: Term<'tcx>,
356 highlight: ty::print::RegionHighlightMode<'tcx>,
357 ) -> InferenceDiagnosticsData {
358 let tcx = self.tcx;
359 match term.kind() {
360 TermKind::Ty(ty) => {
361 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
362 let var_origin = self.infcx.type_var_origin(ty_vid);
363 if let Some(def_id) = var_origin.param_def_id
364 && self.tcx.def_kind(def_id) == DefKind::TyParam
367 && !var_origin.span.from_expansion()
368 {
369 return InferenceDiagnosticsData {
370 name: self.tcx.item_name(def_id).to_string(),
371 span: Some(var_origin.span),
372 kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into() },
373 parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
374 };
375 }
376 }
377
378 InferenceDiagnosticsData {
379 name: Highlighted { highlight, ns: Namespace::TypeNS, tcx, value: ty }
380 .to_string(),
381 span: None,
382 kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
383 parent: None,
384 }
385 }
386 TermKind::Const(ct) => {
387 if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
388 let origin = self.const_var_origin(vid).expect("expected unresolved const var");
389 if let Some(def_id) = origin.param_def_id {
390 return InferenceDiagnosticsData {
391 name: self.tcx.item_name(def_id).to_string(),
392 span: Some(origin.span),
393 kind: UnderspecifiedArgKind::Const { is_parameter: true },
394 parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
395 };
396 }
397
398 if true {
if !!origin.span.is_dummy() {
::core::panicking::panic("assertion failed: !origin.span.is_dummy()")
};
};debug_assert!(!origin.span.is_dummy());
399 InferenceDiagnosticsData {
400 name: Highlighted { highlight, ns: Namespace::ValueNS, tcx, value: ct }
401 .to_string(),
402 span: Some(origin.span),
403 kind: UnderspecifiedArgKind::Const { is_parameter: false },
404 parent: None,
405 }
406 } else {
407 InferenceDiagnosticsData {
414 name: Highlighted { highlight, ns: Namespace::ValueNS, tcx, value: ct }
415 .to_string(),
416 span: None,
417 kind: UnderspecifiedArgKind::Const { is_parameter: false },
418 parent: None,
419 }
420 }
421 }
422 }
423 }
424
425 fn bad_inference_failure_err(
428 &self,
429 span: Span,
430 arg_data: InferenceDiagnosticsData,
431 error_code: TypeAnnotationNeeded,
432 ) -> Diag<'a> {
433 let source_kind = "other";
434 let source_name = "";
435 let failure_span = None;
436 let infer_subdiags = Vec::new();
437 let multi_suggestions = Vec::new();
438 let bad_label = Some(arg_data.make_bad_error(span));
439 match error_code {
440 TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
441 span,
442 source_kind,
443 source_name,
444 failure_span,
445 infer_subdiags,
446 multi_suggestions,
447 bad_label,
448 }),
449 TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
450 span,
451 source_kind,
452 source_name,
453 failure_span,
454 infer_subdiags,
455 multi_suggestions,
456 bad_label,
457 }),
458 TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
459 span,
460 source_kind,
461 source_name,
462 failure_span,
463 infer_subdiags,
464 multi_suggestions,
465 bad_label,
466 }),
467 }
468 }
469
470 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("emit_inference_failure_err",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(470u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["body_def_id",
"failure_span", "term", "should_label_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body_def_id)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&failure_span)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&term)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&should_label_span
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Diag<'a> = loop {};
return __tracing_attr_fake_return;
}
{
self.emit_inference_failure_err_with_type_hint(body_def_id,
failure_span, term, error_code, should_label_span, None)
}
}
}#[instrument(level = "debug", skip(self, error_code))]
471 pub fn emit_inference_failure_err(
472 &self,
473 body_def_id: LocalDefId,
474 failure_span: Span,
475 term: Term<'tcx>,
476 error_code: TypeAnnotationNeeded,
477 should_label_span: bool,
478 ) -> Diag<'a> {
479 self.emit_inference_failure_err_with_type_hint(
480 body_def_id,
481 failure_span,
482 term,
483 error_code,
484 should_label_span,
485 None,
486 )
487 }
488
489 pub fn emit_inference_failure_err_with_type_hint(
490 &self,
491 body_def_id: LocalDefId,
492 failure_span: Span,
493 term: Term<'tcx>,
494 error_code: TypeAnnotationNeeded,
495 should_label_span: bool,
496 ty: Option<Ty<'tcx>>,
497 ) -> Diag<'a> {
498 let term = self.resolve_vars_if_possible(term);
499 let arg_data = self
500 .extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default());
501
502 let Some(typeck_results) = &self.typeck_results else {
503 return self.bad_inference_failure_err(failure_span, arg_data, error_code);
507 };
508
509 let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term, ty);
510 if let Some(body) =
511 self.tcx.hir_maybe_body_owned_by(self.tcx.typeck_root_def_id_local(body_def_id))
512 {
513 let expr = body.value;
514 local_visitor.visit_expr(expr);
515 }
516
517 let Some(InferSource { span, kind }) = local_visitor.infer_source else {
518 let silence = if let DefKind::AssocFn = self.tcx.def_kind(body_def_id)
519 && let parent = self.tcx.local_parent(body_def_id)
520 && self.tcx.is_automatically_derived(parent.to_def_id())
521 && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(parent)
522 && let hir::ItemKind::Impl(imp) = item.kind
523 && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = imp.self_ty.kind
524 && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, def_id) = path.res
525 && let Some(def_id) = def_id.as_local()
526 && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(def_id)
527 {
528 item.kind.recovered()
533 } else {
534 false
535 };
536 let mut err = self.bad_inference_failure_err(failure_span, arg_data, error_code);
537 if silence {
538 err.downgrade_to_delayed_bug();
539 }
540 return err;
541 };
542
543 let (source_kind, name, long_ty_path) = kind.ty_localized_msg(self);
544 let failure_span = if should_label_span && !failure_span.overlaps(span) {
545 Some(failure_span)
546 } else {
547 None
548 };
549
550 let mut infer_subdiags = Vec::new();
551 let mut multi_suggestions = Vec::new();
552 match kind {
553 InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
554 infer_subdiags.push(SourceKindSubdiag::LetLike {
555 span: insert_span,
556 name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
557 x_kind: arg_data.where_x_is_kind(ty),
558 prefix_kind: arg_data.kind.clone(),
559 prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
560 arg_name: arg_data.name,
561 kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
562 type_name: ty_to_string(self, ty, def_id),
563 });
564 }
565 InferSourceKind::ClosureArg { insert_span, ty, .. } => {
566 infer_subdiags.push(SourceKindSubdiag::LetLike {
567 span: insert_span,
568 name: String::new(),
569 x_kind: arg_data.where_x_is_kind(ty),
570 prefix_kind: arg_data.kind.clone(),
571 prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
572 arg_name: arg_data.name,
573 kind: "closure",
574 type_name: ty_to_string(self, ty, None),
575 });
576 }
577 InferSourceKind::GenericArg {
578 insert_span,
579 argument_index,
580 generics_def_id,
581 def_id: _,
582 generic_args,
583 have_turbofish,
584 hir_id,
585 } => {
586 let generics = self.tcx.generics_of(generics_def_id);
587 let is_type = term.as_type().is_some();
588
589 let (parent_exists, parent_prefix, parent_name) =
590 InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id)
591 .map_or((false, String::new(), String::new()), |parent| {
592 (true, parent.prefix.to_string(), parent.name)
593 });
594
595 infer_subdiags.push(SourceKindSubdiag::GenericLabel {
596 span,
597 is_type,
598 param_name: generics.own_params[argument_index].name.to_string(),
599 parent_exists,
600 parent_prefix,
601 parent_name,
602 });
603
604 let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn)
605 == Some(generics_def_id)
606 {
607 if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(hir_id)
608 && let hir::ExprKind::Call(expr, _args) = expr.kind
609 && let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind
610 && let Res::Def(DefKind::AssocFn, def_id) = path.res
611 && let Some(try_trait) = self.tcx.lang_items().try_trait()
612 && try_trait == self.tcx.parent(def_id)
613 && let DefKind::Fn | DefKind::AssocFn =
614 self.tcx.def_kind(body_def_id.to_def_id())
615 && let ret = self
616 .tcx
617 .fn_sig(body_def_id.to_def_id())
618 .instantiate_identity()
619 .skip_binder()
620 .output()
621 && let ty::Adt(adt, _args) = ret.kind()
622 && let Some(sym::Option | sym::Result) =
623 self.tcx.get_diagnostic_name(adt.did())
624 {
625 if let Some(sym::Option) = self.tcx.get_diagnostic_name(adt.did()) {
626 "Option<_>".to_string()
627 } else {
628 "Result<_, _>".to_string()
629 }
630 } else {
631 "Vec<_>".to_string()
632 }
633 } else {
634 let mut p = fmt_printer(self, Namespace::TypeNS);
635 p.comma_sep(generic_args.iter().copied().map(|arg| {
636 if arg.is_suggestable(self.tcx, true) {
637 return arg;
638 }
639
640 match arg.kind() {
641 GenericArgKind::Lifetime(_) => ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected lifetime"))bug!("unexpected lifetime"),
642 GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
643 GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
644 }
645 }))
646 .unwrap();
647 p.into_buffer()
648 };
649
650 if !have_turbofish {
651 infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
652 span: insert_span,
653 arg_count: generic_args.len(),
654 args,
655 });
656 }
657 }
658 InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
659 let placeholder = Some(self.next_ty_var(DUMMY_SP));
660 if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
661 let mut p = fmt_printer(self, Namespace::ValueNS);
662 p.print_def_path(def_id, args).unwrap();
663 let def_path = p.into_buffer();
664
665 let adjustment = match typeck_results.expr_adjustments(receiver) {
669 [
670 Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ },
671 ..,
672 Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ },
673 ] => "",
674 [
675 ..,
676 Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mut_)), target: _ },
677 ] => hir::Mutability::from(*mut_).ref_prefix_str(),
678 _ => "",
679 };
680
681 multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified(
682 receiver.span,
683 def_path,
684 adjustment,
685 successor,
686 ));
687 }
688 }
689 InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
690 let placeholder = Some(self.next_ty_var(DUMMY_SP));
691 if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
692 let ty_info = ty_to_string(self, ty, None);
693 multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
694 ty_info,
695 data,
696 should_wrap_expr,
697 ));
698 }
699 }
700 }
701 let mut err = match error_code {
702 TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
703 span,
704 source_kind,
705 source_name: &name,
706 failure_span,
707 infer_subdiags,
708 multi_suggestions,
709 bad_label: None,
710 }),
711 TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
712 span,
713 source_kind,
714 source_name: &name,
715 failure_span,
716 infer_subdiags,
717 multi_suggestions,
718 bad_label: None,
719 }),
720 TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
721 span,
722 source_kind,
723 source_name: &name,
724 failure_span,
725 infer_subdiags,
726 multi_suggestions,
727 bad_label: None,
728 }),
729 };
730 *err.long_ty_path() = long_ty_path;
731 if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } = kind {
732 err.downgrade_to_delayed_bug();
734 }
735 err
736 }
737}
738
739#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InferSource<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "InferSource",
"span", &self.span, "kind", &&self.kind)
}
}Debug)]
740struct InferSource<'tcx> {
741 span: Span,
742 kind: InferSourceKind<'tcx>,
743}
744
745#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InferSourceKind<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
InferSourceKind::LetBinding {
insert_span: __self_0,
pattern_name: __self_1,
ty: __self_2,
def_id: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"LetBinding", "insert_span", __self_0, "pattern_name",
__self_1, "ty", __self_2, "def_id", &__self_3),
InferSourceKind::ClosureArg {
insert_span: __self_0, ty: __self_1, kind: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"ClosureArg", "insert_span", __self_0, "ty", __self_1,
"kind", &__self_2),
InferSourceKind::GenericArg {
insert_span: __self_0,
argument_index: __self_1,
generics_def_id: __self_2,
def_id: __self_3,
generic_args: __self_4,
have_turbofish: __self_5,
hir_id: __self_6 } => {
let names: &'static _ =
&["insert_span", "argument_index", "generics_def_id",
"def_id", "generic_args", "have_turbofish", "hir_id"];
let values: &[&dyn ::core::fmt::Debug] =
&[__self_0, __self_1, __self_2, __self_3, __self_4,
__self_5, &__self_6];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"GenericArg", names, values)
}
InferSourceKind::FullyQualifiedMethodCall {
receiver: __self_0,
successor: __self_1,
args: __self_2,
def_id: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"FullyQualifiedMethodCall", "receiver", __self_0,
"successor", __self_1, "args", __self_2, "def_id",
&__self_3),
InferSourceKind::ClosureReturn {
ty: __self_0, data: __self_1, should_wrap_expr: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"ClosureReturn", "ty", __self_0, "data", __self_1,
"should_wrap_expr", &__self_2),
}
}
}Debug)]
746enum InferSourceKind<'tcx> {
747 LetBinding {
748 insert_span: Span,
749 pattern_name: Option<Ident>,
750 ty: Ty<'tcx>,
751 def_id: Option<DefId>,
752 },
753 ClosureArg {
754 insert_span: Span,
755 ty: Ty<'tcx>,
756 kind: PatKind<'tcx>,
757 },
758 GenericArg {
759 insert_span: Span,
760 argument_index: usize,
761 generics_def_id: DefId,
762 def_id: DefId,
763 generic_args: &'tcx [GenericArg<'tcx>],
764 have_turbofish: bool,
765 hir_id: HirId,
766 },
767 FullyQualifiedMethodCall {
768 receiver: &'tcx Expr<'tcx>,
769 successor: (&'static str, BytePos),
772 args: GenericArgsRef<'tcx>,
773 def_id: DefId,
774 },
775 ClosureReturn {
776 ty: Ty<'tcx>,
777 data: &'tcx FnRetTy<'tcx>,
778 should_wrap_expr: Option<Span>,
779 },
780}
781
782impl<'tcx> InferSource<'tcx> {
783 fn from_expansion(&self) -> bool {
784 let source_from_expansion = match self.kind {
785 InferSourceKind::LetBinding { insert_span, .. }
786 | InferSourceKind::ClosureArg { insert_span, .. }
787 | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(),
788 InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => {
789 receiver.span.from_expansion()
790 }
791 InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
792 data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
793 }
794 };
795 source_from_expansion || self.span.from_expansion()
796 }
797}
798
799impl<'tcx> InferSourceKind<'tcx> {
800 fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
801 let mut long_ty_path = None;
802 match *self {
803 InferSourceKind::LetBinding { ty, .. }
804 | InferSourceKind::ClosureArg { ty, .. }
805 | InferSourceKind::ClosureReturn { ty, .. } => {
806 if ty.is_closure() {
807 ("closure", closure_as_fn_str(infcx, ty), long_ty_path)
808 } else if ty.is_ty_or_numeric_infer()
809 || ty.is_primitive()
810 || #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Adt(_, args) if
args.types().count() == 0 && args.consts().count() == 0 => true,
_ => false,
}matches!(
811 ty.kind(),
812 ty::Adt(_, args)
813 if args.types().count() == 0 && args.consts().count() == 0
814 )
815 {
816 ("other", String::new(), long_ty_path)
820 } else {
821 ("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
822 }
823 }
824 InferSourceKind::GenericArg { .. }
826 | InferSourceKind::FullyQualifiedMethodCall { .. } => {
827 ("other", String::new(), long_ty_path)
828 }
829 }
830 }
831}
832
833#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InsertableGenericArgs<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"InsertableGenericArgs", "insert_span", &self.insert_span, "args",
&self.args, "generics_def_id", &self.generics_def_id, "def_id",
&self.def_id, "have_turbofish", &&self.have_turbofish)
}
}Debug)]
834struct InsertableGenericArgs<'tcx> {
835 insert_span: Span,
836 args: GenericArgsRef<'tcx>,
837 generics_def_id: DefId,
838 def_id: DefId,
839 have_turbofish: bool,
840}
841
842struct FindInferSourceVisitor<'a, 'tcx> {
850 tecx: &'a TypeErrCtxt<'a, 'tcx>,
851 typeck_results: &'a TypeckResults<'tcx>,
852
853 target: Term<'tcx>,
854 ty: Option<Ty<'tcx>>,
855
856 attempt: usize,
857 infer_source_cost: usize,
858 infer_source: Option<InferSource<'tcx>>,
859}
860
861impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
862 fn new(
863 tecx: &'a TypeErrCtxt<'a, 'tcx>,
864 typeck_results: &'a TypeckResults<'tcx>,
865 target: Term<'tcx>,
866 ty: Option<Ty<'tcx>>,
867 ) -> Self {
868 FindInferSourceVisitor {
869 tecx,
870 typeck_results,
871
872 target,
873 ty,
874
875 attempt: 0,
876 infer_source_cost: usize::MAX,
877 infer_source: None,
878 }
879 }
880
881 fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
886 #[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for CostCtxt<'tcx> {
#[inline]
fn clone(&self) -> CostCtxt<'tcx> {
let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for CostCtxt<'tcx> { }Copy)]
887 struct CostCtxt<'tcx> {
888 tcx: TyCtxt<'tcx>,
889 }
890 impl<'tcx> CostCtxt<'tcx> {
891 fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
892 match arg.kind() {
893 GenericArgKind::Lifetime(_) => 0, GenericArgKind::Type(ty) => self.ty_cost(ty),
895 GenericArgKind::Const(_) => 3, }
897 }
898 fn ty_cost(self, ty: Ty<'tcx>) -> usize {
899 match *ty.kind() {
900 ty::Closure(..) => 1000,
901 ty::FnDef(..) => 150,
902 ty::FnPtr(..) => 30,
903 ty::Adt(def, args) => {
904 5 + self
905 .tcx
906 .generics_of(def.did())
907 .own_args_no_defaults(self.tcx, args)
908 .iter()
909 .map(|&arg| self.arg_cost(arg))
910 .sum::<usize>()
911 }
912 ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(),
913 ty::Ref(_, ty, _) => 2 + self.ty_cost(ty),
914 ty::Infer(..) => 0,
915 _ => 1,
916 }
917 }
918 }
919
920 let tcx = self.tecx.tcx;
922 let ctx = CostCtxt { tcx };
923 match source.kind {
924 InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
925 InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
926 InferSourceKind::GenericArg { def_id, generic_args, .. } => {
927 let variant_cost = match tcx.def_kind(def_id) {
928 DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15,
930 _ => 10,
931 };
932 variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
933 }
934 InferSourceKind::FullyQualifiedMethodCall { args, .. } => {
935 20 + args.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
936 }
937 InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
938 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
939 }
940 }
941 }
942
943 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("update_infer_source",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(945u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["new_source"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_source)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if new_source.from_expansion() { return; }
let cost = self.source_cost(&new_source) + self.attempt;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:952",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(952u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["cost"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&cost) as
&dyn Value))])
});
} else { ; }
};
self.attempt += 1;
if let Some(InferSource {
kind: InferSourceKind::GenericArg { def_id: did, .. }, .. })
= self.infer_source &&
let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..
} = new_source.kind && ty.is_ty_or_numeric_infer() {
*def_id = Some(did);
}
if cost < self.infer_source_cost {
self.infer_source_cost = cost;
self.infer_source = Some(new_source);
}
}
}
}#[instrument(level = "debug", skip(self))]
946 fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
947 if new_source.from_expansion() {
948 return;
949 }
950
951 let cost = self.source_cost(&new_source) + self.attempt;
952 debug!(?cost);
953 self.attempt += 1;
954 if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, .. }, .. }) =
955 self.infer_source
956 && let InferSourceKind::LetBinding { ref ty, ref mut def_id, .. } = new_source.kind
957 && ty.is_ty_or_numeric_infer()
958 {
959 *def_id = Some(did);
962 }
963
964 if cost < self.infer_source_cost {
965 self.infer_source_cost = cost;
966 self.infer_source = Some(new_source);
967 }
968 }
969
970 fn node_args_opt(&self, hir_id: HirId) -> Option<GenericArgsRef<'tcx>> {
971 let args = self.typeck_results.node_args_opt(hir_id);
972 self.tecx.resolve_vars_if_possible(args)
973 }
974
975 fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
976 let ty = self.typeck_results.node_type_opt(hir_id);
977 self.tecx.resolve_vars_if_possible(ty)
978 }
979
980 fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool {
983 if arg == self.target.into() {
984 return true;
985 }
986
987 match (arg.kind(), self.target.kind()) {
988 (GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => {
989 use ty::{Infer, TyVar};
990 match (inner_ty.kind(), target_ty.kind()) {
991 (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
992 self.tecx.sub_unification_table_root_var(a_vid)
993 == self.tecx.sub_unification_table_root_var(b_vid)
994 }
995 _ => false,
996 }
997 }
998 (GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => {
999 match (inner_ct.kind(), target_ct.kind()) {
1000 (
1001 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
1002 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
1003 ) => self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid),
1004 _ => false,
1005 }
1006 }
1007 _ => false,
1008 }
1009 }
1010
1011 fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool {
1014 let mut walker = arg.walk();
1015 while let Some(inner) = walker.next() {
1016 if self.generic_arg_is_target(inner) {
1017 return true;
1018 }
1019 match inner.kind() {
1020 GenericArgKind::Lifetime(_) => {}
1021 GenericArgKind::Type(ty) => {
1022 if #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. }) | ty::Closure(..) |
ty::CoroutineClosure(..) | ty::Coroutine(..) => true,
_ => false,
}matches!(
1023 ty.kind(),
1024 ty::Alias(ty::AliasTy { kind: ty::Opaque { .. }, .. })
1025 | ty::Closure(..)
1026 | ty::CoroutineClosure(..)
1027 | ty::Coroutine(..)
1028 ) {
1029 walker.skip_current_subtree();
1040 }
1041 }
1042 GenericArgKind::Const(ct) => {
1043 if #[allow(non_exhaustive_omitted_patterns)] match ct.kind() {
ty::ConstKind::Unevaluated(..) => true,
_ => false,
}matches!(ct.kind(), ty::ConstKind::Unevaluated(..)) {
1044 walker.skip_current_subtree();
1047 }
1048 }
1049 }
1050 }
1051 false
1052 }
1053
1054 fn expr_inferred_arg_iter(
1055 &self,
1056 expr: &'tcx hir::Expr<'tcx>,
1057 ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
1058 let tcx = self.tecx.tcx;
1059 match expr.kind {
1060 hir::ExprKind::Path(ref path) => {
1061 if let Some(args) = self.node_args_opt(expr.hir_id) {
1062 return self.path_inferred_arg_iter(expr.hir_id, args, path);
1063 }
1064 }
1065 hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
1076 if #[allow(non_exhaustive_omitted_patterns)] match path.res {
Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => true,
_ => false,
}matches!(path.res, Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) => {
1083 if let Some(ty) = self.opt_node_type(expr.hir_id)
1084 && let ty::Adt(_, args) = ty.kind()
1085 {
1086 return Box::new(self.resolved_path_inferred_arg_iter(path, args));
1087 }
1088 }
1089 hir::ExprKind::MethodCall(segment, ..) => {
1090 if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) {
1091 let generics = tcx.generics_of(def_id);
1092 let insertable = try {
1093 if generics.has_impl_trait() {
1094 None?
1095 }
1096 let args = self.node_args_opt(expr.hir_id)?;
1097 let span = tcx.hir_span(segment.hir_id);
1098 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1099 let have_turbofish = segment.args.is_some_and(|args| {
1100 args.args.iter().any(|arg| arg.is_ty_or_const())
1101 });
1102 InsertableGenericArgs {
1103 insert_span,
1104 args,
1105 generics_def_id: def_id,
1106 def_id,
1107 have_turbofish,
1108 }
1109 };
1110 return Box::new(insertable.into_iter());
1111 }
1112 }
1113 _ => {}
1114 }
1115
1116 Box::new(iter::empty())
1117 }
1118
1119 fn resolved_path_inferred_arg_iter(
1120 &self,
1121 path: &'tcx hir::Path<'tcx>,
1122 args: GenericArgsRef<'tcx>,
1123 ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'tcx {
1124 let tcx = self.tecx.tcx;
1125 let have_turbofish = path.segments.iter().any(|segment| {
1126 segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
1127 });
1128 let last_segment_using_path_data = try {
1134 let generics_def_id = tcx.res_generics_def_id(path.res)?;
1135 let generics = tcx.generics_of(generics_def_id);
1136 if generics.has_impl_trait() {
1137 do yeet ();
1138 }
1139 let insert_span =
1140 path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi());
1141 InsertableGenericArgs {
1142 insert_span,
1143 args,
1144 generics_def_id,
1145 def_id: path.res.def_id(),
1146 have_turbofish,
1147 }
1148 };
1149
1150 path.segments
1151 .iter()
1152 .filter_map(move |segment| {
1153 let res = segment.res;
1154 let generics_def_id = tcx.res_generics_def_id(res)?;
1155 let generics = tcx.generics_of(generics_def_id);
1156 if generics.has_impl_trait() {
1157 return None;
1158 }
1159 let span = tcx.hir_span(segment.hir_id);
1160 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1161 Some(InsertableGenericArgs {
1162 insert_span,
1163 args,
1164 generics_def_id,
1165 def_id: res.def_id(),
1166 have_turbofish,
1167 })
1168 })
1169 .chain(last_segment_using_path_data)
1170 }
1171
1172 fn path_inferred_arg_iter(
1173 &self,
1174 hir_id: HirId,
1175 args: GenericArgsRef<'tcx>,
1176 qpath: &'tcx hir::QPath<'tcx>,
1177 ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
1178 let tcx = self.tecx.tcx;
1179 match qpath {
1180 hir::QPath::Resolved(_self_ty, path) => {
1181 Box::new(self.resolved_path_inferred_arg_iter(path, args))
1182 }
1183 hir::QPath::TypeRelative(ty, segment) => {
1184 let Some(def_id) = self.typeck_results.type_dependent_def_id(hir_id) else {
1185 return Box::new(iter::empty());
1186 };
1187
1188 let generics = tcx.generics_of(def_id);
1189 let segment = if !segment.infer_args || generics.has_impl_trait() {
1190 None
1191 } else {
1192 let span = tcx.hir_span(segment.hir_id);
1193 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1194 Some(InsertableGenericArgs {
1195 insert_span,
1196 args,
1197 generics_def_id: def_id,
1198 def_id,
1199 have_turbofish: false,
1200 })
1201 };
1202
1203 let parent_def_id = generics.parent.unwrap();
1204 if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
1205 let parent_ty = tcx.type_of(parent_def_id).instantiate(tcx, args);
1206 match (parent_ty.kind(), &ty.kind) {
1207 (
1208 ty::Adt(def, args),
1209 hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
1210 ) => {
1211 if tcx.res_generics_def_id(path.res) != Some(def.did()) {
1212 match path.res {
1213 Res::Def(DefKind::TyAlias, _) => {
1214 }
1221 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
1224 _ => {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1224",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1224u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("unexpected path: def={0:?} args={1:?} path={2:?}",
def, args, path) as &dyn Value))])
});
} else { ; }
}warn!(
1225 "unexpected path: def={:?} args={:?} path={:?}",
1226 def, args, path,
1227 ),
1228 }
1229 } else {
1230 return Box::new(
1231 self.resolved_path_inferred_arg_iter(path, args).chain(segment),
1232 );
1233 }
1234 }
1235 _ => (),
1236 }
1237 }
1238
1239 Box::new(segment.into_iter())
1240 }
1241 }
1242 }
1243}
1244
1245impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
1246 type NestedFilter = nested_filter::OnlyBodies;
1247
1248 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
1249 self.tecx.tcx
1250 }
1251
1252 fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
1253 intravisit::walk_local(self, local);
1254
1255 if let Some(mut ty) = self.opt_node_type(local.hir_id) {
1256 if self.generic_arg_contains_target(ty.into()) {
1257 fn get_did(
1258 typeck_results: &TypeckResults<'_>,
1259 expr: &hir::Expr<'_>,
1260 ) -> Option<DefId> {
1261 match expr.kind {
1262 hir::ExprKind::Match(expr, _, hir::MatchSource::TryDesugar(_))
1263 if let hir::ExprKind::Call(_, [expr]) = expr.kind =>
1264 {
1265 get_did(typeck_results, expr)
1266 }
1267 hir::ExprKind::Call(base, _args)
1268 if let hir::ExprKind::Path(path) = base.kind
1269 && let hir::QPath::Resolved(_, path) = path
1270 && let Res::Def(_, did) = path.res =>
1271 {
1272 Some(did)
1273 }
1274 hir::ExprKind::MethodCall(..)
1275 if let Some(did) =
1276 typeck_results.type_dependent_def_id(expr.hir_id) =>
1277 {
1278 Some(did)
1279 }
1280 _ => None,
1281 }
1282 }
1283 if let Some(t) = self.ty
1284 && ty.has_infer()
1285 {
1286 ty = t;
1287 }
1288 if let LocalSource::Normal = local.source
1289 && local.ty.is_none()
1290 {
1291 self.update_infer_source(InferSource {
1292 span: local.pat.span,
1293 kind: InferSourceKind::LetBinding {
1294 insert_span: local.pat.span.shrink_to_hi(),
1295 pattern_name: local.pat.simple_ident(),
1296 ty,
1297 def_id: local.init.and_then(|expr| get_did(self.typeck_results, expr)),
1298 },
1299 });
1300 }
1301 }
1302 }
1303 }
1304
1305 fn visit_body(&mut self, body: &Body<'tcx>) {
1308 for param in body.params {
1309 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1309",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1309u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("param: span {0:?}, ty_span {1:?}, pat.span {2:?}",
param.span, param.ty_span, param.pat.span) as &dyn Value))])
});
} else { ; }
};debug!(
1310 "param: span {:?}, ty_span {:?}, pat.span {:?}",
1311 param.span, param.ty_span, param.pat.span
1312 );
1313 if param.ty_span != param.pat.span {
1314 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1314",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1314u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("skipping param: has explicit type")
as &dyn Value))])
});
} else { ; }
};debug!("skipping param: has explicit type");
1315 continue;
1316 }
1317
1318 let Some(param_ty) = self.opt_node_type(param.hir_id) else { continue };
1319
1320 if self.generic_arg_contains_target(param_ty.into()) {
1321 self.update_infer_source(InferSource {
1322 span: param.pat.span,
1323 kind: InferSourceKind::ClosureArg {
1324 insert_span: param.pat.span.shrink_to_hi(),
1325 ty: param_ty,
1326 kind: param.pat.kind,
1327 },
1328 })
1329 }
1330 }
1331 intravisit::walk_body(self, body);
1332 }
1333
1334 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_expr",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1334u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["expr"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = self.tecx.tcx;
match expr.kind {
ExprKind::Call(func, args) => {
for arg in args { self.visit_expr(arg); }
self.visit_expr(func);
}
_ => intravisit::walk_expr(self, expr),
}
for args in self.expr_inferred_arg_iter(expr) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1350",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1350u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["args"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&args) as
&dyn Value))])
});
} else { ; }
};
let InsertableGenericArgs {
insert_span, args, generics_def_id, def_id, have_turbofish
} = args;
let generics = tcx.generics_of(generics_def_id);
if let Some(argument_index) =
generics.own_args(args).iter().position(|&arg|
self.generic_arg_contains_target(arg)) {
let args = self.tecx.resolve_vars_if_possible(args);
let generic_args =
&generics.own_args_no_defaults(tcx,
args)[generics.own_counts().lifetimes..];
let span =
match expr.kind {
ExprKind::MethodCall(segment, ..) if
have_turbofish && let Some(hir_args) = segment.args &&
let Some(idx) =
argument_index.checked_sub(generics.own_counts().lifetimes)
&&
let Some(arg) =
hir_args.args.get(hir_args.num_lifetime_params() + idx) => {
arg.span()
}
ExprKind::MethodCall(segment, ..) => segment.ident.span,
_ => expr.span,
};
let mut argument_index = argument_index;
if generics.has_own_self() { argument_index += 1; }
self.update_infer_source(InferSource {
span,
kind: InferSourceKind::GenericArg {
insert_span,
argument_index,
generics_def_id,
def_id,
generic_args,
have_turbofish,
hir_id: expr.hir_id,
},
});
}
}
if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
if let (&ExprKind::Closure(&Closure {
fn_decl, body, fn_decl_span, .. }), ty::Closure(_, args)) =
(&expr.kind, node_ty.kind()) {
let output = args.as_closure().sig().output().skip_binder();
if self.generic_arg_contains_target(output.into()) {
let body = self.tecx.tcx.hir_body(body);
let should_wrap_expr =
if #[allow(non_exhaustive_omitted_patterns)] match body.value.kind
{
ExprKind::Block(..) => true,
_ => false,
} {
None
} else { Some(body.value.span.shrink_to_hi()) };
self.update_infer_source(InferSource {
span: fn_decl_span,
kind: InferSourceKind::ClosureReturn {
ty: output,
data: &fn_decl.output,
should_wrap_expr,
},
})
}
}
}
let has_impl_trait =
|def_id|
{
iter::successors(Some(tcx.generics_of(def_id)),
|generics|
{
generics.parent.map(|def_id| tcx.generics_of(def_id))
}).any(|generics| generics.has_impl_trait())
};
if let ExprKind::MethodCall(path, receiver, method_args, span) =
expr.kind &&
let Some(args) = self.node_args_opt(expr.hir_id) &&
args.iter().any(|arg| self.generic_arg_contains_target(arg))
&&
let Some(def_id) =
self.typeck_results.type_dependent_def_id(expr.hir_id) &&
self.tecx.tcx.trait_of_assoc(def_id).is_some() &&
!has_impl_trait(def_id) &&
tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
{
let successor =
method_args.get(0).map_or_else(|| (")", span.hi()),
|arg| (", ", arg.span.lo()));
let args = self.tecx.resolve_vars_if_possible(args);
self.update_infer_source(InferSource {
span: path.ident.span,
kind: InferSourceKind::FullyQualifiedMethodCall {
receiver,
successor,
args,
def_id,
},
})
}
}
}
}#[instrument(level = "debug", skip(self))]
1335 fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
1336 let tcx = self.tecx.tcx;
1337 match expr.kind {
1338 ExprKind::Call(func, args) => {
1341 for arg in args {
1342 self.visit_expr(arg);
1343 }
1344 self.visit_expr(func);
1345 }
1346 _ => intravisit::walk_expr(self, expr),
1347 }
1348
1349 for args in self.expr_inferred_arg_iter(expr) {
1350 debug!(?args);
1351 let InsertableGenericArgs {
1352 insert_span,
1353 args,
1354 generics_def_id,
1355 def_id,
1356 have_turbofish,
1357 } = args;
1358 let generics = tcx.generics_of(generics_def_id);
1359 if let Some(argument_index) = generics
1360 .own_args(args)
1361 .iter()
1362 .position(|&arg| self.generic_arg_contains_target(arg))
1363 {
1364 let args = self.tecx.resolve_vars_if_possible(args);
1365 let generic_args =
1366 &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
1367 let span = match expr.kind {
1368 ExprKind::MethodCall(segment, ..)
1369 if have_turbofish
1370 && let Some(hir_args) = segment.args
1371 && let Some(idx) =
1372 argument_index.checked_sub(generics.own_counts().lifetimes)
1373 && let Some(arg) =
1374 hir_args.args.get(hir_args.num_lifetime_params() + idx) =>
1375 {
1376 arg.span()
1377 }
1378 ExprKind::MethodCall(segment, ..) => segment.ident.span,
1379 _ => expr.span,
1380 };
1381 let mut argument_index = argument_index;
1382 if generics.has_own_self() {
1383 argument_index += 1;
1384 }
1385
1386 self.update_infer_source(InferSource {
1387 span,
1388 kind: InferSourceKind::GenericArg {
1389 insert_span,
1390 argument_index,
1391 generics_def_id,
1392 def_id,
1393 generic_args,
1394 have_turbofish,
1395 hir_id: expr.hir_id,
1396 },
1397 });
1398 }
1399 }
1400
1401 if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
1402 if let (
1403 &ExprKind::Closure(&Closure { fn_decl, body, fn_decl_span, .. }),
1404 ty::Closure(_, args),
1405 ) = (&expr.kind, node_ty.kind())
1406 {
1407 let output = args.as_closure().sig().output().skip_binder();
1408 if self.generic_arg_contains_target(output.into()) {
1409 let body = self.tecx.tcx.hir_body(body);
1410 let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
1411 None
1412 } else {
1413 Some(body.value.span.shrink_to_hi())
1414 };
1415 self.update_infer_source(InferSource {
1416 span: fn_decl_span,
1417 kind: InferSourceKind::ClosureReturn {
1418 ty: output,
1419 data: &fn_decl.output,
1420 should_wrap_expr,
1421 },
1422 })
1423 }
1424 }
1425 }
1426
1427 let has_impl_trait = |def_id| {
1428 iter::successors(Some(tcx.generics_of(def_id)), |generics| {
1429 generics.parent.map(|def_id| tcx.generics_of(def_id))
1430 })
1431 .any(|generics| generics.has_impl_trait())
1432 };
1433 if let ExprKind::MethodCall(path, receiver, method_args, span) = expr.kind
1434 && let Some(args) = self.node_args_opt(expr.hir_id)
1435 && args.iter().any(|arg| self.generic_arg_contains_target(arg))
1436 && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
1437 && self.tecx.tcx.trait_of_assoc(def_id).is_some()
1438 && !has_impl_trait(def_id)
1439 && tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
1442 {
1443 let successor =
1444 method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
1445 let args = self.tecx.resolve_vars_if_possible(args);
1446 self.update_infer_source(InferSource {
1447 span: path.ident.span,
1448 kind: InferSourceKind::FullyQualifiedMethodCall {
1449 receiver,
1450 successor,
1451 args,
1452 def_id,
1453 },
1454 })
1455 }
1456 }
1457}