]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
Rollup merge of #93613 - crlf0710:rename_to_async_iter, r=yaahc
[rust.git] / compiler / rustc_infer / src / infer / error_reporting / need_type_info.rs
1 use crate::infer::type_variable::TypeVariableOriginKind;
2 use crate::infer::{InferCtxt, Symbol};
3 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder};
4 use rustc_hir as hir;
5 use rustc_hir::def::{DefKind, Namespace};
6 use rustc_hir::def_id::DefId;
7 use rustc_hir::intravisit::{self, Visitor};
8 use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, MatchSource, Pat};
9 use rustc_middle::hir::nested_filter;
10 use rustc_middle::infer::unify_key::ConstVariableOriginKind;
11 use rustc_middle::ty::print::Print;
12 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
13 use rustc_middle::ty::{self, Const, DefIdTree, InferConst, Ty, TyCtxt, TypeFoldable, TypeFolder};
14 use rustc_span::symbol::kw;
15 use rustc_span::{sym, Span};
16 use std::borrow::Cow;
17
18 struct FindHirNodeVisitor<'a, 'tcx> {
19     infcx: &'a InferCtxt<'a, 'tcx>,
20     target: GenericArg<'tcx>,
21     target_span: Span,
22     found_node_ty: Option<Ty<'tcx>>,
23     found_local_pattern: Option<&'tcx Pat<'tcx>>,
24     found_arg_pattern: Option<&'tcx Pat<'tcx>>,
25     found_closure: Option<&'tcx Expr<'tcx>>,
26     found_method_call: Option<&'tcx Expr<'tcx>>,
27     found_exact_method_call: Option<&'tcx Expr<'tcx>>,
28     found_for_loop_iter: Option<&'tcx Expr<'tcx>>,
29     found_use_diagnostic: Option<UseDiagnostic<'tcx>>,
30 }
31
32 impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
33     fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>, target_span: Span) -> Self {
34         Self {
35             infcx,
36             target,
37             target_span,
38             found_node_ty: None,
39             found_local_pattern: None,
40             found_arg_pattern: None,
41             found_closure: None,
42             found_method_call: None,
43             found_exact_method_call: None,
44             found_for_loop_iter: None,
45             found_use_diagnostic: None,
46         }
47     }
48
49     fn node_type_opt(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
50         self.infcx.in_progress_typeck_results?.borrow().node_type_opt(hir_id)
51     }
52
53     fn node_ty_contains_target(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
54         self.node_type_opt(hir_id).map(|ty| self.infcx.resolve_vars_if_possible(ty)).filter(|ty| {
55             ty.walk().any(|inner| {
56                 inner == self.target
57                     || match (inner.unpack(), self.target.unpack()) {
58                         (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
59                             use ty::{Infer, TyVar};
60                             match (inner_ty.kind(), target_ty.kind()) {
61                                 (&Infer(TyVar(a_vid)), &Infer(TyVar(b_vid))) => self
62                                     .infcx
63                                     .inner
64                                     .borrow_mut()
65                                     .type_variables()
66                                     .sub_unified(a_vid, b_vid),
67                                 _ => false,
68                             }
69                         }
70                         _ => false,
71                     }
72             })
73         })
74     }
75
76     /// Determine whether the expression, assumed to be the callee within a `Call`,
77     /// corresponds to the `From::from` emitted in desugaring of the `?` operator.
78     fn is_try_conversion(&self, callee: &Expr<'tcx>) -> bool {
79         self.infcx
80             .trait_def_from_hir_fn(callee.hir_id)
81             .map_or(false, |def_id| self.infcx.is_try_conversion(callee.span, def_id))
82     }
83 }
84
85 impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
86     type NestedFilter = nested_filter::OnlyBodies;
87
88     fn nested_visit_map(&mut self) -> Self::Map {
89         self.infcx.tcx.hir()
90     }
91
92     fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
93         if let (None, Some(ty)) =
94             (self.found_local_pattern, self.node_ty_contains_target(local.hir_id))
95         {
96             self.found_local_pattern = Some(&*local.pat);
97             self.found_node_ty = Some(ty);
98         }
99         intravisit::walk_local(self, local);
100     }
101
102     fn visit_body(&mut self, body: &'tcx Body<'tcx>) {
103         for param in body.params {
104             if let (None, Some(ty)) =
105                 (self.found_arg_pattern, self.node_ty_contains_target(param.hir_id))
106             {
107                 self.found_arg_pattern = Some(&*param.pat);
108                 self.found_node_ty = Some(ty);
109             }
110         }
111         intravisit::walk_body(self, body);
112     }
113
114     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
115         if let ExprKind::Match(scrutinee, [_, arm], MatchSource::ForLoopDesugar) = expr.kind {
116             if let Some(pat) = arm.pat.for_loop_some() {
117                 if let Some(ty) = self.node_ty_contains_target(pat.hir_id) {
118                     self.found_for_loop_iter = Some(scrutinee);
119                     self.found_node_ty = Some(ty);
120                     return;
121                 }
122             }
123         }
124         if let ExprKind::MethodCall(segment, exprs, _) = expr.kind {
125             if segment.ident.span == self.target_span
126                 && Some(self.target)
127                     == self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
128                         typeck_results
129                             .borrow()
130                             .node_type_opt(exprs.first().unwrap().hir_id)
131                             .map(Into::into)
132                     })
133             {
134                 self.found_exact_method_call = Some(&expr);
135                 return;
136             }
137         }
138
139         // FIXME(const_generics): Currently, any uninferred `const` generics arguments
140         // are handled specially, but instead they should be handled in `annotate_method_call`,
141         // which currently doesn't work because this evaluates to `false` for const arguments.
142         // See https://github.com/rust-lang/rust/pull/77758 for more details.
143         if let Some(ty) = self.node_ty_contains_target(expr.hir_id) {
144             match expr.kind {
145                 ExprKind::Closure(..) => self.found_closure = Some(&expr),
146                 ExprKind::MethodCall(..) => self.found_method_call = Some(&expr),
147
148                 // If the given expression falls within the target span and is a
149                 // `From::from(e)` call emitted during desugaring of the `?` operator,
150                 // extract the types inferred before and after the call
151                 ExprKind::Call(callee, [arg])
152                     if self.target_span.contains(expr.span)
153                         && self.found_use_diagnostic.is_none()
154                         && self.is_try_conversion(callee) =>
155                 {
156                     self.found_use_diagnostic = self.node_type_opt(arg.hir_id).map(|pre_ty| {
157                         UseDiagnostic::TryConversion { pre_ty, post_ty: ty, span: callee.span }
158                     });
159                 }
160                 _ => {}
161             }
162         }
163         intravisit::walk_expr(self, expr);
164     }
165 }
166
167 /// An observation about the use site of a type to be emitted as an additional
168 /// note in an inference failure error.
169 enum UseDiagnostic<'tcx> {
170     /// Records the types inferred before and after `From::from` is called on the
171     /// error value within the desugaring of the `?` operator.
172     TryConversion { pre_ty: Ty<'tcx>, post_ty: Ty<'tcx>, span: Span },
173 }
174
175 impl UseDiagnostic<'_> {
176     /// Return a descriptor of the value at the use site
177     fn descr(&self) -> &'static str {
178         match self {
179             Self::TryConversion { .. } => "error for `?` operator",
180         }
181     }
182
183     /// Return a descriptor of the type at the use site
184     fn type_descr(&self) -> &'static str {
185         match self {
186             Self::TryConversion { .. } => "error type for `?` operator",
187         }
188     }
189
190     fn applies_to(&self, span: Span) -> bool {
191         match *self {
192             // In some cases the span for an inference failure due to try
193             // conversion contains the antecedent expression as well as the `?`
194             Self::TryConversion { span: s, .. } => span.contains(s) && span.hi() == s.hi(),
195         }
196     }
197
198     fn attach_note(&self, err: &mut DiagnosticBuilder<'_>) {
199         match *self {
200             Self::TryConversion { pre_ty, post_ty, .. } => {
201                 let intro = "`?` implicitly converts the error value";
202
203                 let msg = match (pre_ty.is_ty_infer(), post_ty.is_ty_infer()) {
204                     (true, true) => format!("{} using the `From` trait", intro),
205                     (false, true) => {
206                         format!("{} into a type implementing `From<{}>`", intro, pre_ty)
207                     }
208                     (true, false) => {
209                         format!("{} into `{}` using the `From` trait", intro, post_ty)
210                     }
211                     (false, false) => {
212                         format!(
213                             "{} into `{}` using its implementation of `From<{}>`",
214                             intro, post_ty, pre_ty
215                         )
216                     }
217                 };
218
219                 err.note(&msg);
220             }
221         }
222     }
223 }
224
225 /// Suggest giving an appropriate return type to a closure expression.
226 fn closure_return_type_suggestion(
227     err: &mut DiagnosticBuilder<'_>,
228     output: &FnRetTy<'_>,
229     body: &Body<'_>,
230     ret: &str,
231 ) {
232     let (arrow, post) = match output {
233         FnRetTy::DefaultReturn(_) => ("-> ", " "),
234         _ => ("", ""),
235     };
236     let suggestion = match body.value.kind {
237         ExprKind::Block(..) => vec![(output.span(), format!("{}{}{}", arrow, ret, post))],
238         _ => vec![
239             (output.span(), format!("{}{}{}{{ ", arrow, ret, post)),
240             (body.value.span.shrink_to_hi(), " }".to_string()),
241         ],
242     };
243     err.multipart_suggestion(
244         "give this closure an explicit return type without `_` placeholders",
245         suggestion,
246         Applicability::HasPlaceholders,
247     );
248 }
249
250 /// Given a closure signature, return a `String` containing a list of all its argument types.
251 fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
252     fn_sig
253         .inputs()
254         .skip_binder()
255         .iter()
256         .next()
257         .map(|args| args.tuple_fields().map(|arg| arg.to_string()).collect::<Vec<_>>().join(", "))
258         .unwrap_or_default()
259 }
260
261 pub enum TypeAnnotationNeeded {
262     /// ```compile_fail,E0282
263     /// let x = "hello".chars().rev().collect();
264     /// ```
265     E0282,
266     /// An implementation cannot be chosen unambiguously because of lack of information.
267     /// ```compile_fail,E0283
268     /// let _ = Default::default();
269     /// ```
270     E0283,
271     /// ```compile_fail,E0284
272     /// let mut d: u64 = 2;
273     /// d = d % 1u32.into();
274     /// ```
275     E0284,
276 }
277
278 impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
279     fn into(self) -> rustc_errors::DiagnosticId {
280         match self {
281             Self::E0282 => rustc_errors::error_code!(E0282),
282             Self::E0283 => rustc_errors::error_code!(E0283),
283             Self::E0284 => rustc_errors::error_code!(E0284),
284         }
285     }
286 }
287
288 /// Information about a constant or a type containing inference variables.
289 pub struct InferenceDiagnosticsData {
290     pub name: String,
291     pub span: Option<Span>,
292     pub kind: UnderspecifiedArgKind,
293     pub parent: Option<InferenceDiagnosticsParentData>,
294 }
295
296 /// Data on the parent definition where a generic argument was declared.
297 pub struct InferenceDiagnosticsParentData {
298     pub prefix: &'static str,
299     pub name: String,
300     pub def_id: DefId,
301 }
302
303 pub enum UnderspecifiedArgKind {
304     Type { prefix: Cow<'static, str> },
305     Const { is_parameter: bool },
306 }
307
308 impl UnderspecifiedArgKind {
309     fn descr(&self) -> &'static str {
310         match self {
311             Self::Type { .. } => "type",
312             Self::Const { .. } => "const",
313         }
314     }
315 }
316
317 impl InferenceDiagnosticsData {
318     /// Generate a label for a generic argument which can't be inferred. When not
319     /// much is known about the argument, `use_diag` may be used to describe the
320     /// labeled value.
321     fn cannot_infer_msg(&self, use_diag: Option<&UseDiagnostic<'_>>) -> String {
322         if self.name == "_" && matches!(self.kind, UnderspecifiedArgKind::Type { .. }) {
323             if let Some(use_diag) = use_diag {
324                 return format!("cannot infer type of {}", use_diag.descr());
325             }
326
327             return "cannot infer type".to_string();
328         }
329
330         let suffix = match (&self.parent, use_diag) {
331             (Some(parent), _) => format!(" declared on the {} `{}`", parent.prefix, parent.name),
332             (None, Some(use_diag)) => format!(" in {}", use_diag.type_descr()),
333             (None, None) => String::new(),
334         };
335
336         // For example: "cannot infer type for type parameter `T`"
337         format!("cannot infer {} `{}`{}", self.kind.prefix_string(), self.name, suffix)
338     }
339 }
340
341 impl InferenceDiagnosticsParentData {
342     fn for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<InferenceDiagnosticsParentData> {
343         let parent_def_id = tcx.parent(def_id)?;
344
345         let parent_name =
346             tcx.def_key(parent_def_id).disambiguated_data.data.get_opt_name()?.to_string();
347
348         Some(InferenceDiagnosticsParentData {
349             prefix: tcx.def_kind(parent_def_id).descr(parent_def_id),
350             name: parent_name,
351             def_id: parent_def_id,
352         })
353     }
354 }
355
356 impl UnderspecifiedArgKind {
357     fn prefix_string(&self) -> Cow<'static, str> {
358         match self {
359             Self::Type { prefix } => format!("type for {}", prefix).into(),
360             Self::Const { is_parameter: true } => "the value of const parameter".into(),
361             Self::Const { is_parameter: false } => "the value of the constant".into(),
362         }
363     }
364 }
365
366 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
367     /// Extracts data used by diagnostic for either types or constants
368     /// which were stuck during inference.
369     pub fn extract_inference_diagnostics_data(
370         &self,
371         arg: GenericArg<'tcx>,
372         highlight: Option<ty::print::RegionHighlightMode<'tcx>>,
373     ) -> InferenceDiagnosticsData {
374         match arg.unpack() {
375             GenericArgKind::Type(ty) => {
376                 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
377                     let mut inner = self.inner.borrow_mut();
378                     let ty_vars = &inner.type_variables();
379                     let var_origin = ty_vars.var_origin(ty_vid);
380                     if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
381                         var_origin.kind
382                     {
383                         if name != kw::SelfUpper {
384                             return InferenceDiagnosticsData {
385                                 name: name.to_string(),
386                                 span: Some(var_origin.span),
387                                 kind: UnderspecifiedArgKind::Type {
388                                     prefix: "type parameter".into(),
389                                 },
390                                 parent: def_id.and_then(|def_id| {
391                                     InferenceDiagnosticsParentData::for_def_id(self.tcx, def_id)
392                                 }),
393                             };
394                         }
395                     }
396                 }
397
398                 let mut s = String::new();
399                 let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
400                 if let Some(highlight) = highlight {
401                     printer.region_highlight_mode = highlight;
402                 }
403                 let _ = ty.print(printer);
404                 InferenceDiagnosticsData {
405                     name: s,
406                     span: None,
407                     kind: UnderspecifiedArgKind::Type { prefix: ty.prefix_string(self.tcx) },
408                     parent: None,
409                 }
410             }
411             GenericArgKind::Const(ct) => {
412                 match ct.val() {
413                     ty::ConstKind::Infer(InferConst::Var(vid)) => {
414                         let origin = self
415                             .inner
416                             .borrow_mut()
417                             .const_unification_table()
418                             .probe_value(vid)
419                             .origin;
420                         if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
421                             origin.kind
422                         {
423                             return InferenceDiagnosticsData {
424                                 name: name.to_string(),
425                                 span: Some(origin.span),
426                                 kind: UnderspecifiedArgKind::Const { is_parameter: true },
427                                 parent: InferenceDiagnosticsParentData::for_def_id(
428                                     self.tcx, def_id,
429                                 ),
430                             };
431                         }
432
433                         debug_assert!(!origin.span.is_dummy());
434                         let mut s = String::new();
435                         let mut printer =
436                             ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
437                         if let Some(highlight) = highlight {
438                             printer.region_highlight_mode = highlight;
439                         }
440                         let _ = ct.print(printer);
441                         InferenceDiagnosticsData {
442                             name: s,
443                             span: Some(origin.span),
444                             kind: UnderspecifiedArgKind::Const { is_parameter: false },
445                             parent: None,
446                         }
447                     }
448                     ty::ConstKind::Unevaluated(ty::Unevaluated { substs, .. }) => {
449                         assert!(substs.has_infer_types_or_consts());
450
451                         // FIXME: We only use the first inference variable we encounter in
452                         // `substs` here, this gives insufficiently informative diagnostics
453                         // in case there are multiple inference variables
454                         for s in substs.iter() {
455                             match s.unpack() {
456                                 GenericArgKind::Type(t) => match t.kind() {
457                                     ty::Infer(_) => {
458                                         return self.extract_inference_diagnostics_data(s, None);
459                                     }
460                                     _ => {}
461                                 },
462                                 GenericArgKind::Const(c) => match c.val() {
463                                     ty::ConstKind::Infer(InferConst::Var(_)) => {
464                                         return self.extract_inference_diagnostics_data(s, None);
465                                     }
466                                     _ => {}
467                                 },
468                                 _ => {}
469                             }
470                         }
471                         bug!(
472                             "expected an inference variable in substs of unevaluated const {:?}",
473                             ct
474                         );
475                     }
476                     _ => {
477                         bug!("unexpect const: {:?}", ct);
478                     }
479                 }
480             }
481             GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
482         }
483     }
484
485     pub fn emit_inference_failure_err(
486         &self,
487         body_id: Option<hir::BodyId>,
488         span: Span,
489         arg: GenericArg<'tcx>,
490         impl_candidates: Vec<ty::TraitRef<'tcx>>,
491         error_code: TypeAnnotationNeeded,
492     ) -> DiagnosticBuilder<'tcx> {
493         let arg = self.resolve_vars_if_possible(arg);
494         let arg_data = self.extract_inference_diagnostics_data(arg, None);
495
496         let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
497         let ty_to_string = |ty: Ty<'tcx>| -> String {
498             let mut s = String::new();
499             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
500             let mut inner = self.inner.borrow_mut();
501             let ty_vars = inner.type_variables();
502             let getter = move |ty_vid| {
503                 let var_origin = ty_vars.var_origin(ty_vid);
504                 if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
505                     return Some(name.to_string());
506                 }
507                 None
508             };
509             printer.name_resolver = Some(Box::new(&getter));
510             let _ = if let ty::FnDef(..) = ty.kind() {
511                 // We don't want the regular output for `fn`s because it includes its path in
512                 // invalid pseudo-syntax, we want the `fn`-pointer output instead.
513                 ty.fn_sig(self.tcx).print(printer)
514             } else {
515                 ty.print(printer)
516             };
517             s
518         };
519
520         if let Some(body_id) = body_id {
521             let expr = self.tcx.hir().expect_expr(body_id.hir_id);
522             local_visitor.visit_expr(expr);
523         }
524         let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
525             pattern.span
526         } else if let Some(span) = arg_data.span {
527             // `span` here lets us point at `sum` instead of the entire right hand side expr:
528             // error[E0282]: type annotations needed
529             //  --> file2.rs:3:15
530             //   |
531             // 3 |     let _ = x.sum() as f64;
532             //   |               ^^^ cannot infer type for `S`
533             span
534         } else if let Some(ExprKind::MethodCall(segment, ..)) =
535             local_visitor.found_method_call.map(|e| &e.kind)
536         {
537             // Point at the call instead of the whole expression:
538             // error[E0284]: type annotations needed
539             //  --> file.rs:2:5
540             //   |
541             // 2 |     [Ok(2)].into_iter().collect()?;
542             //   |                         ^^^^^^^ cannot infer type
543             //   |
544             //   = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
545             if span.contains(segment.ident.span) { segment.ident.span } else { span }
546         } else {
547             span
548         };
549
550         let is_named_and_not_impl_trait =
551             |ty: Ty<'_>| &ty.to_string() != "_" && !ty.is_impl_trait();
552
553         let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) {
554             (_, Some(_)) => String::new(),
555             (Some(ty), _) if ty.is_closure() => {
556                 let ty::Closure(_, substs) = *ty.kind() else { unreachable!() };
557                 let fn_sig = substs.as_closure().sig();
558                 let args = closure_args(&fn_sig);
559                 let ret = fn_sig.output().skip_binder().to_string();
560                 format!(" for the closure `fn({}) -> {}`", args, ret)
561             }
562             (Some(ty), _) if is_named_and_not_impl_trait(ty) => {
563                 let ty = ty_to_string(ty);
564                 format!(" for `{}`", ty)
565             }
566             _ => String::new(),
567         };
568
569         // When `arg_data.name` corresponds to a type argument, show the path of the full type we're
570         // trying to infer. In the following example, `ty_msg` contains
571         // " for `std::result::Result<i32, E>`":
572         // ```
573         // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
574         //  --> file.rs:L:CC
575         //   |
576         // L |     let b = Ok(4);
577         //   |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
578         //   |         |
579         //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
580         //   |         the type parameter `E` is specified
581         // ```
582         let error_code = error_code.into();
583         let mut err = self.tcx.sess.struct_span_err_with_code(
584             err_span,
585             &format!("type annotations needed{}", ty_msg),
586             error_code,
587         );
588
589         let use_diag = local_visitor.found_use_diagnostic.as_ref();
590         if let Some(use_diag) = use_diag {
591             if use_diag.applies_to(err_span) {
592                 use_diag.attach_note(&mut err);
593             }
594         }
595
596         let param_type = arg_data.kind.descr();
597         let suffix = match local_visitor.found_node_ty {
598             Some(ty) if ty.is_closure() => {
599                 let ty::Closure(_, substs) = *ty.kind() else { unreachable!() };
600                 let fn_sig = substs.as_closure().sig();
601                 let ret = fn_sig.output().skip_binder().to_string();
602
603                 let closure_decl_and_body_id =
604                     local_visitor.found_closure.and_then(|closure| match &closure.kind {
605                         ExprKind::Closure(_, decl, body_id, ..) => Some((decl, *body_id)),
606                         _ => None,
607                     });
608
609                 if let Some((decl, body_id)) = closure_decl_and_body_id {
610                     closure_return_type_suggestion(
611                         &mut err,
612                         &decl.output,
613                         self.tcx.hir().body(body_id),
614                         &ret,
615                     );
616                     // We don't want to give the other suggestions when the problem is the
617                     // closure return type.
618                     err.span_label(
619                         span,
620                         arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))),
621                     );
622                     return err;
623                 }
624
625                 // This shouldn't be reachable, but just in case we leave a reasonable fallback.
626                 let args = closure_args(&fn_sig);
627                 // This suggestion is incomplete, as the user will get further type inference
628                 // errors due to the `_` placeholders and the introduction of `Box`, but it does
629                 // nudge them in the right direction.
630                 format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
631             }
632             Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
633                 let ty = ty_to_string(ty);
634                 format!("the explicit type `{}`, with the {} parameters specified", ty, param_type)
635             }
636             Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => {
637                 let ty = ResolvedTypeParamEraser::new(self.tcx).fold_ty(ty);
638                 let ty = ErrTypeParamEraser(self.tcx).fold_ty(ty);
639                 let ty = ty_to_string(ty);
640                 format!(
641                     "the explicit type `{}`, where the {} parameter `{}` is specified",
642                     ty, param_type, arg_data.name,
643                 )
644             }
645             _ => "a type".to_string(),
646         };
647
648         if let Some(e) = local_visitor.found_exact_method_call {
649             if let ExprKind::MethodCall(segment, ..) = &e.kind {
650                 // Suggest specifying type params or point out the return type of the call:
651                 //
652                 // error[E0282]: type annotations needed
653                 //   --> $DIR/type-annotations-needed-expr.rs:2:39
654                 //    |
655                 // LL |     let _ = x.into_iter().sum() as f64;
656                 //    |                           ^^^
657                 //    |                           |
658                 //    |                           cannot infer type for `S`
659                 //    |                           help: consider specifying the type argument in
660                 //    |                           the method call: `sum::<S>`
661                 //    |
662                 //    = note: type must be known at this point
663                 //
664                 // or
665                 //
666                 // error[E0282]: type annotations needed
667                 //   --> $DIR/issue-65611.rs:59:20
668                 //    |
669                 // LL |     let x = buffer.last().unwrap().0.clone();
670                 //    |             -------^^^^--
671                 //    |             |      |
672                 //    |             |      cannot infer type for `T`
673                 //    |             this method call resolves to `std::option::Option<&T>`
674                 //    |
675                 //    = note: type must be known at this point
676                 self.annotate_method_call(segment, e, &mut err);
677             }
678         } else if let Some(pattern) = local_visitor.found_arg_pattern {
679             // We don't want to show the default label for closures.
680             //
681             // So, before clearing, the output would look something like this:
682             // ```
683             // let x = |_| {  };
684             //          -  ^^^^ cannot infer type for `[_; 0]`
685             //          |
686             //          consider giving this closure parameter a type
687             // ```
688             //
689             // After clearing, it looks something like this:
690             // ```
691             // let x = |_| {  };
692             //          ^ consider giving this closure parameter the type `[_; 0]`
693             //            with the type parameter `_` specified
694             // ```
695             err.span_label(
696                 pattern.span,
697                 format!("consider giving this closure parameter {}", suffix),
698             );
699         } else if let Some(pattern) = local_visitor.found_local_pattern {
700             let msg = if let Some(simple_ident) = pattern.simple_ident() {
701                 match pattern.span.desugaring_kind() {
702                     None => format!("consider giving `{}` {}", simple_ident, suffix),
703                     Some(_) => format!("this needs {}", suffix),
704                 }
705             } else {
706                 format!("consider giving this pattern {}", suffix)
707             };
708             err.span_label(pattern.span, msg);
709         } else if let Some(e) = local_visitor.found_method_call {
710             if let ExprKind::MethodCall(segment, exprs, _) = &e.kind {
711                 // Suggest impl candidates:
712                 //
713                 // error[E0283]: type annotations needed
714                 //   --> $DIR/E0283.rs:35:24
715                 //    |
716                 // LL |     let bar = foo_impl.into() * 1u32;
717                 //    |               ---------^^^^--
718                 //    |               |        |
719                 //    |               |        cannot infer type for type parameter `T` declared on the trait `Into`
720                 //    |               this method call resolves to `T`
721                 //    |               help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
722                 //    |
723                 //    = note: cannot satisfy `Impl: Into<_>`
724                 if !impl_candidates.is_empty() && e.span.contains(span) {
725                     if let Some(expr) = exprs.first() {
726                         if let ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind {
727                             if let [path_segment] = path.segments {
728                                 let candidate_len = impl_candidates.len();
729                                 let suggestions = impl_candidates.iter().map(|candidate| {
730                                     format!(
731                                         "{}::{}({})",
732                                         candidate, segment.ident, path_segment.ident
733                                     )
734                                 });
735                                 err.span_suggestions(
736                                     e.span,
737                                     &format!(
738                                         "use the fully qualified path for the potential candidate{}",
739                                         pluralize!(candidate_len),
740                                     ),
741                                     suggestions,
742                                     Applicability::MaybeIncorrect,
743                                 );
744                             }
745                         }
746                     };
747                 }
748                 // Suggest specifying type params or point out the return type of the call:
749                 //
750                 // error[E0282]: type annotations needed
751                 //   --> $DIR/type-annotations-needed-expr.rs:2:39
752                 //    |
753                 // LL |     let _ = x.into_iter().sum() as f64;
754                 //    |                           ^^^
755                 //    |                           |
756                 //    |                           cannot infer type for `S`
757                 //    |                           help: consider specifying the type argument in
758                 //    |                           the method call: `sum::<S>`
759                 //    |
760                 //    = note: type must be known at this point
761                 //
762                 // or
763                 //
764                 // error[E0282]: type annotations needed
765                 //   --> $DIR/issue-65611.rs:59:20
766                 //    |
767                 // LL |     let x = buffer.last().unwrap().0.clone();
768                 //    |             -------^^^^--
769                 //    |             |      |
770                 //    |             |      cannot infer type for `T`
771                 //    |             this method call resolves to `std::option::Option<&T>`
772                 //    |
773                 //    = note: type must be known at this point
774                 self.annotate_method_call(segment, e, &mut err);
775             }
776         } else if let Some(scrutinee) = local_visitor.found_for_loop_iter {
777             err.span_label(
778                 scrutinee.span,
779                 "the element type for this iterator is not specified".to_string(),
780             );
781         }
782         // Instead of the following:
783         // error[E0282]: type annotations needed
784         //  --> file2.rs:3:15
785         //   |
786         // 3 |     let _ = x.sum() as f64;
787         //   |             --^^^--------- cannot infer type for `S`
788         //   |
789         //   = note: type must be known at this point
790         // We want:
791         // error[E0282]: type annotations needed
792         //  --> file2.rs:3:15
793         //   |
794         // 3 |     let _ = x.sum() as f64;
795         //   |               ^^^ cannot infer type for `S`
796         //   |
797         //   = note: type must be known at this point
798         let span = arg_data.span.unwrap_or(err_span);
799
800         // Avoid multiple labels pointing at `span`.
801         if !err
802             .span
803             .span_labels()
804             .iter()
805             .any(|span_label| span_label.label.is_some() && span_label.span == span)
806             && local_visitor.found_arg_pattern.is_none()
807         {
808             // FIXME(const_generics): we would like to handle const arguments
809             // as part of the normal diagnostics flow below, but there appear to
810             // be subtleties in doing so, so for now we special-case const args
811             // here.
812             if let (UnderspecifiedArgKind::Const { .. }, Some(parent_data)) =
813                 (&arg_data.kind, &arg_data.parent)
814             {
815                 // (#83606): Do not emit a suggestion if the parent has an `impl Trait`
816                 // as an argument otherwise it will cause the E0282 error.
817                 if !self.tcx.generics_of(parent_data.def_id).has_impl_trait()
818                     || self.tcx.features().explicit_generic_args_with_impl_trait
819                 {
820                     err.span_suggestion_verbose(
821                         span,
822                         "consider specifying the const argument",
823                         format!("{}::<{}>", parent_data.name, arg_data.name),
824                         Applicability::MaybeIncorrect,
825                     );
826                 }
827             }
828
829             err.span_label(
830                 span,
831                 arg_data.cannot_infer_msg(use_diag.filter(|d| d.applies_to(span))),
832             );
833         }
834
835         err
836     }
837
838     fn trait_def_from_hir_fn(&self, hir_id: hir::HirId) -> Option<DefId> {
839         // The DefId will be the method's trait item ID unless this is an inherent impl
840         if let Some((DefKind::AssocFn, def_id)) =
841             self.in_progress_typeck_results?.borrow().type_dependent_def(hir_id)
842         {
843             return self
844                 .tcx
845                 .parent(def_id)
846                 .filter(|&parent_def_id| self.tcx.is_trait(parent_def_id));
847         }
848
849         None
850     }
851
852     /// If the `FnSig` for the method call can be found and type arguments are identified as
853     /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
854     fn annotate_method_call(
855         &self,
856         segment: &hir::PathSegment<'_>,
857         e: &Expr<'_>,
858         err: &mut DiagnosticBuilder<'_>,
859     ) {
860         if let (Some(typeck_results), None) = (self.in_progress_typeck_results, &segment.args) {
861             let borrow = typeck_results.borrow();
862             if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) {
863                 let generics = self.tcx.generics_of(did);
864                 if !generics.params.is_empty() && !generics.has_impl_trait() {
865                     err.span_suggestion_verbose(
866                         segment.ident.span.shrink_to_hi(),
867                         &format!(
868                             "consider specifying the type argument{} in the method call",
869                             pluralize!(generics.params.len()),
870                         ),
871                         format!(
872                             "::<{}>",
873                             generics
874                                 .params
875                                 .iter()
876                                 .map(|p| p.name.to_string())
877                                 .collect::<Vec<String>>()
878                                 .join(", ")
879                         ),
880                         Applicability::HasPlaceholders,
881                     );
882                 } else {
883                     let sig = self.tcx.fn_sig(did);
884                     let bound_output = sig.output();
885                     let output = bound_output.skip_binder();
886                     err.span_label(e.span, &format!("this method call resolves to `{}`", output));
887                     let kind = output.kind();
888                     if let ty::Projection(proj) = kind {
889                         if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) {
890                             err.span_label(span, &format!("`{}` defined here", output));
891                         }
892                     }
893                 }
894             }
895         }
896     }
897
898     pub fn need_type_info_err_in_generator(
899         &self,
900         kind: hir::GeneratorKind,
901         span: Span,
902         ty: Ty<'tcx>,
903     ) -> DiagnosticBuilder<'tcx> {
904         let ty = self.resolve_vars_if_possible(ty);
905         let data = self.extract_inference_diagnostics_data(ty.into(), None);
906
907         let mut err = struct_span_err!(
908             self.tcx.sess,
909             span,
910             E0698,
911             "type inside {} must be known in this context",
912             kind,
913         );
914         err.span_label(span, data.cannot_infer_msg(None));
915         err
916     }
917 }
918
919 /// Turn *resolved* type params into `[type error]` to signal we don't want to display them. After
920 /// performing that replacement, we'll turn all remaining infer type params to use their name from
921 /// their definition, and replace all the `[type error]`s back to being infer so they display in
922 /// the output as `_`. If we didn't go through `[type error]`, we would either show all type params
923 /// by their name *or* `_`, neither of which is desireable: we want to show all types that we could
924 /// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations.
925 struct ResolvedTypeParamEraser<'tcx> {
926     tcx: TyCtxt<'tcx>,
927     level: usize,
928 }
929
930 impl<'tcx> ResolvedTypeParamEraser<'tcx> {
931     fn new(tcx: TyCtxt<'tcx>) -> Self {
932         ResolvedTypeParamEraser { tcx, level: 0 }
933     }
934
935     /// Replace not yet inferred const params with their def name.
936     fn replace_infers(&self, c: Const<'tcx>, index: u32, name: Symbol) -> Const<'tcx> {
937         match c.val() {
938             ty::ConstKind::Infer(..) => self.tcx().mk_const_param(index, name, c.ty()),
939             _ => c,
940         }
941     }
942 }
943
944 impl<'tcx> TypeFolder<'tcx> for ResolvedTypeParamEraser<'tcx> {
945     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
946         self.tcx
947     }
948     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
949         self.level += 1;
950         let t = match t.kind() {
951             // We'll hide this type only if all its type params are hidden as well.
952             ty::Adt(def, substs) => {
953                 let generics = self.tcx().generics_of(def.did);
954                 // Account for params with default values, like `Vec`, where we
955                 // want to show `Vec<T>`, not `Vec<T, _>`. If we replaced that
956                 // subst, then we'd get the incorrect output, so we passthrough.
957                 let substs: Vec<_> = substs
958                     .iter()
959                     .zip(generics.params.iter())
960                     .map(|(subst, param)| match &(subst.unpack(), &param.kind) {
961                         (_, ty::GenericParamDefKind::Type { has_default: true, .. }) => subst,
962                         (crate::infer::GenericArgKind::Const(c), _) => {
963                             self.replace_infers(*c, param.index, param.name).into()
964                         }
965                         _ => subst.super_fold_with(self),
966                     })
967                     .collect();
968                 let should_keep = |subst: &GenericArg<'_>| match subst.unpack() {
969                     ty::subst::GenericArgKind::Type(t) => match t.kind() {
970                         ty::Error(_) => false,
971                         _ => true,
972                     },
973                     // Account for `const` params here, otherwise `doesnt_infer.rs`
974                     // shows `_` instead of `Foo<{ _: u32 }>`
975                     ty::subst::GenericArgKind::Const(_) => true,
976                     _ => false,
977                 };
978                 if self.level == 1 || substs.iter().any(should_keep) {
979                     let substs = self.tcx().intern_substs(&substs[..]);
980                     self.tcx().mk_ty(ty::Adt(def, substs))
981                 } else {
982                     self.tcx().ty_error()
983                 }
984             }
985             ty::Ref(_, ty, _) => {
986                 let ty = self.fold_ty(*ty);
987                 match ty.kind() {
988                     // Avoid `&_`, these can be safely presented as `_`.
989                     ty::Error(_) => self.tcx().ty_error(),
990                     _ => t.super_fold_with(self),
991                 }
992             }
993             // We could account for `()` if we wanted to replace it, but it's assured to be short.
994             ty::Tuple(_)
995             | ty::Slice(_)
996             | ty::RawPtr(_)
997             | ty::FnDef(..)
998             | ty::FnPtr(_)
999             | ty::Opaque(..)
1000             | ty::Projection(_)
1001             | ty::Never => t.super_fold_with(self),
1002             ty::Array(ty, c) => {
1003                 self.tcx().mk_ty(ty::Array(self.fold_ty(*ty), self.replace_infers(*c, 0, sym::N)))
1004             }
1005             // We don't want to hide type params that haven't been resolved yet.
1006             // This would be the type that will be written out with the type param
1007             // name in the output.
1008             ty::Infer(_) => t,
1009             // We don't want to hide the outermost type, only its type params.
1010             _ if self.level == 1 => t.super_fold_with(self),
1011             // Hide this type
1012             _ => self.tcx().ty_error(),
1013         };
1014         self.level -= 1;
1015         t
1016     }
1017 }
1018
1019 /// Replace `[type error]` with `ty::Infer(ty::Var)` to display `_`.
1020 struct ErrTypeParamEraser<'tcx>(TyCtxt<'tcx>);
1021 impl<'tcx> TypeFolder<'tcx> for ErrTypeParamEraser<'tcx> {
1022     fn tcx<'a>(&'a self) -> TyCtxt<'tcx> {
1023         self.0
1024     }
1025     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
1026         match t.kind() {
1027             ty::Error(_) => self.tcx().mk_ty_var(ty::TyVid::from_u32(0)),
1028             _ => t.super_fold_with(self),
1029         }
1030     }
1031 }