]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
unused into
[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;
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::intravisit::{self, NestedVisitorMap, Visitor};
7 use rustc_hir::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat};
8 use rustc_middle::hir::map::Map;
9 use rustc_middle::infer::unify_key::ConstVariableOriginKind;
10 use rustc_middle::ty::print::Print;
11 use rustc_middle::ty::subst::{GenericArg, GenericArgKind};
12 use rustc_middle::ty::{self, DefIdTree, InferConst, Ty};
13 use rustc_span::source_map::DesugaringKind;
14 use rustc_span::symbol::kw;
15 use rustc_span::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 }
29
30 impl<'a, 'tcx> FindHirNodeVisitor<'a, 'tcx> {
31     fn new(infcx: &'a InferCtxt<'a, 'tcx>, target: GenericArg<'tcx>, target_span: Span) -> Self {
32         Self {
33             infcx,
34             target,
35             target_span,
36             found_node_ty: None,
37             found_local_pattern: None,
38             found_arg_pattern: None,
39             found_closure: None,
40             found_method_call: None,
41             found_exact_method_call: None,
42         }
43     }
44
45     fn node_ty_contains_target(&mut self, hir_id: HirId) -> Option<Ty<'tcx>> {
46         let ty_opt = self
47             .infcx
48             .in_progress_typeck_results
49             .and_then(|typeck_results| typeck_results.borrow().node_type_opt(hir_id));
50         match ty_opt {
51             Some(ty) => {
52                 let ty = self.infcx.resolve_vars_if_possible(&ty);
53                 if ty.walk().any(|inner| {
54                     inner == self.target
55                         || match (inner.unpack(), self.target.unpack()) {
56                             (GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
57                                 match (inner_ty.kind(), target_ty.kind()) {
58                                     (
59                                         &ty::Infer(ty::TyVar(a_vid)),
60                                         &ty::Infer(ty::TyVar(b_vid)),
61                                     ) => 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                     Some(ty)
74                 } else {
75                     None
76                 }
77             }
78             None => None,
79         }
80     }
81 }
82
83 impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
84     type Map = Map<'tcx>;
85
86     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
87         NestedVisitorMap::OnlyBodies(self.infcx.tcx.hir())
88     }
89
90     fn visit_local(&mut self, local: &'tcx Local<'tcx>) {
91         if let (None, Some(ty)) =
92             (self.found_local_pattern, self.node_ty_contains_target(local.hir_id))
93         {
94             // FIXME: There's a trade-off here - we can either check that our target span
95             // is contained in `local.span` or not. If we choose to check containment
96             // we can avoid some spurious suggestions (see #72690), but we lose
97             // the ability to report on things like:
98             //
99             // ```
100             // let x = vec![];
101             // ```
102             //
103             // because the target span will be in the macro expansion of `vec![]`.
104             // At present we choose not to check containment.
105             self.found_local_pattern = Some(&*local.pat);
106             self.found_node_ty = Some(ty);
107         }
108         intravisit::walk_local(self, local);
109     }
110
111     fn visit_body(&mut self, body: &'tcx Body<'tcx>) {
112         for param in body.params {
113             if let (None, Some(ty)) =
114                 (self.found_arg_pattern, self.node_ty_contains_target(param.hir_id))
115             {
116                 if self.target_span.contains(param.pat.span) {
117                     self.found_arg_pattern = Some(&*param.pat);
118                     self.found_node_ty = Some(ty);
119                 }
120             }
121         }
122         intravisit::walk_body(self, body);
123     }
124
125     fn visit_expr(&mut self, expr: &'tcx Expr<'tcx>) {
126         if let ExprKind::MethodCall(_, call_span, exprs, _) = expr.kind {
127             if call_span == self.target_span
128                 && Some(self.target)
129                     == self.infcx.in_progress_typeck_results.and_then(|typeck_results| {
130                         typeck_results
131                             .borrow()
132                             .node_type_opt(exprs.first().unwrap().hir_id)
133                             .map(Into::into)
134                     })
135             {
136                 self.found_exact_method_call = Some(&expr);
137                 return;
138             }
139         }
140         if self.node_ty_contains_target(expr.hir_id).is_some() {
141             match expr.kind {
142                 ExprKind::Closure(..) => self.found_closure = Some(&expr),
143                 ExprKind::MethodCall(..) => self.found_method_call = Some(&expr),
144                 _ => {}
145             }
146         }
147         intravisit::walk_expr(self, expr);
148     }
149 }
150
151 /// Suggest giving an appropriate return type to a closure expression.
152 fn closure_return_type_suggestion(
153     span: Span,
154     err: &mut DiagnosticBuilder<'_>,
155     output: &FnRetTy<'_>,
156     body: &Body<'_>,
157     descr: &str,
158     name: &str,
159     ret: &str,
160     parent_name: Option<String>,
161     parent_descr: Option<&str>,
162 ) {
163     let (arrow, post) = match output {
164         FnRetTy::DefaultReturn(_) => ("-> ", " "),
165         _ => ("", ""),
166     };
167     let suggestion = match body.value.kind {
168         ExprKind::Block(..) => vec![(output.span(), format!("{}{}{}", arrow, ret, post))],
169         _ => vec![
170             (output.span(), format!("{}{}{}{{ ", arrow, ret, post)),
171             (body.value.span.shrink_to_hi(), " }".to_string()),
172         ],
173     };
174     err.multipart_suggestion(
175         "give this closure an explicit return type without `_` placeholders",
176         suggestion,
177         Applicability::HasPlaceholders,
178     );
179     err.span_label(
180         span,
181         InferCtxt::cannot_infer_msg("type", &name, &descr, parent_name, parent_descr),
182     );
183 }
184
185 /// Given a closure signature, return a `String` containing a list of all its argument types.
186 fn closure_args(fn_sig: &ty::PolyFnSig<'_>) -> String {
187     fn_sig
188         .inputs()
189         .skip_binder()
190         .iter()
191         .next()
192         .map(|args| args.tuple_fields().map(|arg| arg.to_string()).collect::<Vec<_>>().join(", "))
193         .unwrap_or_default()
194 }
195
196 pub enum TypeAnnotationNeeded {
197     /// ```compile_fail,E0282
198     /// let x = "hello".chars().rev().collect();
199     /// ```
200     E0282,
201     /// An implementation cannot be chosen unambiguously because of lack of information.
202     /// ```compile_fail,E0283
203     /// let _ = Default::default();
204     /// ```
205     E0283,
206     /// ```compile_fail,E0284
207     /// let mut d: u64 = 2;
208     /// d = d % 1u32.into();
209     /// ```
210     E0284,
211 }
212
213 impl Into<rustc_errors::DiagnosticId> for TypeAnnotationNeeded {
214     fn into(self) -> rustc_errors::DiagnosticId {
215         match self {
216             Self::E0282 => rustc_errors::error_code!(E0282),
217             Self::E0283 => rustc_errors::error_code!(E0283),
218             Self::E0284 => rustc_errors::error_code!(E0284),
219         }
220     }
221 }
222
223 /// Information about a constant or a type containing inference variables.
224 pub struct InferenceDiagnosticsData {
225     pub name: String,
226     pub span: Option<Span>,
227     pub description: Cow<'static, str>,
228     pub parent_name: Option<String>,
229     pub parent_description: Option<&'static str>,
230 }
231
232 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
233     /// Extracts data used by diagnostic for either types or constants
234     /// which were stuck during inference.
235     pub fn extract_inference_diagnostics_data(
236         &self,
237         arg: GenericArg<'tcx>,
238         highlight: Option<ty::print::RegionHighlightMode>,
239     ) -> InferenceDiagnosticsData {
240         match arg.unpack() {
241             GenericArgKind::Type(ty) => {
242                 if let ty::Infer(ty::TyVar(ty_vid)) = *ty.kind() {
243                     let mut inner = self.inner.borrow_mut();
244                     let ty_vars = &inner.type_variables();
245                     let var_origin = ty_vars.var_origin(ty_vid);
246                     if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) =
247                         var_origin.kind
248                     {
249                         let parent_def_id = def_id.and_then(|def_id| self.tcx.parent(def_id));
250                         let (parent_name, parent_description) =
251                             if let Some(parent_def_id) = parent_def_id {
252                                 let parent_name = self
253                                     .tcx
254                                     .def_key(parent_def_id)
255                                     .disambiguated_data
256                                     .data
257                                     .get_opt_name()
258                                     .map(|parent_symbol| parent_symbol.to_string());
259
260                                 (
261                                     parent_name,
262                                     Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
263                                 )
264                             } else {
265                                 (None, None)
266                             };
267
268                         if name != kw::SelfUpper {
269                             return InferenceDiagnosticsData {
270                                 name: name.to_string(),
271                                 span: Some(var_origin.span),
272                                 description: "type parameter".into(),
273                                 parent_name,
274                                 parent_description,
275                             };
276                         }
277                     }
278                 }
279
280                 let mut s = String::new();
281                 let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
282                 if let Some(highlight) = highlight {
283                     printer.region_highlight_mode = highlight;
284                 }
285                 let _ = ty.print(printer);
286                 InferenceDiagnosticsData {
287                     name: s,
288                     span: None,
289                     description: ty.prefix_string(),
290                     parent_name: None,
291                     parent_description: None,
292                 }
293             }
294             GenericArgKind::Const(ct) => {
295                 if let ty::ConstKind::Infer(InferConst::Var(vid)) = ct.val {
296                     let origin =
297                         self.inner.borrow_mut().const_unification_table().probe_value(vid).origin;
298                     if let ConstVariableOriginKind::ConstParameterDefinition(name, def_id) =
299                         origin.kind
300                     {
301                         let parent_def_id = self.tcx.parent(def_id);
302                         let (parent_name, parent_description) =
303                             if let Some(parent_def_id) = parent_def_id {
304                                 let parent_name = self
305                                     .tcx
306                                     .def_key(parent_def_id)
307                                     .disambiguated_data
308                                     .data
309                                     .get_opt_name()
310                                     .map(|parent_symbol| parent_symbol.to_string());
311
312                                 (
313                                     parent_name,
314                                     Some(self.tcx.def_kind(parent_def_id).descr(parent_def_id)),
315                                 )
316                             } else {
317                                 (None, None)
318                             };
319
320                         return InferenceDiagnosticsData {
321                             name: name.to_string(),
322                             span: Some(origin.span),
323                             description: "const parameter".into(),
324                             parent_name,
325                             parent_description,
326                         };
327                     }
328
329                     debug_assert!(!origin.span.is_dummy());
330                     let mut s = String::new();
331                     let mut printer =
332                         ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::ValueNS);
333                     if let Some(highlight) = highlight {
334                         printer.region_highlight_mode = highlight;
335                     }
336                     let _ = ct.print(printer);
337                     InferenceDiagnosticsData {
338                         name: s,
339                         span: Some(origin.span),
340                         description: "the constant".into(),
341                         parent_name: None,
342                         parent_description: None,
343                     }
344                 } else {
345                     bug!("unexpect const: {:?}", ct);
346                 }
347             }
348             GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
349         }
350     }
351
352     pub fn emit_inference_failure_err(
353         &self,
354         body_id: Option<hir::BodyId>,
355         span: Span,
356         arg: GenericArg<'tcx>,
357         error_code: TypeAnnotationNeeded,
358     ) -> DiagnosticBuilder<'tcx> {
359         let arg = self.resolve_vars_if_possible(&arg);
360         let arg_data = self.extract_inference_diagnostics_data(arg, None);
361         let kind_str = match arg.unpack() {
362             GenericArgKind::Type(_) => "type",
363             GenericArgKind::Const(_) => "the value",
364             GenericArgKind::Lifetime(_) => bug!("unexpected lifetime"),
365         };
366
367         let mut local_visitor = FindHirNodeVisitor::new(&self, arg, span);
368         let ty_to_string = |ty: Ty<'tcx>| -> String {
369             let mut s = String::new();
370             let mut printer = ty::print::FmtPrinter::new(self.tcx, &mut s, Namespace::TypeNS);
371             let mut inner = self.inner.borrow_mut();
372             let ty_vars = inner.type_variables();
373             let getter = move |ty_vid| {
374                 let var_origin = ty_vars.var_origin(ty_vid);
375                 if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind {
376                     return Some(name.to_string());
377                 }
378                 None
379             };
380             printer.name_resolver = Some(Box::new(&getter));
381             let _ = if let ty::FnDef(..) = ty.kind() {
382                 // We don't want the regular output for `fn`s because it includes its path in
383                 // invalid pseudo-syntax, we want the `fn`-pointer output instead.
384                 ty.fn_sig(self.tcx).print(printer)
385             } else {
386                 ty.print(printer)
387             };
388             s
389         };
390
391         if let Some(body_id) = body_id {
392             let expr = self.tcx.hir().expect_expr(body_id.hir_id);
393             local_visitor.visit_expr(expr);
394         }
395         let err_span = if let Some(pattern) = local_visitor.found_arg_pattern {
396             pattern.span
397         } else if let Some(span) = arg_data.span {
398             // `span` here lets us point at `sum` instead of the entire right hand side expr:
399             // error[E0282]: type annotations needed
400             //  --> file2.rs:3:15
401             //   |
402             // 3 |     let _ = x.sum() as f64;
403             //   |               ^^^ cannot infer type for `S`
404             span
405         } else if let Some(ExprKind::MethodCall(_, call_span, _, _)) =
406             local_visitor.found_method_call.map(|e| &e.kind)
407         {
408             // Point at the call instead of the whole expression:
409             // error[E0284]: type annotations needed
410             //  --> file.rs:2:5
411             //   |
412             // 2 |     vec![Ok(2)].into_iter().collect()?;
413             //   |                             ^^^^^^^ cannot infer type
414             //   |
415             //   = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
416             if span.contains(*call_span) { *call_span } else { span }
417         } else {
418             span
419         };
420
421         let is_named_and_not_impl_trait = |ty: Ty<'_>| {
422             &ty.to_string() != "_" &&
423                 // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527
424                 (!ty.is_impl_trait() || self.tcx.features().impl_trait_in_bindings)
425         };
426
427         let ty_msg = match (local_visitor.found_node_ty, local_visitor.found_exact_method_call) {
428             (_, Some(_)) => String::new(),
429             (Some(ty), _) if ty.is_closure() => {
430                 let substs =
431                     if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() };
432                 let fn_sig = substs.as_closure().sig();
433                 let args = closure_args(&fn_sig);
434                 let ret = fn_sig.output().skip_binder().to_string();
435                 format!(" for the closure `fn({}) -> {}`", args, ret)
436             }
437             (Some(ty), _) if is_named_and_not_impl_trait(ty) => {
438                 let ty = ty_to_string(ty);
439                 format!(" for `{}`", ty)
440             }
441             _ => String::new(),
442         };
443
444         // When `arg_data.name` corresponds to a type argument, show the path of the full type we're
445         // trying to infer. In the following example, `ty_msg` contains
446         // " in `std::result::Result<i32, E>`":
447         // ```
448         // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
449         //  --> file.rs:L:CC
450         //   |
451         // L |     let b = Ok(4);
452         //   |         -   ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
453         //   |         |
454         //   |         consider giving `b` the explicit type `std::result::Result<i32, E>`, where
455         //   |         the type parameter `E` is specified
456         // ```
457         let error_code = error_code.into();
458         let mut err = self.tcx.sess.struct_span_err_with_code(
459             err_span,
460             &format!("type annotations needed{}", ty_msg),
461             error_code,
462         );
463
464         let suffix = match local_visitor.found_node_ty {
465             Some(ty) if ty.is_closure() => {
466                 let substs =
467                     if let ty::Closure(_, substs) = *ty.kind() { substs } else { unreachable!() };
468                 let fn_sig = substs.as_closure().sig();
469                 let ret = fn_sig.output().skip_binder().to_string();
470
471                 let closure_decl_and_body_id =
472                     local_visitor.found_closure.and_then(|closure| match &closure.kind {
473                         ExprKind::Closure(_, decl, body_id, ..) => Some((decl, *body_id)),
474                         _ => None,
475                     });
476
477                 if let Some((decl, body_id)) = closure_decl_and_body_id {
478                     closure_return_type_suggestion(
479                         span,
480                         &mut err,
481                         &decl.output,
482                         self.tcx.hir().body(body_id),
483                         &arg_data.description,
484                         &arg_data.name,
485                         &ret,
486                         arg_data.parent_name,
487                         arg_data.parent_description,
488                     );
489                     // We don't want to give the other suggestions when the problem is the
490                     // closure return type.
491                     return err;
492                 }
493
494                 // This shouldn't be reachable, but just in case we leave a reasonable fallback.
495                 let args = closure_args(&fn_sig);
496                 // This suggestion is incomplete, as the user will get further type inference
497                 // errors due to the `_` placeholders and the introduction of `Box`, but it does
498                 // nudge them in the right direction.
499                 format!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args, ret)
500             }
501             Some(ty) if is_named_and_not_impl_trait(ty) && arg_data.name == "_" => {
502                 let ty = ty_to_string(ty);
503                 format!("the explicit type `{}`, with the type parameters specified", ty)
504             }
505             Some(ty) if is_named_and_not_impl_trait(ty) && ty.to_string() != arg_data.name => {
506                 let ty = ty_to_string(ty);
507                 format!(
508                     "the explicit type `{}`, where the type parameter `{}` is specified",
509                     ty, arg_data.name,
510                 )
511             }
512             _ => "a type".to_string(),
513         };
514
515         if let Some(e) = local_visitor.found_exact_method_call {
516             if let ExprKind::MethodCall(segment, ..) = &e.kind {
517                 // Suggest specifying type params or point out the return type of the call:
518                 //
519                 // error[E0282]: type annotations needed
520                 //   --> $DIR/type-annotations-needed-expr.rs:2:39
521                 //    |
522                 // LL |     let _ = x.into_iter().sum() as f64;
523                 //    |                           ^^^
524                 //    |                           |
525                 //    |                           cannot infer type for `S`
526                 //    |                           help: consider specifying the type argument in
527                 //    |                           the method call: `sum::<S>`
528                 //    |
529                 //    = note: type must be known at this point
530                 //
531                 // or
532                 //
533                 // error[E0282]: type annotations needed
534                 //   --> $DIR/issue-65611.rs:59:20
535                 //    |
536                 // LL |     let x = buffer.last().unwrap().0.clone();
537                 //    |             -------^^^^--
538                 //    |             |      |
539                 //    |             |      cannot infer type for `T`
540                 //    |             this method call resolves to `std::option::Option<&T>`
541                 //    |
542                 //    = note: type must be known at this point
543                 self.annotate_method_call(segment, e, &mut err);
544             }
545         } else if let Some(pattern) = local_visitor.found_arg_pattern {
546             // We don't want to show the default label for closures.
547             //
548             // So, before clearing, the output would look something like this:
549             // ```
550             // let x = |_| {  };
551             //          -  ^^^^ cannot infer type for `[_; 0]`
552             //          |
553             //          consider giving this closure parameter a type
554             // ```
555             //
556             // After clearing, it looks something like this:
557             // ```
558             // let x = |_| {  };
559             //          ^ consider giving this closure parameter the type `[_; 0]`
560             //            with the type parameter `_` specified
561             // ```
562             err.span_label(
563                 pattern.span,
564                 format!("consider giving this closure parameter {}", suffix),
565             );
566         } else if let Some(pattern) = local_visitor.found_local_pattern {
567             let msg = if let Some(simple_ident) = pattern.simple_ident() {
568                 match pattern.span.desugaring_kind() {
569                     None => format!("consider giving `{}` {}", simple_ident, suffix),
570                     Some(DesugaringKind::ForLoop(_)) => {
571                         "the element type for this iterator is not specified".to_string()
572                     }
573                     _ => format!("this needs {}", suffix),
574                 }
575             } else {
576                 format!("consider giving this pattern {}", suffix)
577             };
578             err.span_label(pattern.span, msg);
579         } else if let Some(e) = local_visitor.found_method_call {
580             if let ExprKind::MethodCall(segment, ..) = &e.kind {
581                 // Suggest specifying type params or point out the return type of the call:
582                 //
583                 // error[E0282]: type annotations needed
584                 //   --> $DIR/type-annotations-needed-expr.rs:2:39
585                 //    |
586                 // LL |     let _ = x.into_iter().sum() as f64;
587                 //    |                           ^^^
588                 //    |                           |
589                 //    |                           cannot infer type for `S`
590                 //    |                           help: consider specifying the type argument in
591                 //    |                           the method call: `sum::<S>`
592                 //    |
593                 //    = note: type must be known at this point
594                 //
595                 // or
596                 //
597                 // error[E0282]: type annotations needed
598                 //   --> $DIR/issue-65611.rs:59:20
599                 //    |
600                 // LL |     let x = buffer.last().unwrap().0.clone();
601                 //    |             -------^^^^--
602                 //    |             |      |
603                 //    |             |      cannot infer type for `T`
604                 //    |             this method call resolves to `std::option::Option<&T>`
605                 //    |
606                 //    = note: type must be known at this point
607                 self.annotate_method_call(segment, e, &mut err);
608             }
609         }
610         // Instead of the following:
611         // error[E0282]: type annotations needed
612         //  --> file2.rs:3:15
613         //   |
614         // 3 |     let _ = x.sum() as f64;
615         //   |             --^^^--------- cannot infer type for `S`
616         //   |
617         //   = note: type must be known at this point
618         // We want:
619         // error[E0282]: type annotations needed
620         //  --> file2.rs:3:15
621         //   |
622         // 3 |     let _ = x.sum() as f64;
623         //   |               ^^^ cannot infer type for `S`
624         //   |
625         //   = note: type must be known at this point
626         let span = arg_data.span.unwrap_or(err_span);
627         if !err
628             .span
629             .span_labels()
630             .iter()
631             .any(|span_label| span_label.label.is_some() && span_label.span == span)
632             && local_visitor.found_arg_pattern.is_none()
633         {
634             // Avoid multiple labels pointing at `span`.
635             err.span_label(
636                 span,
637                 InferCtxt::cannot_infer_msg(
638                     kind_str,
639                     &arg_data.name,
640                     &arg_data.description,
641                     arg_data.parent_name,
642                     arg_data.parent_description,
643                 ),
644             );
645         }
646
647         err
648     }
649
650     /// If the `FnSig` for the method call can be found and type arguments are identified as
651     /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
652     fn annotate_method_call(
653         &self,
654         segment: &hir::PathSegment<'_>,
655         e: &Expr<'_>,
656         err: &mut DiagnosticBuilder<'_>,
657     ) {
658         if let (Some(typeck_results), None) = (self.in_progress_typeck_results, &segment.args) {
659             let borrow = typeck_results.borrow();
660             if let Some((DefKind::AssocFn, did)) = borrow.type_dependent_def(e.hir_id) {
661                 let generics = self.tcx.generics_of(did);
662                 if !generics.params.is_empty() {
663                     err.span_suggestion_verbose(
664                         segment.ident.span.shrink_to_hi(),
665                         &format!(
666                             "consider specifying the type argument{} in the method call",
667                             pluralize!(generics.params.len()),
668                         ),
669                         format!(
670                             "::<{}>",
671                             generics
672                                 .params
673                                 .iter()
674                                 .map(|p| p.name.to_string())
675                                 .collect::<Vec<String>>()
676                                 .join(", ")
677                         ),
678                         Applicability::HasPlaceholders,
679                     );
680                 } else {
681                     let sig = self.tcx.fn_sig(did);
682                     let bound_output = sig.output();
683                     let output = bound_output.skip_binder();
684                     err.span_label(e.span, &format!("this method call resolves to `{}`", output));
685                     let kind = output.kind();
686                     if let ty::Projection(proj) = kind {
687                         if let Some(span) = self.tcx.hir().span_if_local(proj.item_def_id) {
688                             err.span_label(span, &format!("`{}` defined here", output));
689                         }
690                     }
691                 }
692             }
693         }
694     }
695
696     pub fn need_type_info_err_in_generator(
697         &self,
698         kind: hir::GeneratorKind,
699         span: Span,
700         ty: Ty<'tcx>,
701     ) -> DiagnosticBuilder<'tcx> {
702         let ty = self.resolve_vars_if_possible(&ty);
703         let data = self.extract_inference_diagnostics_data(ty.into(), None);
704
705         let mut err = struct_span_err!(
706             self.tcx.sess,
707             span,
708             E0698,
709             "type inside {} must be known in this context",
710             kind,
711         );
712         err.span_label(
713             span,
714             InferCtxt::cannot_infer_msg(
715                 "type",
716                 &data.name,
717                 &data.description,
718                 data.parent_name,
719                 data.parent_description,
720             ),
721         );
722         err
723     }
724
725     fn cannot_infer_msg(
726         kind_str: &str,
727         type_name: &str,
728         descr: &str,
729         parent_name: Option<String>,
730         parent_descr: Option<&str>,
731     ) -> String {
732         if type_name == "_" {
733             format!("cannot infer {}", kind_str)
734         } else {
735             let parent_desc = if let Some(parent_name) = parent_name {
736                 let parent_type_descr = if let Some(parent_descr) = parent_descr {
737                     format!(" the {}", parent_descr)
738                 } else {
739                     "".into()
740                 };
741
742                 format!(" declared on{} `{}`", parent_type_descr, parent_name)
743             } else {
744                 "".to_string()
745             };
746
747             // FIXME: We really shouldn't be dealing with strings here
748             // but instead use a sensible enum for cases like this.
749             let preposition = if "the value" == kind_str { "of" } else { "for" };
750             // For example: "cannot infer type for type parameter `T`"
751             format!(
752                 "cannot infer {} {} {} `{}`{}",
753                 kind_str, preposition, descr, type_name, parent_desc
754             )
755             .into()
756         }
757     }
758 }