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