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