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