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}
162
163impl<'a, 'tcx> ClosureEraser<'a, 'tcx> {
164 fn new_infer(&mut self) -> Ty<'tcx> {
165 self.infcx.next_ty_var(DUMMY_SP)
166 }
167}
168
169impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for ClosureEraser<'a, 'tcx> {
170 fn cx(&self) -> TyCtxt<'tcx> {
171 self.infcx.tcx
172 }
173
174 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
175 match ty.kind() {
176 ty::Closure(_, args) => {
177 let closure_sig = args.as_closure().sig();
180 Ty::new_fn_ptr(
181 self.cx(),
182 self.cx().signature_unclosure(closure_sig, hir::Safety::Safe),
183 )
184 }
185 ty::Adt(_, args) if !args.iter().any(|a| a.has_infer()) => {
186 self.new_infer()
191 }
192 ty::Adt(def, args) => {
193 let generics = self.cx().generics_of(def.did());
194 let generics: Vec<bool> = generics
195 .own_params
196 .iter()
197 .map(|param| param.default_value(self.cx()).is_some())
198 .collect();
199 let ty = Ty::new_adt(
200 self.cx(),
201 *def,
202 self.cx().mk_args_from_iter(generics.into_iter().zip(args.iter()).map(
203 |(has_default, arg)| {
204 if arg.has_infer() {
205 arg.fold_with(self)
211 } else if has_default {
212 arg
219 } else if let GenericArgKind::Type(_) = arg.kind() {
220 self.new_infer().into()
222 } else {
223 arg.fold_with(self)
224 }
225 },
226 )),
227 );
228 ty
229 }
230 _ if ty.has_infer() => {
231 ty.super_fold_with(self)
235 }
236 _ => self.new_infer(),
238 }
239 }
240
241 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
242 c
244 }
245}
246
247fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinter<'a, 'tcx> {
248 let mut p = FmtPrinter::new(infcx.tcx, ns);
249 let ty_getter = move |ty_vid| {
250 if infcx.probe_ty_var(ty_vid).is_ok() {
251 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:251",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(251u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("resolved ty var in error message")
as &dyn Value))])
});
} else { ; }
};warn!("resolved ty var in error message");
252 }
253
254 let var_origin = infcx.type_var_origin(ty_vid);
255 if let Some(def_id) = var_origin.param_def_id
256 && infcx.tcx.def_kind(def_id) == DefKind::TyParam
259 && let name = infcx.tcx.item_name(def_id)
260 && !var_origin.span.from_expansion()
261 {
262 let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
263 let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
264 let generic_param_def = generics.param_at(idx as usize, infcx.tcx);
265 if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param_def.kind {
266 None
267 } else {
268 Some(name)
269 }
270 } else {
271 None
272 }
273 };
274 p.ty_infer_name_resolver = Some(Box::new(ty_getter));
275 let const_getter =
276 move |ct_vid| Some(infcx.tcx.item_name(infcx.const_var_origin(ct_vid)?.param_def_id?));
277 p.const_infer_name_resolver = Some(Box::new(const_getter));
278 p
279}
280
281fn ty_to_string<'tcx>(
282 infcx: &InferCtxt<'tcx>,
283 ty: Ty<'tcx>,
284 called_method_def_id: Option<DefId>,
285) -> String {
286 let mut p = fmt_printer(infcx, Namespace::TypeNS);
287 let ty = infcx.resolve_vars_if_possible(ty);
288 let ty = ty.fold_with(&mut ClosureEraser { infcx });
291
292 match (ty.kind(), called_method_def_id) {
293 (ty::FnDef(..), _) => {
296 ty.fn_sig(infcx.tcx).print(&mut p).unwrap();
297 p.into_buffer()
298 }
299 (_, Some(def_id))
300 if ty.is_ty_or_numeric_infer()
301 && infcx.tcx.get_diagnostic_item(sym::iterator_collect_fn) == Some(def_id) =>
302 {
303 "Vec<_>".to_string()
304 }
305 _ if ty.is_ty_or_numeric_infer() => "/* Type */".to_string(),
306 _ => {
307 ty.print(&mut p).unwrap();
308 p.into_buffer()
309 }
310 }
311}
312
313fn closure_as_fn_str<'tcx>(infcx: &InferCtxt<'tcx>, ty: Ty<'tcx>) -> String {
317 let ty::Closure(_, args) = ty.kind() else {
318 ::rustc_middle::util::bug::bug_fmt(format_args!("cannot convert non-closure to fn str in `closure_as_fn_str`"))bug!("cannot convert non-closure to fn str in `closure_as_fn_str`")
319 };
320 let fn_sig = args.as_closure().sig();
321 let args = fn_sig
322 .inputs()
323 .skip_binder()
324 .iter()
325 .next()
326 .map(|args| {
327 args.tuple_fields()
328 .iter()
329 .map(|arg| ty_to_string(infcx, arg, None))
330 .collect::<Vec<_>>()
331 .join(", ")
332 })
333 .unwrap_or_default();
334 let ret = if fn_sig.output().skip_binder().is_unit() {
335 String::new()
336 } else {
337 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" -> {0}",
ty_to_string(infcx, fn_sig.output().skip_binder(), None)))
})format!(" -> {}", ty_to_string(infcx, fn_sig.output().skip_binder(), None))
338 };
339 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("fn({0}){1}", args, ret))
})format!("fn({args}){ret}")
340}
341
342impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
343 pub fn extract_inference_diagnostics_data(
346 &self,
347 term: Term<'tcx>,
348 highlight: ty::print::RegionHighlightMode<'tcx>,
349 ) -> InferenceDiagnosticsData {
350 let tcx = self.tcx;
351 match term.kind() {
352 TermKind::Ty(ty) => {
353 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
354 let var_origin = self.infcx.type_var_origin(ty_vid);
355 if let Some(def_id) = var_origin.param_def_id
356 && self.tcx.def_kind(def_id) == DefKind::TyParam
359 && !var_origin.span.from_expansion()
360 {
361 return InferenceDiagnosticsData {
362 name: self.tcx.item_name(def_id).to_string(),
363 span: Some(var_origin.span),
364 kind: UnderspecifiedArgKind::Type { prefix: "type parameter".into() },
365 parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
366 };
367 }
368 }
369
370 InferenceDiagnosticsData {
371 name: Highlighted { highlight, ns: Namespace::TypeNS, tcx, value: ty }
372 .to_string(),
373 span: None,
374 kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
375 parent: None,
376 }
377 }
378 TermKind::Const(ct) => {
379 if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.kind() {
380 let origin = self.const_var_origin(vid).expect("expected unresolved const var");
381 if let Some(def_id) = origin.param_def_id {
382 return InferenceDiagnosticsData {
383 name: self.tcx.item_name(def_id).to_string(),
384 span: Some(origin.span),
385 kind: UnderspecifiedArgKind::Const { is_parameter: true },
386 parent: InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id),
387 };
388 }
389
390 if true {
if !!origin.span.is_dummy() {
::core::panicking::panic("assertion failed: !origin.span.is_dummy()")
};
};debug_assert!(!origin.span.is_dummy());
391 InferenceDiagnosticsData {
392 name: Highlighted { highlight, ns: Namespace::ValueNS, tcx, value: ct }
393 .to_string(),
394 span: Some(origin.span),
395 kind: UnderspecifiedArgKind::Const { is_parameter: false },
396 parent: None,
397 }
398 } else {
399 InferenceDiagnosticsData {
406 name: Highlighted { highlight, ns: Namespace::ValueNS, tcx, value: ct }
407 .to_string(),
408 span: None,
409 kind: UnderspecifiedArgKind::Const { is_parameter: false },
410 parent: None,
411 }
412 }
413 }
414 }
415 }
416
417 fn bad_inference_failure_err(
420 &self,
421 span: Span,
422 arg_data: InferenceDiagnosticsData,
423 error_code: TypeAnnotationNeeded,
424 ) -> Diag<'a> {
425 let source_kind = "other";
426 let source_name = "";
427 let failure_span = None;
428 let infer_subdiags = Vec::new();
429 let multi_suggestions = Vec::new();
430 let bad_label = Some(arg_data.make_bad_error(span));
431 match error_code {
432 TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
433 span,
434 source_kind,
435 source_name,
436 failure_span,
437 infer_subdiags,
438 multi_suggestions,
439 bad_label,
440 }),
441 TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
442 span,
443 source_kind,
444 source_name,
445 failure_span,
446 infer_subdiags,
447 multi_suggestions,
448 bad_label,
449 }),
450 TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
451 span,
452 source_kind,
453 source_name,
454 failure_span,
455 infer_subdiags,
456 multi_suggestions,
457 bad_label,
458 }),
459 }
460 }
461
462 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("emit_inference_failure_err",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(462u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["body_def_id",
"failure_span", "term", "should_label_span"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body_def_id)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&failure_span)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&term)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&should_label_span
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Diag<'a> = loop {};
return __tracing_attr_fake_return;
}
{
let term = self.resolve_vars_if_possible(term);
let arg_data =
self.extract_inference_diagnostics_data(term,
ty::print::RegionHighlightMode::default());
let Some(typeck_results) =
&self.typeck_results else {
return self.bad_inference_failure_err(failure_span,
arg_data, error_code);
};
let mut local_visitor =
FindInferSourceVisitor::new(self, typeck_results, term);
if let Some(body) =
self.tcx.hir_maybe_body_owned_by(self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local())
{
let expr = body.value;
local_visitor.visit_expr(expr);
}
let Some(InferSource { span, kind }) =
local_visitor.infer_source else {
let silence =
if let DefKind::AssocFn = self.tcx.def_kind(body_def_id) &&
let parent = self.tcx.parent(body_def_id.into()) &&
self.tcx.is_automatically_derived(parent) &&
let Some(parent) = parent.as_local() &&
let hir::Node::Item(item) =
self.tcx.hir_node_by_def_id(parent) &&
let hir::ItemKind::Impl(imp) = item.kind &&
let hir::TyKind::Path(hir::QPath::Resolved(_, path)) =
imp.self_ty.kind &&
let Res::Def(DefKind::Struct | DefKind::Enum |
DefKind::Union, def_id) = path.res &&
let Some(def_id) = def_id.as_local() &&
let hir::Node::Item(item) =
self.tcx.hir_node_by_def_id(def_id) {
item.kind.recovered()
} else { false };
let mut err =
self.bad_inference_failure_err(failure_span, arg_data,
error_code);
if silence { err.downgrade_to_delayed_bug(); }
return err;
};
let (source_kind, name, long_ty_path) =
kind.ty_localized_msg(self);
let failure_span =
if should_label_span && !failure_span.overlaps(span) {
Some(failure_span)
} else { None };
let mut infer_subdiags = Vec::new();
let mut multi_suggestions = Vec::new();
match kind {
InferSourceKind::LetBinding {
insert_span, pattern_name, ty, def_id } => {
infer_subdiags.push(SourceKindSubdiag::LetLike {
span: insert_span,
name: pattern_name.map(|name|
name.to_string()).unwrap_or_else(String::new),
x_kind: arg_data.where_x_is_kind(ty),
prefix_kind: arg_data.kind.clone(),
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
arg_name: arg_data.name,
kind: if pattern_name.is_some() {
"with_pattern"
} else { "other" },
type_name: ty_to_string(self, ty, def_id),
});
}
InferSourceKind::ClosureArg { insert_span, ty, .. } => {
infer_subdiags.push(SourceKindSubdiag::LetLike {
span: insert_span,
name: String::new(),
x_kind: arg_data.where_x_is_kind(ty),
prefix_kind: arg_data.kind.clone(),
prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
arg_name: arg_data.name,
kind: "closure",
type_name: ty_to_string(self, ty, None),
});
}
InferSourceKind::GenericArg {
insert_span,
argument_index,
generics_def_id,
def_id: _,
generic_args,
have_turbofish } => {
let generics = self.tcx.generics_of(generics_def_id);
let is_type = term.as_type().is_some();
let (parent_exists, parent_prefix, parent_name) =
InferenceDiagnosticsParentData::for_parent_def_id(self.tcx,
generics_def_id).map_or((false, String::new(),
String::new()),
|parent|
{ (true, parent.prefix.to_string(), parent.name) });
infer_subdiags.push(SourceKindSubdiag::GenericLabel {
span,
is_type,
param_name: generics.own_params[argument_index].name.to_string(),
parent_exists,
parent_prefix,
parent_name,
});
let args =
if self.tcx.get_diagnostic_item(sym::iterator_collect_fn) ==
Some(generics_def_id) {
"Vec<_>".to_string()
} else {
let mut p = fmt_printer(self, Namespace::TypeNS);
p.comma_sep(generic_args.iter().copied().map(|arg|
{
if arg.is_suggestable(self.tcx, true) { return arg; }
match arg.kind() {
GenericArgKind::Lifetime(_) =>
::rustc_middle::util::bug::bug_fmt(format_args!("unexpected lifetime")),
GenericArgKind::Type(_) =>
self.next_ty_var(DUMMY_SP).into(),
GenericArgKind::Const(_) =>
self.next_const_var(DUMMY_SP).into(),
}
})).unwrap();
p.into_buffer()
};
if !have_turbofish {
infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
span: insert_span,
arg_count: generic_args.len(),
args,
});
}
}
InferSourceKind::FullyQualifiedMethodCall {
receiver, successor, args, def_id } => {
let placeholder = Some(self.next_ty_var(DUMMY_SP));
if let Some(args) =
args.make_suggestable(self.infcx.tcx, true, placeholder) {
let mut p = fmt_printer(self, Namespace::ValueNS);
p.print_def_path(def_id, args).unwrap();
let def_path = p.into_buffer();
let adjustment =
match typeck_results.expr_adjustments(receiver) {
[Adjustment {
kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ },
.., Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ }] =>
"",
[.., Adjustment {
kind: Adjust::Borrow(AutoBorrow::Ref(mut_)), target: _ }] =>
hir::Mutability::from(*mut_).ref_prefix_str(),
_ => "",
};
multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified(receiver.span,
def_path, adjustment, successor));
}
}
InferSourceKind::ClosureReturn { ty, data, should_wrap_expr }
=> {
let placeholder = Some(self.next_ty_var(DUMMY_SP));
if let Some(ty) =
ty.make_suggestable(self.infcx.tcx, true, placeholder) {
let ty_info = ty_to_string(self, ty, None);
multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(ty_info,
data, should_wrap_expr));
}
}
}
let mut err =
match error_code {
TypeAnnotationNeeded::E0282 =>
self.dcx().create_err(AnnotationRequired {
span,
source_kind,
source_name: &name,
failure_span,
infer_subdiags,
multi_suggestions,
bad_label: None,
}),
TypeAnnotationNeeded::E0283 =>
self.dcx().create_err(AmbiguousImpl {
span,
source_kind,
source_name: &name,
failure_span,
infer_subdiags,
multi_suggestions,
bad_label: None,
}),
TypeAnnotationNeeded::E0284 =>
self.dcx().create_err(AmbiguousReturn {
span,
source_kind,
source_name: &name,
failure_span,
infer_subdiags,
multi_suggestions,
bad_label: None,
}),
};
*err.long_ty_path() = long_ty_path;
if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } =
kind {
err.downgrade_to_delayed_bug();
}
err
}
}
}#[instrument(level = "debug", skip(self, error_code))]
463 pub fn emit_inference_failure_err(
464 &self,
465 body_def_id: LocalDefId,
466 failure_span: Span,
467 term: Term<'tcx>,
468 error_code: TypeAnnotationNeeded,
469 should_label_span: bool,
470 ) -> Diag<'a> {
471 let term = self.resolve_vars_if_possible(term);
472 let arg_data = self
473 .extract_inference_diagnostics_data(term, ty::print::RegionHighlightMode::default());
474
475 let Some(typeck_results) = &self.typeck_results else {
476 return self.bad_inference_failure_err(failure_span, arg_data, error_code);
480 };
481
482 let mut local_visitor = FindInferSourceVisitor::new(self, typeck_results, term);
483 if let Some(body) = self.tcx.hir_maybe_body_owned_by(
484 self.tcx.typeck_root_def_id(body_def_id.to_def_id()).expect_local(),
485 ) {
486 let expr = body.value;
487 local_visitor.visit_expr(expr);
488 }
489
490 let Some(InferSource { span, kind }) = local_visitor.infer_source else {
491 let silence = if let DefKind::AssocFn = self.tcx.def_kind(body_def_id)
492 && let parent = self.tcx.parent(body_def_id.into())
493 && self.tcx.is_automatically_derived(parent)
494 && let Some(parent) = parent.as_local()
495 && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(parent)
496 && let hir::ItemKind::Impl(imp) = item.kind
497 && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = imp.self_ty.kind
498 && let Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, def_id) = path.res
499 && let Some(def_id) = def_id.as_local()
500 && let hir::Node::Item(item) = self.tcx.hir_node_by_def_id(def_id)
501 {
502 item.kind.recovered()
507 } else {
508 false
509 };
510 let mut err = self.bad_inference_failure_err(failure_span, arg_data, error_code);
511 if silence {
512 err.downgrade_to_delayed_bug();
513 }
514 return err;
515 };
516
517 let (source_kind, name, long_ty_path) = kind.ty_localized_msg(self);
518 let failure_span = if should_label_span && !failure_span.overlaps(span) {
519 Some(failure_span)
520 } else {
521 None
522 };
523
524 let mut infer_subdiags = Vec::new();
525 let mut multi_suggestions = Vec::new();
526 match kind {
527 InferSourceKind::LetBinding { insert_span, pattern_name, ty, def_id } => {
528 infer_subdiags.push(SourceKindSubdiag::LetLike {
529 span: insert_span,
530 name: pattern_name.map(|name| name.to_string()).unwrap_or_else(String::new),
531 x_kind: arg_data.where_x_is_kind(ty),
532 prefix_kind: arg_data.kind.clone(),
533 prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
534 arg_name: arg_data.name,
535 kind: if pattern_name.is_some() { "with_pattern" } else { "other" },
536 type_name: ty_to_string(self, ty, def_id),
537 });
538 }
539 InferSourceKind::ClosureArg { insert_span, ty, .. } => {
540 infer_subdiags.push(SourceKindSubdiag::LetLike {
541 span: insert_span,
542 name: String::new(),
543 x_kind: arg_data.where_x_is_kind(ty),
544 prefix_kind: arg_data.kind.clone(),
545 prefix: arg_data.kind.try_get_prefix().unwrap_or_default(),
546 arg_name: arg_data.name,
547 kind: "closure",
548 type_name: ty_to_string(self, ty, None),
549 });
550 }
551 InferSourceKind::GenericArg {
552 insert_span,
553 argument_index,
554 generics_def_id,
555 def_id: _,
556 generic_args,
557 have_turbofish,
558 } => {
559 let generics = self.tcx.generics_of(generics_def_id);
560 let is_type = term.as_type().is_some();
561
562 let (parent_exists, parent_prefix, parent_name) =
563 InferenceDiagnosticsParentData::for_parent_def_id(self.tcx, generics_def_id)
564 .map_or((false, String::new(), String::new()), |parent| {
565 (true, parent.prefix.to_string(), parent.name)
566 });
567
568 infer_subdiags.push(SourceKindSubdiag::GenericLabel {
569 span,
570 is_type,
571 param_name: generics.own_params[argument_index].name.to_string(),
572 parent_exists,
573 parent_prefix,
574 parent_name,
575 });
576
577 let args = if self.tcx.get_diagnostic_item(sym::iterator_collect_fn)
578 == Some(generics_def_id)
579 {
580 "Vec<_>".to_string()
581 } else {
582 let mut p = fmt_printer(self, Namespace::TypeNS);
583 p.comma_sep(generic_args.iter().copied().map(|arg| {
584 if arg.is_suggestable(self.tcx, true) {
585 return arg;
586 }
587
588 match arg.kind() {
589 GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
590 GenericArgKind::Type(_) => self.next_ty_var(DUMMY_SP).into(),
591 GenericArgKind::Const(_) => self.next_const_var(DUMMY_SP).into(),
592 }
593 }))
594 .unwrap();
595 p.into_buffer()
596 };
597
598 if !have_turbofish {
599 infer_subdiags.push(SourceKindSubdiag::GenericSuggestion {
600 span: insert_span,
601 arg_count: generic_args.len(),
602 args,
603 });
604 }
605 }
606 InferSourceKind::FullyQualifiedMethodCall { receiver, successor, args, def_id } => {
607 let placeholder = Some(self.next_ty_var(DUMMY_SP));
608 if let Some(args) = args.make_suggestable(self.infcx.tcx, true, placeholder) {
609 let mut p = fmt_printer(self, Namespace::ValueNS);
610 p.print_def_path(def_id, args).unwrap();
611 let def_path = p.into_buffer();
612
613 let adjustment = match typeck_results.expr_adjustments(receiver) {
617 [
618 Adjustment { kind: Adjust::Deref(DerefAdjustKind::Builtin), target: _ },
619 ..,
620 Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(..)), target: _ },
621 ] => "",
622 [
623 ..,
624 Adjustment { kind: Adjust::Borrow(AutoBorrow::Ref(mut_)), target: _ },
625 ] => hir::Mutability::from(*mut_).ref_prefix_str(),
626 _ => "",
627 };
628
629 multi_suggestions.push(SourceKindMultiSuggestion::new_fully_qualified(
630 receiver.span,
631 def_path,
632 adjustment,
633 successor,
634 ));
635 }
636 }
637 InferSourceKind::ClosureReturn { ty, data, should_wrap_expr } => {
638 let placeholder = Some(self.next_ty_var(DUMMY_SP));
639 if let Some(ty) = ty.make_suggestable(self.infcx.tcx, true, placeholder) {
640 let ty_info = ty_to_string(self, ty, None);
641 multi_suggestions.push(SourceKindMultiSuggestion::new_closure_return(
642 ty_info,
643 data,
644 should_wrap_expr,
645 ));
646 }
647 }
648 }
649 let mut err = match error_code {
650 TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
651 span,
652 source_kind,
653 source_name: &name,
654 failure_span,
655 infer_subdiags,
656 multi_suggestions,
657 bad_label: None,
658 }),
659 TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
660 span,
661 source_kind,
662 source_name: &name,
663 failure_span,
664 infer_subdiags,
665 multi_suggestions,
666 bad_label: None,
667 }),
668 TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
669 span,
670 source_kind,
671 source_name: &name,
672 failure_span,
673 infer_subdiags,
674 multi_suggestions,
675 bad_label: None,
676 }),
677 };
678 *err.long_ty_path() = long_ty_path;
679 if let InferSourceKind::ClosureArg { kind: PatKind::Err(_), .. } = kind {
680 err.downgrade_to_delayed_bug();
682 }
683 err
684 }
685}
686
687#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InferSource<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "InferSource",
"span", &self.span, "kind", &&self.kind)
}
}Debug)]
688struct InferSource<'tcx> {
689 span: Span,
690 kind: InferSourceKind<'tcx>,
691}
692
693#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InferSourceKind<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
InferSourceKind::LetBinding {
insert_span: __self_0,
pattern_name: __self_1,
ty: __self_2,
def_id: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"LetBinding", "insert_span", __self_0, "pattern_name",
__self_1, "ty", __self_2, "def_id", &__self_3),
InferSourceKind::ClosureArg {
insert_span: __self_0, ty: __self_1, kind: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"ClosureArg", "insert_span", __self_0, "ty", __self_1,
"kind", &__self_2),
InferSourceKind::GenericArg {
insert_span: __self_0,
argument_index: __self_1,
generics_def_id: __self_2,
def_id: __self_3,
generic_args: __self_4,
have_turbofish: __self_5 } => {
let names: &'static _ =
&["insert_span", "argument_index", "generics_def_id",
"def_id", "generic_args", "have_turbofish"];
let values: &[&dyn ::core::fmt::Debug] =
&[__self_0, __self_1, __self_2, __self_3, __self_4,
&__self_5];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"GenericArg", names, values)
}
InferSourceKind::FullyQualifiedMethodCall {
receiver: __self_0,
successor: __self_1,
args: __self_2,
def_id: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"FullyQualifiedMethodCall", "receiver", __self_0,
"successor", __self_1, "args", __self_2, "def_id",
&__self_3),
InferSourceKind::ClosureReturn {
ty: __self_0, data: __self_1, should_wrap_expr: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"ClosureReturn", "ty", __self_0, "data", __self_1,
"should_wrap_expr", &__self_2),
}
}
}Debug)]
694enum InferSourceKind<'tcx> {
695 LetBinding {
696 insert_span: Span,
697 pattern_name: Option<Ident>,
698 ty: Ty<'tcx>,
699 def_id: Option<DefId>,
700 },
701 ClosureArg {
702 insert_span: Span,
703 ty: Ty<'tcx>,
704 kind: PatKind<'tcx>,
705 },
706 GenericArg {
707 insert_span: Span,
708 argument_index: usize,
709 generics_def_id: DefId,
710 def_id: DefId,
711 generic_args: &'tcx [GenericArg<'tcx>],
712 have_turbofish: bool,
713 },
714 FullyQualifiedMethodCall {
715 receiver: &'tcx Expr<'tcx>,
716 successor: (&'static str, BytePos),
719 args: GenericArgsRef<'tcx>,
720 def_id: DefId,
721 },
722 ClosureReturn {
723 ty: Ty<'tcx>,
724 data: &'tcx FnRetTy<'tcx>,
725 should_wrap_expr: Option<Span>,
726 },
727}
728
729impl<'tcx> InferSource<'tcx> {
730 fn from_expansion(&self) -> bool {
731 let source_from_expansion = match self.kind {
732 InferSourceKind::LetBinding { insert_span, .. }
733 | InferSourceKind::ClosureArg { insert_span, .. }
734 | InferSourceKind::GenericArg { insert_span, .. } => insert_span.from_expansion(),
735 InferSourceKind::FullyQualifiedMethodCall { receiver, .. } => {
736 receiver.span.from_expansion()
737 }
738 InferSourceKind::ClosureReturn { data, should_wrap_expr, .. } => {
739 data.span().from_expansion() || should_wrap_expr.is_some_and(Span::from_expansion)
740 }
741 };
742 source_from_expansion || self.span.from_expansion()
743 }
744}
745
746impl<'tcx> InferSourceKind<'tcx> {
747 fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
748 let mut long_ty_path = None;
749 match *self {
750 InferSourceKind::LetBinding { ty, .. }
751 | InferSourceKind::ClosureArg { ty, .. }
752 | InferSourceKind::ClosureReturn { ty, .. } => {
753 if ty.is_closure() {
754 ("closure", closure_as_fn_str(infcx, ty), long_ty_path)
755 } else if !ty.is_ty_or_numeric_infer() {
756 ("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
757 } else {
758 ("other", String::new(), long_ty_path)
759 }
760 }
761 InferSourceKind::GenericArg { .. }
763 | InferSourceKind::FullyQualifiedMethodCall { .. } => {
764 ("other", String::new(), long_ty_path)
765 }
766 }
767 }
768}
769
770#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for InsertableGenericArgs<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"InsertableGenericArgs", "insert_span", &self.insert_span, "args",
&self.args, "generics_def_id", &self.generics_def_id, "def_id",
&self.def_id, "have_turbofish", &&self.have_turbofish)
}
}Debug)]
771struct InsertableGenericArgs<'tcx> {
772 insert_span: Span,
773 args: GenericArgsRef<'tcx>,
774 generics_def_id: DefId,
775 def_id: DefId,
776 have_turbofish: bool,
777}
778
779struct FindInferSourceVisitor<'a, 'tcx> {
787 tecx: &'a TypeErrCtxt<'a, 'tcx>,
788 typeck_results: &'a TypeckResults<'tcx>,
789
790 target: Term<'tcx>,
791
792 attempt: usize,
793 infer_source_cost: usize,
794 infer_source: Option<InferSource<'tcx>>,
795}
796
797impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> {
798 fn new(
799 tecx: &'a TypeErrCtxt<'a, 'tcx>,
800 typeck_results: &'a TypeckResults<'tcx>,
801 target: Term<'tcx>,
802 ) -> Self {
803 FindInferSourceVisitor {
804 tecx,
805 typeck_results,
806
807 target,
808
809 attempt: 0,
810 infer_source_cost: usize::MAX,
811 infer_source: None,
812 }
813 }
814
815 fn source_cost(&self, source: &InferSource<'tcx>) -> usize {
820 #[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for CostCtxt<'tcx> {
#[inline]
fn clone(&self) -> CostCtxt<'tcx> {
let _: ::core::clone::AssertParamIsClone<TyCtxt<'tcx>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for CostCtxt<'tcx> { }Copy)]
821 struct CostCtxt<'tcx> {
822 tcx: TyCtxt<'tcx>,
823 }
824 impl<'tcx> CostCtxt<'tcx> {
825 fn arg_cost(self, arg: GenericArg<'tcx>) -> usize {
826 match arg.kind() {
827 GenericArgKind::Lifetime(_) => 0, GenericArgKind::Type(ty) => self.ty_cost(ty),
829 GenericArgKind::Const(_) => 3, }
831 }
832 fn ty_cost(self, ty: Ty<'tcx>) -> usize {
833 match *ty.kind() {
834 ty::Closure(..) => 1000,
835 ty::FnDef(..) => 150,
836 ty::FnPtr(..) => 30,
837 ty::Adt(def, args) => {
838 5 + self
839 .tcx
840 .generics_of(def.did())
841 .own_args_no_defaults(self.tcx, args)
842 .iter()
843 .map(|&arg| self.arg_cost(arg))
844 .sum::<usize>()
845 }
846 ty::Tuple(args) => 5 + args.iter().map(|arg| self.ty_cost(arg)).sum::<usize>(),
847 ty::Ref(_, ty, _) => 2 + self.ty_cost(ty),
848 ty::Infer(..) => 0,
849 _ => 1,
850 }
851 }
852 }
853
854 let tcx = self.tecx.tcx;
856 let ctx = CostCtxt { tcx };
857 match source.kind {
858 InferSourceKind::LetBinding { ty, .. } => ctx.ty_cost(ty),
859 InferSourceKind::ClosureArg { ty, .. } => ctx.ty_cost(ty),
860 InferSourceKind::GenericArg { def_id, generic_args, .. } => {
861 let variant_cost = match tcx.def_kind(def_id) {
862 DefKind::Variant | DefKind::Ctor(CtorOf::Variant, _) => 15,
864 _ => 10,
865 };
866 variant_cost + generic_args.iter().map(|&arg| ctx.arg_cost(arg)).sum::<usize>()
867 }
868 InferSourceKind::FullyQualifiedMethodCall { args, .. } => {
869 20 + args.iter().map(|arg| ctx.arg_cost(arg)).sum::<usize>()
870 }
871 InferSourceKind::ClosureReturn { ty, should_wrap_expr, .. } => {
872 30 + ctx.ty_cost(ty) + if should_wrap_expr.is_some() { 10 } else { 0 }
873 }
874 }
875 }
876
877 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("update_infer_source",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(879u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["new_source"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_source)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if new_source.from_expansion() { return; }
let cost = self.source_cost(&new_source) + self.attempt;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:886",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(886u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["cost"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&cost) as
&dyn Value))])
});
} else { ; }
};
self.attempt += 1;
if let Some(InferSource {
kind: InferSourceKind::GenericArg { def_id: did, .. }, .. })
= self.infer_source &&
let InferSourceKind::LetBinding { ref ty, ref mut def_id, ..
} = new_source.kind && ty.is_ty_or_numeric_infer() {
*def_id = Some(did);
}
if cost < self.infer_source_cost {
self.infer_source_cost = cost;
self.infer_source = Some(new_source);
}
}
}
}#[instrument(level = "debug", skip(self))]
880 fn update_infer_source(&mut self, mut new_source: InferSource<'tcx>) {
881 if new_source.from_expansion() {
882 return;
883 }
884
885 let cost = self.source_cost(&new_source) + self.attempt;
886 debug!(?cost);
887 self.attempt += 1;
888 if let Some(InferSource { kind: InferSourceKind::GenericArg { def_id: did, .. }, .. }) =
889 self.infer_source
890 && let InferSourceKind::LetBinding { ref ty, ref mut def_id, .. } = new_source.kind
891 && ty.is_ty_or_numeric_infer()
892 {
893 *def_id = Some(did);
896 }
897
898 if cost < self.infer_source_cost {
899 self.infer_source_cost = cost;
900 self.infer_source = Some(new_source);
901 }
902 }
903
904 fn node_args_opt(&self, hir_id: HirId) -> Option<GenericArgsRef<'tcx>> {
905 let args = self.typeck_results.node_args_opt(hir_id);
906 self.tecx.resolve_vars_if_possible(args)
907 }
908
909 fn opt_node_type(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
910 let ty = self.typeck_results.node_type_opt(hir_id);
911 self.tecx.resolve_vars_if_possible(ty)
912 }
913
914 fn generic_arg_is_target(&self, arg: GenericArg<'tcx>) -> bool {
917 if arg == self.target.into() {
918 return true;
919 }
920
921 match (arg.kind(), self.target.kind()) {
922 (GenericArgKind::Type(inner_ty), TermKind::Ty(target_ty)) => {
923 use ty::{Infer, TyVar};
924 match (inner_ty.kind(), target_ty.kind()) {
925 (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => {
926 self.tecx.sub_unification_table_root_var(a_vid)
927 == self.tecx.sub_unification_table_root_var(b_vid)
928 }
929 _ => false,
930 }
931 }
932 (GenericArgKind::Const(inner_ct), TermKind::Const(target_ct)) => {
933 match (inner_ct.kind(), target_ct.kind()) {
934 (
935 ty::ConstKind::Infer(ty::InferConst::Var(a_vid)),
936 ty::ConstKind::Infer(ty::InferConst::Var(b_vid)),
937 ) => self.tecx.root_const_var(a_vid) == self.tecx.root_const_var(b_vid),
938 _ => false,
939 }
940 }
941 _ => false,
942 }
943 }
944
945 fn generic_arg_contains_target(&self, arg: GenericArg<'tcx>) -> bool {
948 let mut walker = arg.walk();
949 while let Some(inner) = walker.next() {
950 if self.generic_arg_is_target(inner) {
951 return true;
952 }
953 match inner.kind() {
954 GenericArgKind::Lifetime(_) => {}
955 GenericArgKind::Type(ty) => {
956 if #[allow(non_exhaustive_omitted_patterns)] match ty.kind() {
ty::Alias(ty::Opaque, ..) | ty::Closure(..) | ty::CoroutineClosure(..) |
ty::Coroutine(..) => true,
_ => false,
}matches!(
957 ty.kind(),
958 ty::Alias(ty::Opaque, ..)
959 | ty::Closure(..)
960 | ty::CoroutineClosure(..)
961 | ty::Coroutine(..)
962 ) {
963 walker.skip_current_subtree();
974 }
975 }
976 GenericArgKind::Const(ct) => {
977 if #[allow(non_exhaustive_omitted_patterns)] match ct.kind() {
ty::ConstKind::Unevaluated(..) => true,
_ => false,
}matches!(ct.kind(), ty::ConstKind::Unevaluated(..)) {
978 walker.skip_current_subtree();
981 }
982 }
983 }
984 }
985 false
986 }
987
988 fn expr_inferred_arg_iter(
989 &self,
990 expr: &'tcx hir::Expr<'tcx>,
991 ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
992 let tcx = self.tecx.tcx;
993 match expr.kind {
994 hir::ExprKind::Path(ref path) => {
995 if let Some(args) = self.node_args_opt(expr.hir_id) {
996 return self.path_inferred_arg_iter(expr.hir_id, args, path);
997 }
998 }
999 hir::ExprKind::Struct(&hir::QPath::Resolved(_self_ty, path), _, _)
1010 if #[allow(non_exhaustive_omitted_patterns)] match path.res {
Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => true,
_ => false,
}matches!(path.res, Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) => {
1017 if let Some(ty) = self.opt_node_type(expr.hir_id)
1018 && let ty::Adt(_, args) = ty.kind()
1019 {
1020 return Box::new(self.resolved_path_inferred_arg_iter(path, args));
1021 }
1022 }
1023 hir::ExprKind::MethodCall(segment, ..) => {
1024 if let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id) {
1025 let generics = tcx.generics_of(def_id);
1026 let insertable = try {
1027 if generics.has_impl_trait() {
1028 None?
1029 }
1030 let args = self.node_args_opt(expr.hir_id)?;
1031 let span = tcx.hir_span(segment.hir_id);
1032 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1033 InsertableGenericArgs {
1034 insert_span,
1035 args,
1036 generics_def_id: def_id,
1037 def_id,
1038 have_turbofish: false,
1039 }
1040 };
1041 return Box::new(insertable.into_iter());
1042 }
1043 }
1044 _ => {}
1045 }
1046
1047 Box::new(iter::empty())
1048 }
1049
1050 fn resolved_path_inferred_arg_iter(
1051 &self,
1052 path: &'tcx hir::Path<'tcx>,
1053 args: GenericArgsRef<'tcx>,
1054 ) -> impl Iterator<Item = InsertableGenericArgs<'tcx>> + 'tcx {
1055 let tcx = self.tecx.tcx;
1056 let have_turbofish = path.segments.iter().any(|segment| {
1057 segment.args.is_some_and(|args| args.args.iter().any(|arg| arg.is_ty_or_const()))
1058 });
1059 let last_segment_using_path_data = try {
1065 let generics_def_id = tcx.res_generics_def_id(path.res)?;
1066 let generics = tcx.generics_of(generics_def_id);
1067 if generics.has_impl_trait() {
1068 do yeet ();
1069 }
1070 let insert_span =
1071 path.segments.last().unwrap().ident.span.shrink_to_hi().with_hi(path.span.hi());
1072 InsertableGenericArgs {
1073 insert_span,
1074 args,
1075 generics_def_id,
1076 def_id: path.res.def_id(),
1077 have_turbofish,
1078 }
1079 };
1080
1081 path.segments
1082 .iter()
1083 .filter_map(move |segment| {
1084 let res = segment.res;
1085 let generics_def_id = tcx.res_generics_def_id(res)?;
1086 let generics = tcx.generics_of(generics_def_id);
1087 if generics.has_impl_trait() {
1088 return None;
1089 }
1090 let span = tcx.hir_span(segment.hir_id);
1091 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1092 Some(InsertableGenericArgs {
1093 insert_span,
1094 args,
1095 generics_def_id,
1096 def_id: res.def_id(),
1097 have_turbofish,
1098 })
1099 })
1100 .chain(last_segment_using_path_data)
1101 }
1102
1103 fn path_inferred_arg_iter(
1104 &self,
1105 hir_id: HirId,
1106 args: GenericArgsRef<'tcx>,
1107 qpath: &'tcx hir::QPath<'tcx>,
1108 ) -> Box<dyn Iterator<Item = InsertableGenericArgs<'tcx>> + 'a> {
1109 let tcx = self.tecx.tcx;
1110 match qpath {
1111 hir::QPath::Resolved(_self_ty, path) => {
1112 Box::new(self.resolved_path_inferred_arg_iter(path, args))
1113 }
1114 hir::QPath::TypeRelative(ty, segment) => {
1115 let Some(def_id) = self.typeck_results.type_dependent_def_id(hir_id) else {
1116 return Box::new(iter::empty());
1117 };
1118
1119 let generics = tcx.generics_of(def_id);
1120 let segment = if !segment.infer_args || generics.has_impl_trait() {
1121 None
1122 } else {
1123 let span = tcx.hir_span(segment.hir_id);
1124 let insert_span = segment.ident.span.shrink_to_hi().with_hi(span.hi());
1125 Some(InsertableGenericArgs {
1126 insert_span,
1127 args,
1128 generics_def_id: def_id,
1129 def_id,
1130 have_turbofish: false,
1131 })
1132 };
1133
1134 let parent_def_id = generics.parent.unwrap();
1135 if let DefKind::Impl { .. } = tcx.def_kind(parent_def_id) {
1136 let parent_ty = tcx.type_of(parent_def_id).instantiate(tcx, args);
1137 match (parent_ty.kind(), &ty.kind) {
1138 (
1139 ty::Adt(def, args),
1140 hir::TyKind::Path(hir::QPath::Resolved(_self_ty, path)),
1141 ) => {
1142 if tcx.res_generics_def_id(path.res) != Some(def.did()) {
1143 match path.res {
1144 Res::Def(DefKind::TyAlias, _) => {
1145 }
1152 Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {}
1155 _ => {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1155",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::WARN,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1155u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::WARN <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::WARN <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("unexpected path: def={0:?} args={1:?} path={2:?}",
def, args, path) as &dyn Value))])
});
} else { ; }
}warn!(
1156 "unexpected path: def={:?} args={:?} path={:?}",
1157 def, args, path,
1158 ),
1159 }
1160 } else {
1161 return Box::new(
1162 self.resolved_path_inferred_arg_iter(path, args).chain(segment),
1163 );
1164 }
1165 }
1166 _ => (),
1167 }
1168 }
1169
1170 Box::new(segment.into_iter())
1171 }
1172 }
1173 }
1174}
1175
1176impl<'a, 'tcx> Visitor<'tcx> for FindInferSourceVisitor<'a, 'tcx> {
1177 type NestedFilter = nested_filter::OnlyBodies;
1178
1179 fn maybe_tcx(&mut self) -> Self::MaybeTyCtxt {
1180 self.tecx.tcx
1181 }
1182
1183 fn visit_local(&mut self, local: &'tcx LetStmt<'tcx>) {
1184 intravisit::walk_local(self, local);
1185
1186 if let Some(ty) = self.opt_node_type(local.hir_id) {
1187 if self.generic_arg_contains_target(ty.into()) {
1188 match local.source {
1189 LocalSource::Normal if local.ty.is_none() => {
1190 self.update_infer_source(InferSource {
1191 span: local.pat.span,
1192 kind: InferSourceKind::LetBinding {
1193 insert_span: local.pat.span.shrink_to_hi(),
1194 pattern_name: local.pat.simple_ident(),
1195 ty,
1196 def_id: None,
1197 },
1198 })
1199 }
1200 _ => {}
1201 }
1202 }
1203 }
1204 }
1205
1206 fn visit_body(&mut self, body: &Body<'tcx>) {
1209 for param in body.params {
1210 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1210",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1210u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("param: span {0:?}, ty_span {1:?}, pat.span {2:?}",
param.span, param.ty_span, param.pat.span) as &dyn Value))])
});
} else { ; }
};debug!(
1211 "param: span {:?}, ty_span {:?}, pat.span {:?}",
1212 param.span, param.ty_span, param.pat.span
1213 );
1214 if param.ty_span != param.pat.span {
1215 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1215",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1215u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("skipping param: has explicit type")
as &dyn Value))])
});
} else { ; }
};debug!("skipping param: has explicit type");
1216 continue;
1217 }
1218
1219 let Some(param_ty) = self.opt_node_type(param.hir_id) else { continue };
1220
1221 if self.generic_arg_contains_target(param_ty.into()) {
1222 self.update_infer_source(InferSource {
1223 span: param.pat.span,
1224 kind: InferSourceKind::ClosureArg {
1225 insert_span: param.pat.span.shrink_to_hi(),
1226 ty: param_ty,
1227 kind: param.pat.kind,
1228 },
1229 })
1230 }
1231 }
1232 intravisit::walk_body(self, body);
1233 }
1234
1235 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_expr",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1235u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["expr"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&expr)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = self.tecx.tcx;
match expr.kind {
ExprKind::Call(func, args) => {
for arg in args { self.visit_expr(arg); }
self.visit_expr(func);
}
_ => intravisit::walk_expr(self, expr),
}
for args in self.expr_inferred_arg_iter(expr) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs:1251",
"rustc_trait_selection::error_reporting::infer::need_type_info",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs"),
::tracing_core::__macro_support::Option::Some(1251u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::error_reporting::infer::need_type_info"),
::tracing_core::field::FieldSet::new(&["args"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&args) as
&dyn Value))])
});
} else { ; }
};
let InsertableGenericArgs {
insert_span, args, generics_def_id, def_id, have_turbofish
} = args;
let generics = tcx.generics_of(generics_def_id);
if let Some(mut argument_index) =
generics.own_args(args).iter().position(|&arg|
self.generic_arg_contains_target(arg)) {
if generics.has_own_self() { argument_index += 1; }
let args = self.tecx.resolve_vars_if_possible(args);
let generic_args =
&generics.own_args_no_defaults(tcx,
args)[generics.own_counts().lifetimes..];
let span =
match expr.kind {
ExprKind::MethodCall(path, ..) => path.ident.span,
_ => expr.span,
};
self.update_infer_source(InferSource {
span,
kind: InferSourceKind::GenericArg {
insert_span,
argument_index,
generics_def_id,
def_id,
generic_args,
have_turbofish,
},
});
}
}
if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
if let (&ExprKind::Closure(&Closure {
fn_decl, body, fn_decl_span, .. }), ty::Closure(_, args)) =
(&expr.kind, node_ty.kind()) {
let output = args.as_closure().sig().output().skip_binder();
if self.generic_arg_contains_target(output.into()) {
let body = self.tecx.tcx.hir_body(body);
let should_wrap_expr =
if #[allow(non_exhaustive_omitted_patterns)] match body.value.kind
{
ExprKind::Block(..) => true,
_ => false,
} {
None
} else { Some(body.value.span.shrink_to_hi()) };
self.update_infer_source(InferSource {
span: fn_decl_span,
kind: InferSourceKind::ClosureReturn {
ty: output,
data: &fn_decl.output,
should_wrap_expr,
},
})
}
}
}
let has_impl_trait =
|def_id|
{
iter::successors(Some(tcx.generics_of(def_id)),
|generics|
{
generics.parent.map(|def_id| tcx.generics_of(def_id))
}).any(|generics| generics.has_impl_trait())
};
if let ExprKind::MethodCall(path, receiver, method_args, span) =
expr.kind &&
let Some(args) = self.node_args_opt(expr.hir_id) &&
args.iter().any(|arg| self.generic_arg_contains_target(arg))
&&
let Some(def_id) =
self.typeck_results.type_dependent_def_id(expr.hir_id) &&
self.tecx.tcx.trait_of_assoc(def_id).is_some() &&
!has_impl_trait(def_id) &&
tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
{
let successor =
method_args.get(0).map_or_else(|| (")", span.hi()),
|arg| (", ", arg.span.lo()));
let args = self.tecx.resolve_vars_if_possible(args);
self.update_infer_source(InferSource {
span: path.ident.span,
kind: InferSourceKind::FullyQualifiedMethodCall {
receiver,
successor,
args,
def_id,
},
})
}
}
}
}#[instrument(level = "debug", skip(self))]
1236 fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
1237 let tcx = self.tecx.tcx;
1238 match expr.kind {
1239 ExprKind::Call(func, args) => {
1242 for arg in args {
1243 self.visit_expr(arg);
1244 }
1245 self.visit_expr(func);
1246 }
1247 _ => intravisit::walk_expr(self, expr),
1248 }
1249
1250 for args in self.expr_inferred_arg_iter(expr) {
1251 debug!(?args);
1252 let InsertableGenericArgs {
1253 insert_span,
1254 args,
1255 generics_def_id,
1256 def_id,
1257 have_turbofish,
1258 } = args;
1259 let generics = tcx.generics_of(generics_def_id);
1260 if let Some(mut argument_index) = generics
1261 .own_args(args)
1262 .iter()
1263 .position(|&arg| self.generic_arg_contains_target(arg))
1264 {
1265 if generics.has_own_self() {
1266 argument_index += 1;
1267 }
1268 let args = self.tecx.resolve_vars_if_possible(args);
1269 let generic_args =
1270 &generics.own_args_no_defaults(tcx, args)[generics.own_counts().lifetimes..];
1271 let span = match expr.kind {
1272 ExprKind::MethodCall(path, ..) => path.ident.span,
1273 _ => expr.span,
1274 };
1275
1276 self.update_infer_source(InferSource {
1277 span,
1278 kind: InferSourceKind::GenericArg {
1279 insert_span,
1280 argument_index,
1281 generics_def_id,
1282 def_id,
1283 generic_args,
1284 have_turbofish,
1285 },
1286 });
1287 }
1288 }
1289
1290 if let Some(node_ty) = self.opt_node_type(expr.hir_id) {
1291 if let (
1292 &ExprKind::Closure(&Closure { fn_decl, body, fn_decl_span, .. }),
1293 ty::Closure(_, args),
1294 ) = (&expr.kind, node_ty.kind())
1295 {
1296 let output = args.as_closure().sig().output().skip_binder();
1297 if self.generic_arg_contains_target(output.into()) {
1298 let body = self.tecx.tcx.hir_body(body);
1299 let should_wrap_expr = if matches!(body.value.kind, ExprKind::Block(..)) {
1300 None
1301 } else {
1302 Some(body.value.span.shrink_to_hi())
1303 };
1304 self.update_infer_source(InferSource {
1305 span: fn_decl_span,
1306 kind: InferSourceKind::ClosureReturn {
1307 ty: output,
1308 data: &fn_decl.output,
1309 should_wrap_expr,
1310 },
1311 })
1312 }
1313 }
1314 }
1315
1316 let has_impl_trait = |def_id| {
1317 iter::successors(Some(tcx.generics_of(def_id)), |generics| {
1318 generics.parent.map(|def_id| tcx.generics_of(def_id))
1319 })
1320 .any(|generics| generics.has_impl_trait())
1321 };
1322 if let ExprKind::MethodCall(path, receiver, method_args, span) = expr.kind
1323 && let Some(args) = self.node_args_opt(expr.hir_id)
1324 && args.iter().any(|arg| self.generic_arg_contains_target(arg))
1325 && let Some(def_id) = self.typeck_results.type_dependent_def_id(expr.hir_id)
1326 && self.tecx.tcx.trait_of_assoc(def_id).is_some()
1327 && !has_impl_trait(def_id)
1328 && tcx.hir_opt_delegation_sig_id(expr.hir_id.owner.def_id).is_none()
1331 {
1332 let successor =
1333 method_args.get(0).map_or_else(|| (")", span.hi()), |arg| (", ", arg.span.lo()));
1334 let args = self.tecx.resolve_vars_if_possible(args);
1335 self.update_infer_source(InferSource {
1336 span: path.ident.span,
1337 kind: InferSourceKind::FullyQualifiedMethodCall {
1338 receiver,
1339 successor,
1340 args,
1341 def_id,
1342 },
1343 })
1344 }
1345 }
1346}