1 use crate::infer
::type_variable
::TypeVariableOriginKind
;
2 use crate::infer
::InferCtxt
;
3 use rustc_errors
::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}
;
5 use rustc_hir
::def
::{DefKind, Namespace}
;
6 use rustc_hir
::def_id
::DefId
;
7 use rustc_hir
::intravisit
::{self, NestedVisitorMap, Visitor}
;
8 use rustc_hir
::{Body, Expr, ExprKind, FnRetTy, HirId, Local, Pat}
;
9 use rustc_middle
::hir
::map
::Map
;
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, DefIdTree, InferConst, Ty, TyCtxt}
;
14 use rustc_span
::source_map
::DesugaringKind
;
15 use rustc_span
::symbol
::kw
;
19 struct FindHirNodeVisitor
<'a
, 'tcx
> {
20 infcx
: &'a InferCtxt
<'a
, 'tcx
>,
21 target
: GenericArg
<'tcx
>,
23 found_node_ty
: Option
<Ty
<'tcx
>>,
24 found_local_pattern
: Option
<&'tcx Pat
<'tcx
>>,
25 found_arg_pattern
: Option
<&'tcx Pat
<'tcx
>>,
26 found_closure
: Option
<&'tcx Expr
<'tcx
>>,
27 found_method_call
: Option
<&'tcx Expr
<'tcx
>>,
28 found_exact_method_call
: Option
<&'tcx Expr
<'tcx
>>,
29 found_use_diagnostic
: Option
<UseDiagnostic
<'tcx
>>,
32 impl<'a
, 'tcx
> FindHirNodeVisitor
<'a
, 'tcx
> {
33 fn new(infcx
: &'a InferCtxt
<'a
, 'tcx
>, target
: GenericArg
<'tcx
>, target_span
: Span
) -> Self {
39 found_local_pattern
: None
,
40 found_arg_pattern
: None
,
42 found_method_call
: None
,
43 found_exact_method_call
: None
,
44 found_use_diagnostic
: None
,
48 fn node_type_opt(&self, hir_id
: HirId
) -> Option
<Ty
<'tcx
>> {
49 self.infcx
.in_progress_typeck_results?
.borrow().node_type_opt(hir_id
)
52 fn node_ty_contains_target(&self, hir_id
: HirId
) -> Option
<Ty
<'tcx
>> {
53 self.node_type_opt(hir_id
).map(|ty
| self.infcx
.resolve_vars_if_possible(ty
)).filter(|ty
| {
54 ty
.walk(self.infcx
.tcx
).any(|inner
| {
56 || match (inner
.unpack(), self.target
.unpack()) {
57 (GenericArgKind
::Type(inner_ty
), GenericArgKind
::Type(target_ty
)) => {
58 use ty
::{Infer, TyVar}
;
59 match (inner_ty
.kind(), target_ty
.kind()) {
60 (&Infer(TyVar(a_vid
)), &Infer(TyVar(b_vid
))) => self
65 .sub_unified(a_vid
, b_vid
),
75 /// Determine whether the expression, assumed to be the callee within a `Call`,
76 /// corresponds to the `From::from` emitted in desugaring of the `?` operator.
77 fn is_try_conversion(&self, callee
: &Expr
<'tcx
>) -> bool
{
79 .trait_def_from_hir_fn(callee
.hir_id
)
80 .map_or(false, |def_id
| self.infcx
.is_try_conversion(callee
.span
, def_id
))
84 impl<'a
, 'tcx
> Visitor
<'tcx
> for FindHirNodeVisitor
<'a
, 'tcx
> {
87 fn nested_visit_map(&mut self) -> NestedVisitorMap
<Self::Map
> {
88 NestedVisitorMap
::OnlyBodies(self.infcx
.tcx
.hir())
91 fn visit_local(&mut self, local
: &'tcx Local
<'tcx
>) {
92 if let (None
, Some(ty
)) =
93 (self.found_local_pattern
, self.node_ty_contains_target(local
.hir_id
))
95 self.found_local_pattern
= Some(&*local
.pat
);
96 self.found_node_ty
= Some(ty
);
98 intravisit
::walk_local(self, local
);
101 fn visit_body(&mut self, body
: &'tcx Body
<'tcx
>) {
102 for param
in body
.params
{
103 if let (None
, Some(ty
)) =
104 (self.found_arg_pattern
, self.node_ty_contains_target(param
.hir_id
))
106 self.found_arg_pattern
= Some(&*param
.pat
);
107 self.found_node_ty
= Some(ty
);
110 intravisit
::walk_body(self, body
);
113 fn visit_expr(&mut self, expr
: &'tcx Expr
<'tcx
>) {
114 if let ExprKind
::MethodCall(_
, call_span
, exprs
, _
) = expr
.kind
{
115 if call_span
== self.target_span
117 == self.infcx
.in_progress_typeck_results
.and_then(|typeck_results
| {
120 .node_type_opt(exprs
.first().unwrap().hir_id
)
124 self.found_exact_method_call
= Some(&expr
);
129 // FIXME(const_generics): Currently, any uninferred `const` generics arguments
130 // are handled specially, but instead they should be handled in `annotate_method_call`,
131 // which currently doesn't work because this evaluates to `false` for const arguments.
132 // See https://github.com/rust-lang/rust/pull/77758 for more details.
133 if let Some(ty
) = self.node_ty_contains_target(expr
.hir_id
) {
135 ExprKind
::Closure(..) => self.found_closure
= Some(&expr
),
136 ExprKind
::MethodCall(..) => self.found_method_call
= Some(&expr
),
138 // If the given expression falls within the target span and is a
139 // `From::from(e)` call emitted during desugaring of the `?` operator,
140 // extract the types inferred before and after the call
141 ExprKind
::Call(callee
, [arg
])
142 if self.target_span
.contains(expr
.span
)
143 && self.found_use_diagnostic
.is_none()
144 && self.is_try_conversion(callee
) =>
146 self.found_use_diagnostic
= self.node_type_opt(arg
.hir_id
).map(|pre_ty
| {
147 UseDiagnostic
::TryConversion { pre_ty, post_ty: ty, span: callee.span }
153 intravisit
::walk_expr(self, expr
);
157 /// An observation about the use site of a type to be emitted as an additional
158 /// note in an inference failure error.
159 enum UseDiagnostic
<'tcx
> {
160 /// Records the types inferred before and after `From::from` is called on the
161 /// error value within the desugaring of the `?` operator.
162 TryConversion { pre_ty: Ty<'tcx>, post_ty: Ty<'tcx>, span: Span }
,
165 impl UseDiagnostic
<'_
> {
166 /// Return a descriptor of the value at the use site
167 fn descr(&self) -> &'
static str {
169 Self::TryConversion { .. }
=> "error for `?` operator",
173 /// Return a descriptor of the type at the use site
174 fn type_descr(&self) -> &'
static str {
176 Self::TryConversion { .. }
=> "error type for `?` operator",
180 fn applies_to(&self, span
: Span
) -> bool
{
182 // In some cases the span for an inference failure due to try
183 // conversion contains the antecedent expression as well as the `?`
184 Self::TryConversion { span: s, .. }
=> span
.contains(s
) && span
.hi() == s
.hi(),
188 fn attach_note(&self, err
: &mut DiagnosticBuilder
<'_
>) {
190 Self::TryConversion { pre_ty, post_ty, .. }
=> {
191 let intro
= "`?` implicitly converts the error value";
193 let msg
= match (pre_ty
.is_ty_infer(), post_ty
.is_ty_infer()) {
194 (true, true) => format
!("{} using the `From` trait", intro
),
196 format
!("{} into a type implementing `From<{}>`", intro
, pre_ty
)
199 format
!("{} into `{}` using the `From` trait", intro
, post_ty
)
203 "{} into `{}` using its implementation of `From<{}>`",
204 intro
, post_ty
, pre_ty
215 /// Suggest giving an appropriate return type to a closure expression.
216 fn closure_return_type_suggestion(
217 err
: &mut DiagnosticBuilder
<'_
>,
218 output
: &FnRetTy
<'_
>,
222 let (arrow
, post
) = match output
{
223 FnRetTy
::DefaultReturn(_
) => ("-> ", " "),
226 let suggestion
= match body
.value
.kind
{
227 ExprKind
::Block(..) => vec
![(output
.span(), format
!("{}{}{}", arrow
, ret
, post
))],
229 (output
.span(), format
!("{}{}{}{{ ", arrow
, ret
, post
)),
230 (body
.value
.span
.shrink_to_hi(), " }".to_string()),
233 err
.multipart_suggestion(
234 "give this closure an explicit return type without `_` placeholders",
236 Applicability
::HasPlaceholders
,
240 /// Given a closure signature, return a `String` containing a list of all its argument types.
241 fn closure_args(fn_sig
: &ty
::PolyFnSig
<'_
>) -> String
{
247 .map(|args
| args
.tuple_fields().map(|arg
| arg
.to_string()).collect
::<Vec
<_
>>().join(", "))
251 pub enum TypeAnnotationNeeded
{
252 /// ```compile_fail,E0282
253 /// let x = "hello".chars().rev().collect();
256 /// An implementation cannot be chosen unambiguously because of lack of information.
257 /// ```compile_fail,E0283
258 /// let _ = Default::default();
261 /// ```compile_fail,E0284
262 /// let mut d: u64 = 2;
263 /// d = d % 1u32.into();
268 impl Into
<rustc_errors
::DiagnosticId
> for TypeAnnotationNeeded
{
269 fn into(self) -> rustc_errors
::DiagnosticId
{
271 Self::E0282
=> rustc_errors
::error_code
!(E0282
),
272 Self::E0283
=> rustc_errors
::error_code
!(E0283
),
273 Self::E0284
=> rustc_errors
::error_code
!(E0284
),
278 /// Information about a constant or a type containing inference variables.
279 pub struct InferenceDiagnosticsData
{
281 pub span
: Option
<Span
>,
282 pub kind
: UnderspecifiedArgKind
,
283 pub parent
: Option
<InferenceDiagnosticsParentData
>,
286 /// Data on the parent definition where a generic argument was declared.
287 pub struct InferenceDiagnosticsParentData
{
288 pub prefix
: &'
static str,
293 pub enum UnderspecifiedArgKind
{
294 Type { prefix: Cow<'static, str> }
,
295 Const { is_parameter: bool }
,
298 impl InferenceDiagnosticsData
{
299 /// Generate a label for a generic argument which can't be inferred. When not
300 /// much is known about the argument, `use_diag` may be used to describe the
302 fn cannot_infer_msg(&self, use_diag
: Option
<&UseDiagnostic
<'_
>>) -> String
{
303 if self.name
== "_" && matches
!(self.kind
, UnderspecifiedArgKind
::Type { .. }
) {
304 if let Some(use_diag
) = use_diag
{
305 return format
!("cannot infer type of {}", use_diag
.descr());
308 return "cannot infer type".to_string();
311 let suffix
= match (&self.parent
, use_diag
) {
312 (Some(parent
), _
) => format
!(" declared on the {} `{}`", parent
.prefix
, parent
.name
),
313 (None
, Some(use_diag
)) => format
!(" in {}", use_diag
.type_descr()),
314 (None
, None
) => String
::new(),
317 // For example: "cannot infer type for type parameter `T`"
318 format
!("cannot infer {} `{}`{}", self.kind
.prefix_string(), self.name
, suffix
)
322 impl InferenceDiagnosticsParentData
{
323 fn for_def_id(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Option
<InferenceDiagnosticsParentData
> {
324 let parent_def_id
= tcx
.parent(def_id
)?
;
327 tcx
.def_key(parent_def_id
).disambiguated_data
.data
.get_opt_name()?
.to_string();
329 Some(InferenceDiagnosticsParentData
{
330 prefix
: tcx
.def_kind(parent_def_id
).descr(parent_def_id
),
332 def_id
: parent_def_id
,
337 impl UnderspecifiedArgKind
{
338 fn prefix_string(&self) -> Cow
<'
static, str> {
340 Self::Type { prefix }
=> format
!("type for {}", prefix
).into(),
341 Self::Const { is_parameter: true }
=> "the value of const parameter".into(),
342 Self::Const { is_parameter: false }
=> "the value of the constant".into(),
347 impl<'a
, 'tcx
> InferCtxt
<'a
, 'tcx
> {
348 /// Extracts data used by diagnostic for either types or constants
349 /// which were stuck during inference.
350 pub fn extract_inference_diagnostics_data(
352 arg
: GenericArg
<'tcx
>,
353 highlight
: Option
<ty
::print
::RegionHighlightMode
>,
354 ) -> InferenceDiagnosticsData
{
356 GenericArgKind
::Type(ty
) => {
357 if let ty
::Infer(ty
::TyVar(ty_vid
)) = *ty
.kind() {
358 let mut inner
= self.inner
.borrow_mut();
359 let ty_vars
= &inner
.type_variables();
360 let var_origin
= ty_vars
.var_origin(ty_vid
);
361 if let TypeVariableOriginKind
::TypeParameterDefinition(name
, def_id
) =
364 if name
!= kw
::SelfUpper
{
365 return InferenceDiagnosticsData
{
366 name
: name
.to_string(),
367 span
: Some(var_origin
.span
),
368 kind
: UnderspecifiedArgKind
::Type
{
369 prefix
: "type parameter".into(),
371 parent
: def_id
.and_then(|def_id
| {
372 InferenceDiagnosticsParentData
::for_def_id(self.tcx
, def_id
)
379 let mut s
= String
::new();
380 let mut printer
= ty
::print
::FmtPrinter
::new(self.tcx
, &mut s
, Namespace
::TypeNS
);
381 if let Some(highlight
) = highlight
{
382 printer
.region_highlight_mode
= highlight
;
384 let _
= ty
.print(printer
);
385 InferenceDiagnosticsData
{
388 kind
: UnderspecifiedArgKind
::Type { prefix: ty.prefix_string(self.tcx) }
,
392 GenericArgKind
::Const(ct
) => {
393 if let ty
::ConstKind
::Infer(InferConst
::Var(vid
)) = ct
.val
{
395 self.inner
.borrow_mut().const_unification_table().probe_value(vid
).origin
;
396 if let ConstVariableOriginKind
::ConstParameterDefinition(name
, def_id
) =
399 return InferenceDiagnosticsData
{
400 name
: name
.to_string(),
401 span
: Some(origin
.span
),
402 kind
: UnderspecifiedArgKind
::Const { is_parameter: true }
,
403 parent
: InferenceDiagnosticsParentData
::for_def_id(self.tcx
, def_id
),
407 debug_assert
!(!origin
.span
.is_dummy());
408 let mut s
= String
::new();
410 ty
::print
::FmtPrinter
::new(self.tcx
, &mut s
, Namespace
::ValueNS
);
411 if let Some(highlight
) = highlight
{
412 printer
.region_highlight_mode
= highlight
;
414 let _
= ct
.print(printer
);
415 InferenceDiagnosticsData
{
417 span
: Some(origin
.span
),
418 kind
: UnderspecifiedArgKind
::Const { is_parameter: false }
,
422 bug
!("unexpect const: {:?}", ct
);
425 GenericArgKind
::Lifetime(_
) => bug
!("unexpected lifetime"),
429 pub fn emit_inference_failure_err(
431 body_id
: Option
<hir
::BodyId
>,
433 arg
: GenericArg
<'tcx
>,
434 impl_candidates
: Vec
<ty
::TraitRef
<'tcx
>>,
435 error_code
: TypeAnnotationNeeded
,
436 ) -> DiagnosticBuilder
<'tcx
> {
437 let arg
= self.resolve_vars_if_possible(arg
);
438 let arg_data
= self.extract_inference_diagnostics_data(arg
, None
);
440 let mut local_visitor
= FindHirNodeVisitor
::new(&self, arg
, span
);
441 let ty_to_string
= |ty
: Ty
<'tcx
>| -> String
{
442 let mut s
= String
::new();
443 let mut printer
= ty
::print
::FmtPrinter
::new(self.tcx
, &mut s
, Namespace
::TypeNS
);
444 let mut inner
= self.inner
.borrow_mut();
445 let ty_vars
= inner
.type_variables();
446 let getter
= move |ty_vid
| {
447 let var_origin
= ty_vars
.var_origin(ty_vid
);
448 if let TypeVariableOriginKind
::TypeParameterDefinition(name
, _
) = var_origin
.kind
{
449 return Some(name
.to_string());
453 printer
.name_resolver
= Some(Box
::new(&getter
));
454 let _
= if let ty
::FnDef(..) = ty
.kind() {
455 // We don't want the regular output for `fn`s because it includes its path in
456 // invalid pseudo-syntax, we want the `fn`-pointer output instead.
457 ty
.fn_sig(self.tcx
).print(printer
)
464 if let Some(body_id
) = body_id
{
465 let expr
= self.tcx
.hir().expect_expr(body_id
.hir_id
);
466 local_visitor
.visit_expr(expr
);
468 let err_span
= if let Some(pattern
) = local_visitor
.found_arg_pattern
{
470 } else if let Some(span
) = arg_data
.span
{
471 // `span` here lets us point at `sum` instead of the entire right hand side expr:
472 // error[E0282]: type annotations needed
475 // 3 | let _ = x.sum() as f64;
476 // | ^^^ cannot infer type for `S`
478 } else if let Some(ExprKind
::MethodCall(_
, call_span
, _
, _
)) =
479 local_visitor
.found_method_call
.map(|e
| &e
.kind
)
481 // Point at the call instead of the whole expression:
482 // error[E0284]: type annotations needed
485 // 2 | vec![Ok(2)].into_iter().collect()?;
486 // | ^^^^^^^ cannot infer type
488 // = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
489 if span
.contains(*call_span
) { *call_span }
else { span }
494 let is_named_and_not_impl_trait
=
495 |ty
: Ty
<'_
>| &ty
.to_string() != "_" && !ty
.is_impl_trait();
497 let ty_msg
= match (local_visitor
.found_node_ty
, local_visitor
.found_exact_method_call
) {
498 (_
, Some(_
)) => String
::new(),
499 (Some(ty
), _
) if ty
.is_closure() => {
501 if let ty
::Closure(_
, substs
) = *ty
.kind() { substs }
else { unreachable!() }
;
502 let fn_sig
= substs
.as_closure().sig();
503 let args
= closure_args(&fn_sig
);
504 let ret
= fn_sig
.output().skip_binder().to_string();
505 format
!(" for the closure `fn({}) -> {}`", args
, ret
)
507 (Some(ty
), _
) if is_named_and_not_impl_trait(ty
) => {
508 let ty
= ty_to_string(ty
);
509 format
!(" for `{}`", ty
)
514 // When `arg_data.name` corresponds to a type argument, show the path of the full type we're
515 // trying to infer. In the following example, `ty_msg` contains
516 // " for `std::result::Result<i32, E>`":
518 // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
521 // L | let b = Ok(4);
522 // | - ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
524 // | consider giving `b` the explicit type `std::result::Result<i32, E>`, where
525 // | the type parameter `E` is specified
527 let error_code
= error_code
.into();
528 let mut err
= self.tcx
.sess
.struct_span_err_with_code(
530 &format
!("type annotations needed{}", ty_msg
),
534 let use_diag
= local_visitor
.found_use_diagnostic
.as_ref();
535 if let Some(use_diag
) = use_diag
{
536 if use_diag
.applies_to(err_span
) {
537 use_diag
.attach_note(&mut err
);
541 let suffix
= match local_visitor
.found_node_ty
{
542 Some(ty
) if ty
.is_closure() => {
544 if let ty
::Closure(_
, substs
) = *ty
.kind() { substs }
else { unreachable!() }
;
545 let fn_sig
= substs
.as_closure().sig();
546 let ret
= fn_sig
.output().skip_binder().to_string();
548 let closure_decl_and_body_id
=
549 local_visitor
.found_closure
.and_then(|closure
| match &closure
.kind
{
550 ExprKind
::Closure(_
, decl
, body_id
, ..) => Some((decl
, *body_id
)),
554 if let Some((decl
, body_id
)) = closure_decl_and_body_id
{
555 closure_return_type_suggestion(
558 self.tcx
.hir().body(body_id
),
561 // We don't want to give the other suggestions when the problem is the
562 // closure return type.
565 arg_data
.cannot_infer_msg(use_diag
.filter(|d
| d
.applies_to(span
))),
570 // This shouldn't be reachable, but just in case we leave a reasonable fallback.
571 let args
= closure_args(&fn_sig
);
572 // This suggestion is incomplete, as the user will get further type inference
573 // errors due to the `_` placeholders and the introduction of `Box`, but it does
574 // nudge them in the right direction.
575 format
!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args
, ret
)
577 Some(ty
) if is_named_and_not_impl_trait(ty
) && arg_data
.name
== "_" => {
578 let ty
= ty_to_string(ty
);
579 format
!("the explicit type `{}`, with the type parameters specified", ty
)
581 Some(ty
) if is_named_and_not_impl_trait(ty
) && ty
.to_string() != arg_data
.name
=> {
582 let ty
= ty_to_string(ty
);
584 "the explicit type `{}`, where the type parameter `{}` is specified",
588 _
=> "a type".to_string(),
591 if let Some(e
) = local_visitor
.found_exact_method_call
{
592 if let ExprKind
::MethodCall(segment
, ..) = &e
.kind
{
593 // Suggest specifying type params or point out the return type of the call:
595 // error[E0282]: type annotations needed
596 // --> $DIR/type-annotations-needed-expr.rs:2:39
598 // LL | let _ = x.into_iter().sum() as f64;
601 // | cannot infer type for `S`
602 // | help: consider specifying the type argument in
603 // | the method call: `sum::<S>`
605 // = note: type must be known at this point
609 // error[E0282]: type annotations needed
610 // --> $DIR/issue-65611.rs:59:20
612 // LL | let x = buffer.last().unwrap().0.clone();
615 // | | cannot infer type for `T`
616 // | this method call resolves to `std::option::Option<&T>`
618 // = note: type must be known at this point
619 self.annotate_method_call(segment
, e
, &mut err
);
621 } else if let Some(pattern
) = local_visitor
.found_arg_pattern
{
622 // We don't want to show the default label for closures.
624 // So, before clearing, the output would look something like this:
627 // - ^^^^ cannot infer type for `[_; 0]`
629 // consider giving this closure parameter a type
632 // After clearing, it looks something like this:
635 // ^ consider giving this closure parameter the type `[_; 0]`
636 // with the type parameter `_` specified
640 format
!("consider giving this closure parameter {}", suffix
),
642 } else if let Some(pattern
) = local_visitor
.found_local_pattern
{
643 let msg
= if let Some(simple_ident
) = pattern
.simple_ident() {
644 match pattern
.span
.desugaring_kind() {
645 None
=> format
!("consider giving `{}` {}", simple_ident
, suffix
),
646 Some(DesugaringKind
::ForLoop(_
)) => {
647 "the element type for this iterator is not specified".to_string()
649 _
=> format
!("this needs {}", suffix
),
652 format
!("consider giving this pattern {}", suffix
)
654 err
.span_label(pattern
.span
, msg
);
655 } else if let Some(e
) = local_visitor
.found_method_call
{
656 if let ExprKind
::MethodCall(segment
, _
, exprs
, _
) = &e
.kind
{
657 // Suggest impl candidates:
659 // error[E0283]: type annotations needed
660 // --> $DIR/E0283.rs:35:24
662 // LL | let bar = foo_impl.into() * 1u32;
665 // | | cannot infer type for type parameter `T` declared on the trait `Into`
666 // | this method call resolves to `T`
667 // | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
669 // = note: cannot satisfy `Impl: Into<_>`
670 if !impl_candidates
.is_empty() && e
.span
.contains(span
) {
671 if let Some(expr
) = exprs
.first() {
672 if let ExprKind
::Path(hir
::QPath
::Resolved(_
, path
)) = expr
.kind
{
673 if let [path_segment
] = path
.segments
{
674 let candidate_len
= impl_candidates
.len();
675 let suggestions
= impl_candidates
.iter().map(|candidate
| {
678 candidate
, segment
.ident
, path_segment
.ident
681 err
.span_suggestions(
684 "use the fully qualified path for the potential candidate{}",
685 pluralize
!(candidate_len
),
688 Applicability
::MaybeIncorrect
,
694 // Suggest specifying type params or point out the return type of the call:
696 // error[E0282]: type annotations needed
697 // --> $DIR/type-annotations-needed-expr.rs:2:39
699 // LL | let _ = x.into_iter().sum() as f64;
702 // | cannot infer type for `S`
703 // | help: consider specifying the type argument in
704 // | the method call: `sum::<S>`
706 // = note: type must be known at this point
710 // error[E0282]: type annotations needed
711 // --> $DIR/issue-65611.rs:59:20
713 // LL | let x = buffer.last().unwrap().0.clone();
716 // | | cannot infer type for `T`
717 // | this method call resolves to `std::option::Option<&T>`
719 // = note: type must be known at this point
720 self.annotate_method_call(segment
, e
, &mut err
);
723 // Instead of the following:
724 // error[E0282]: type annotations needed
727 // 3 | let _ = x.sum() as f64;
728 // | --^^^--------- cannot infer type for `S`
730 // = note: type must be known at this point
732 // error[E0282]: type annotations needed
735 // 3 | let _ = x.sum() as f64;
736 // | ^^^ cannot infer type for `S`
738 // = note: type must be known at this point
739 let span
= arg_data
.span
.unwrap_or(err_span
);
741 // Avoid multiple labels pointing at `span`.
746 .any(|span_label
| span_label
.label
.is_some() && span_label
.span
== span
)
747 && local_visitor
.found_arg_pattern
.is_none()
749 // FIXME(const_generics): we would like to handle const arguments
750 // as part of the normal diagnostics flow below, but there appear to
751 // be subtleties in doing so, so for now we special-case const args
753 if let (UnderspecifiedArgKind
::Const { .. }
, Some(parent_data
)) =
754 (&arg_data
.kind
, &arg_data
.parent
)
756 // (#83606): Do not emit a suggestion if the parent has an `impl Trait`
757 // as an argument otherwise it will cause the E0282 error.
758 if !self.tcx
.generics_of(parent_data
.def_id
).has_impl_trait()
759 || self.tcx
.features().explicit_generic_args_with_impl_trait
761 err
.span_suggestion_verbose(
763 "consider specifying the const argument",
764 format
!("{}::<{}>", parent_data
.name
, arg_data
.name
),
765 Applicability
::MaybeIncorrect
,
772 arg_data
.cannot_infer_msg(use_diag
.filter(|d
| d
.applies_to(span
))),
779 fn trait_def_from_hir_fn(&self, hir_id
: hir
::HirId
) -> Option
<DefId
> {
780 // The DefId will be the method's trait item ID unless this is an inherent impl
781 if let Some((DefKind
::AssocFn
, def_id
)) =
782 self.in_progress_typeck_results?
.borrow().type_dependent_def(hir_id
)
787 .filter(|&parent_def_id
| self.tcx
.is_trait(parent_def_id
));
793 /// If the `FnSig` for the method call can be found and type arguments are identified as
794 /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
795 fn annotate_method_call(
797 segment
: &hir
::PathSegment
<'_
>,
799 err
: &mut DiagnosticBuilder
<'_
>,
801 if let (Some(typeck_results
), None
) = (self.in_progress_typeck_results
, &segment
.args
) {
802 let borrow
= typeck_results
.borrow();
803 if let Some((DefKind
::AssocFn
, did
)) = borrow
.type_dependent_def(e
.hir_id
) {
804 let generics
= self.tcx
.generics_of(did
);
805 if !generics
.params
.is_empty() && !generics
.has_impl_trait() {
806 err
.span_suggestion_verbose(
807 segment
.ident
.span
.shrink_to_hi(),
809 "consider specifying the type argument{} in the method call",
810 pluralize
!(generics
.params
.len()),
817 .map(|p
| p
.name
.to_string())
818 .collect
::<Vec
<String
>>()
821 Applicability
::HasPlaceholders
,
824 let sig
= self.tcx
.fn_sig(did
);
825 let bound_output
= sig
.output();
826 let output
= bound_output
.skip_binder();
827 err
.span_label(e
.span
, &format
!("this method call resolves to `{}`", output
));
828 let kind
= output
.kind();
829 if let ty
::Projection(proj
) = kind
{
830 if let Some(span
) = self.tcx
.hir().span_if_local(proj
.item_def_id
) {
831 err
.span_label(span
, &format
!("`{}` defined here", output
));
839 pub fn need_type_info_err_in_generator(
841 kind
: hir
::GeneratorKind
,
844 ) -> DiagnosticBuilder
<'tcx
> {
845 let ty
= self.resolve_vars_if_possible(ty
);
846 let data
= self.extract_inference_diagnostics_data(ty
.into(), None
);
848 let mut err
= struct_span_err
!(
852 "type inside {} must be known in this context",
855 err
.span_label(span
, data
.cannot_infer_msg(None
));