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().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,
292 pub enum UnderspecifiedArgKind
{
293 Type { prefix: Cow<'static, str> }
,
294 Const { is_parameter: bool }
,
297 impl InferenceDiagnosticsData
{
298 /// Generate a label for a generic argument which can't be inferred. When not
299 /// much is known about the argument, `use_diag` may be used to describe the
301 fn cannot_infer_msg(&self, use_diag
: Option
<&UseDiagnostic
<'_
>>) -> String
{
302 if self.name
== "_" && matches
!(self.kind
, UnderspecifiedArgKind
::Type { .. }
) {
303 if let Some(use_diag
) = use_diag
{
304 return format
!("cannot infer type of {}", use_diag
.descr());
307 return "cannot infer type".to_string();
310 let suffix
= match (&self.parent
, use_diag
) {
311 (Some(parent
), _
) => format
!(" declared on the {} `{}`", parent
.prefix
, parent
.name
),
312 (None
, Some(use_diag
)) => format
!(" in {}", use_diag
.type_descr()),
313 (None
, None
) => String
::new(),
316 // For example: "cannot infer type for type parameter `T`"
317 format
!("cannot infer {} `{}`{}", self.kind
.prefix_string(), self.name
, suffix
)
321 impl InferenceDiagnosticsParentData
{
322 fn for_def_id(tcx
: TyCtxt
<'_
>, def_id
: DefId
) -> Option
<InferenceDiagnosticsParentData
> {
323 let parent_def_id
= tcx
.parent(def_id
)?
;
326 tcx
.def_key(parent_def_id
).disambiguated_data
.data
.get_opt_name()?
.to_string();
328 Some(InferenceDiagnosticsParentData
{
329 prefix
: tcx
.def_kind(parent_def_id
).descr(parent_def_id
),
335 impl UnderspecifiedArgKind
{
336 fn prefix_string(&self) -> Cow
<'
static, str> {
338 Self::Type { prefix }
=> format
!("type for {}", prefix
).into(),
339 Self::Const { is_parameter: true }
=> "the value of const parameter".into(),
340 Self::Const { is_parameter: false }
=> "the value of the constant".into(),
345 impl<'a
, 'tcx
> InferCtxt
<'a
, 'tcx
> {
346 /// Extracts data used by diagnostic for either types or constants
347 /// which were stuck during inference.
348 pub fn extract_inference_diagnostics_data(
350 arg
: GenericArg
<'tcx
>,
351 highlight
: Option
<ty
::print
::RegionHighlightMode
>,
352 ) -> InferenceDiagnosticsData
{
354 GenericArgKind
::Type(ty
) => {
355 if let ty
::Infer(ty
::TyVar(ty_vid
)) = *ty
.kind() {
356 let mut inner
= self.inner
.borrow_mut();
357 let ty_vars
= &inner
.type_variables();
358 let var_origin
= ty_vars
.var_origin(ty_vid
);
359 if let TypeVariableOriginKind
::TypeParameterDefinition(name
, def_id
) =
362 if name
!= kw
::SelfUpper
{
363 return InferenceDiagnosticsData
{
364 name
: name
.to_string(),
365 span
: Some(var_origin
.span
),
366 kind
: UnderspecifiedArgKind
::Type
{
367 prefix
: "type parameter".into(),
369 parent
: def_id
.and_then(|def_id
| {
370 InferenceDiagnosticsParentData
::for_def_id(self.tcx
, def_id
)
377 let mut s
= String
::new();
378 let mut printer
= ty
::print
::FmtPrinter
::new(self.tcx
, &mut s
, Namespace
::TypeNS
);
379 if let Some(highlight
) = highlight
{
380 printer
.region_highlight_mode
= highlight
;
382 let _
= ty
.print(printer
);
383 InferenceDiagnosticsData
{
386 kind
: UnderspecifiedArgKind
::Type { prefix: ty.prefix_string(self.tcx) }
,
390 GenericArgKind
::Const(ct
) => {
391 if let ty
::ConstKind
::Infer(InferConst
::Var(vid
)) = ct
.val
{
393 self.inner
.borrow_mut().const_unification_table().probe_value(vid
).origin
;
394 if let ConstVariableOriginKind
::ConstParameterDefinition(name
, def_id
) =
397 return InferenceDiagnosticsData
{
398 name
: name
.to_string(),
399 span
: Some(origin
.span
),
400 kind
: UnderspecifiedArgKind
::Const { is_parameter: true }
,
401 parent
: InferenceDiagnosticsParentData
::for_def_id(self.tcx
, def_id
),
405 debug_assert
!(!origin
.span
.is_dummy());
406 let mut s
= String
::new();
408 ty
::print
::FmtPrinter
::new(self.tcx
, &mut s
, Namespace
::ValueNS
);
409 if let Some(highlight
) = highlight
{
410 printer
.region_highlight_mode
= highlight
;
412 let _
= ct
.print(printer
);
413 InferenceDiagnosticsData
{
415 span
: Some(origin
.span
),
416 kind
: UnderspecifiedArgKind
::Const { is_parameter: false }
,
420 bug
!("unexpect const: {:?}", ct
);
423 GenericArgKind
::Lifetime(_
) => bug
!("unexpected lifetime"),
427 pub fn emit_inference_failure_err(
429 body_id
: Option
<hir
::BodyId
>,
431 arg
: GenericArg
<'tcx
>,
432 impl_candidates
: Vec
<ty
::TraitRef
<'tcx
>>,
433 error_code
: TypeAnnotationNeeded
,
434 ) -> DiagnosticBuilder
<'tcx
> {
435 let arg
= self.resolve_vars_if_possible(arg
);
436 let arg_data
= self.extract_inference_diagnostics_data(arg
, None
);
438 let mut local_visitor
= FindHirNodeVisitor
::new(&self, arg
, span
);
439 let ty_to_string
= |ty
: Ty
<'tcx
>| -> String
{
440 let mut s
= String
::new();
441 let mut printer
= ty
::print
::FmtPrinter
::new(self.tcx
, &mut s
, Namespace
::TypeNS
);
442 let mut inner
= self.inner
.borrow_mut();
443 let ty_vars
= inner
.type_variables();
444 let getter
= move |ty_vid
| {
445 let var_origin
= ty_vars
.var_origin(ty_vid
);
446 if let TypeVariableOriginKind
::TypeParameterDefinition(name
, _
) = var_origin
.kind
{
447 return Some(name
.to_string());
451 printer
.name_resolver
= Some(Box
::new(&getter
));
452 let _
= if let ty
::FnDef(..) = ty
.kind() {
453 // We don't want the regular output for `fn`s because it includes its path in
454 // invalid pseudo-syntax, we want the `fn`-pointer output instead.
455 ty
.fn_sig(self.tcx
).print(printer
)
462 if let Some(body_id
) = body_id
{
463 let expr
= self.tcx
.hir().expect_expr(body_id
.hir_id
);
464 local_visitor
.visit_expr(expr
);
466 let err_span
= if let Some(pattern
) = local_visitor
.found_arg_pattern
{
468 } else if let Some(span
) = arg_data
.span
{
469 // `span` here lets us point at `sum` instead of the entire right hand side expr:
470 // error[E0282]: type annotations needed
473 // 3 | let _ = x.sum() as f64;
474 // | ^^^ cannot infer type for `S`
476 } else if let Some(ExprKind
::MethodCall(_
, call_span
, _
, _
)) =
477 local_visitor
.found_method_call
.map(|e
| &e
.kind
)
479 // Point at the call instead of the whole expression:
480 // error[E0284]: type annotations needed
483 // 2 | vec![Ok(2)].into_iter().collect()?;
484 // | ^^^^^^^ cannot infer type
486 // = note: cannot resolve `<_ as std::ops::Try>::Ok == _`
487 if span
.contains(*call_span
) { *call_span }
else { span }
492 let is_named_and_not_impl_trait
= |ty
: Ty
<'_
>| {
493 &ty
.to_string() != "_" &&
494 // FIXME: Remove this check after `impl_trait_in_bindings` is stabilized. #63527
495 (!ty
.is_impl_trait() || self.tcx
.features().impl_trait_in_bindings
)
498 let ty_msg
= match (local_visitor
.found_node_ty
, local_visitor
.found_exact_method_call
) {
499 (_
, Some(_
)) => String
::new(),
500 (Some(ty
), _
) if ty
.is_closure() => {
502 if let ty
::Closure(_
, substs
) = *ty
.kind() { substs }
else { unreachable!() }
;
503 let fn_sig
= substs
.as_closure().sig();
504 let args
= closure_args(&fn_sig
);
505 let ret
= fn_sig
.output().skip_binder().to_string();
506 format
!(" for the closure `fn({}) -> {}`", args
, ret
)
508 (Some(ty
), _
) if is_named_and_not_impl_trait(ty
) => {
509 let ty
= ty_to_string(ty
);
510 format
!(" for `{}`", ty
)
515 // When `arg_data.name` corresponds to a type argument, show the path of the full type we're
516 // trying to infer. In the following example, `ty_msg` contains
517 // " for `std::result::Result<i32, E>`":
519 // error[E0282]: type annotations needed for `std::result::Result<i32, E>`
522 // L | let b = Ok(4);
523 // | - ^^ cannot infer type for `E` in `std::result::Result<i32, E>`
525 // | consider giving `b` the explicit type `std::result::Result<i32, E>`, where
526 // | the type parameter `E` is specified
528 let error_code
= error_code
.into();
529 let mut err
= self.tcx
.sess
.struct_span_err_with_code(
531 &format
!("type annotations needed{}", ty_msg
),
535 let use_diag
= local_visitor
.found_use_diagnostic
.as_ref();
536 if let Some(use_diag
) = use_diag
{
537 if use_diag
.applies_to(err_span
) {
538 use_diag
.attach_note(&mut err
);
542 let suffix
= match local_visitor
.found_node_ty
{
543 Some(ty
) if ty
.is_closure() => {
545 if let ty
::Closure(_
, substs
) = *ty
.kind() { substs }
else { unreachable!() }
;
546 let fn_sig
= substs
.as_closure().sig();
547 let ret
= fn_sig
.output().skip_binder().to_string();
549 let closure_decl_and_body_id
=
550 local_visitor
.found_closure
.and_then(|closure
| match &closure
.kind
{
551 ExprKind
::Closure(_
, decl
, body_id
, ..) => Some((decl
, *body_id
)),
555 if let Some((decl
, body_id
)) = closure_decl_and_body_id
{
556 closure_return_type_suggestion(
559 self.tcx
.hir().body(body_id
),
562 // We don't want to give the other suggestions when the problem is the
563 // closure return type.
566 arg_data
.cannot_infer_msg(use_diag
.filter(|d
| d
.applies_to(span
))),
571 // This shouldn't be reachable, but just in case we leave a reasonable fallback.
572 let args
= closure_args(&fn_sig
);
573 // This suggestion is incomplete, as the user will get further type inference
574 // errors due to the `_` placeholders and the introduction of `Box`, but it does
575 // nudge them in the right direction.
576 format
!("a boxed closure type like `Box<dyn Fn({}) -> {}>`", args
, ret
)
578 Some(ty
) if is_named_and_not_impl_trait(ty
) && arg_data
.name
== "_" => {
579 let ty
= ty_to_string(ty
);
580 format
!("the explicit type `{}`, with the type parameters specified", ty
)
582 Some(ty
) if is_named_and_not_impl_trait(ty
) && ty
.to_string() != arg_data
.name
=> {
583 let ty
= ty_to_string(ty
);
585 "the explicit type `{}`, where the type parameter `{}` is specified",
589 _
=> "a type".to_string(),
592 if let Some(e
) = local_visitor
.found_exact_method_call
{
593 if let ExprKind
::MethodCall(segment
, ..) = &e
.kind
{
594 // Suggest specifying type params or point out the return type of the call:
596 // error[E0282]: type annotations needed
597 // --> $DIR/type-annotations-needed-expr.rs:2:39
599 // LL | let _ = x.into_iter().sum() as f64;
602 // | cannot infer type for `S`
603 // | help: consider specifying the type argument in
604 // | the method call: `sum::<S>`
606 // = note: type must be known at this point
610 // error[E0282]: type annotations needed
611 // --> $DIR/issue-65611.rs:59:20
613 // LL | let x = buffer.last().unwrap().0.clone();
616 // | | cannot infer type for `T`
617 // | this method call resolves to `std::option::Option<&T>`
619 // = note: type must be known at this point
620 self.annotate_method_call(segment
, e
, &mut err
);
622 } else if let Some(pattern
) = local_visitor
.found_arg_pattern
{
623 // We don't want to show the default label for closures.
625 // So, before clearing, the output would look something like this:
628 // - ^^^^ cannot infer type for `[_; 0]`
630 // consider giving this closure parameter a type
633 // After clearing, it looks something like this:
636 // ^ consider giving this closure parameter the type `[_; 0]`
637 // with the type parameter `_` specified
641 format
!("consider giving this closure parameter {}", suffix
),
643 } else if let Some(pattern
) = local_visitor
.found_local_pattern
{
644 let msg
= if let Some(simple_ident
) = pattern
.simple_ident() {
645 match pattern
.span
.desugaring_kind() {
646 None
=> format
!("consider giving `{}` {}", simple_ident
, suffix
),
647 Some(DesugaringKind
::ForLoop(_
)) => {
648 "the element type for this iterator is not specified".to_string()
650 _
=> format
!("this needs {}", suffix
),
653 format
!("consider giving this pattern {}", suffix
)
655 err
.span_label(pattern
.span
, msg
);
656 } else if let Some(e
) = local_visitor
.found_method_call
{
657 if let ExprKind
::MethodCall(segment
, _
, exprs
, _
) = &e
.kind
{
658 // Suggest impl candidates:
660 // error[E0283]: type annotations needed
661 // --> $DIR/E0283.rs:35:24
663 // LL | let bar = foo_impl.into() * 1u32;
666 // | | cannot infer type for type parameter `T` declared on the trait `Into`
667 // | this method call resolves to `T`
668 // | help: specify type like: `<Impl as Into<u32>>::into(foo_impl)`
670 // = note: cannot satisfy `Impl: Into<_>`
671 if !impl_candidates
.is_empty() && e
.span
.contains(span
) {
672 if let Some(expr
) = exprs
.first() {
673 if let ExprKind
::Path(hir
::QPath
::Resolved(_
, path
)) = expr
.kind
{
674 if let [path_segment
] = path
.segments
{
675 let candidate_len
= impl_candidates
.len();
676 let suggestions
= impl_candidates
.iter().map(|candidate
| {
679 candidate
, segment
.ident
, path_segment
.ident
682 err
.span_suggestions(
685 "use the fully qualified path for the potential candidate{}",
686 pluralize
!(candidate_len
),
689 Applicability
::MaybeIncorrect
,
695 // Suggest specifying type params or point out the return type of the call:
697 // error[E0282]: type annotations needed
698 // --> $DIR/type-annotations-needed-expr.rs:2:39
700 // LL | let _ = x.into_iter().sum() as f64;
703 // | cannot infer type for `S`
704 // | help: consider specifying the type argument in
705 // | the method call: `sum::<S>`
707 // = note: type must be known at this point
711 // error[E0282]: type annotations needed
712 // --> $DIR/issue-65611.rs:59:20
714 // LL | let x = buffer.last().unwrap().0.clone();
717 // | | cannot infer type for `T`
718 // | this method call resolves to `std::option::Option<&T>`
720 // = note: type must be known at this point
721 self.annotate_method_call(segment
, e
, &mut err
);
724 // Instead of the following:
725 // error[E0282]: type annotations needed
728 // 3 | let _ = x.sum() as f64;
729 // | --^^^--------- cannot infer type for `S`
731 // = note: type must be known at this point
733 // error[E0282]: type annotations needed
736 // 3 | let _ = x.sum() as f64;
737 // | ^^^ cannot infer type for `S`
739 // = note: type must be known at this point
740 let span
= arg_data
.span
.unwrap_or(err_span
);
742 // Avoid multiple labels pointing at `span`.
747 .any(|span_label
| span_label
.label
.is_some() && span_label
.span
== span
)
748 && local_visitor
.found_arg_pattern
.is_none()
750 // FIXME(const_generics): we would like to handle const arguments
751 // as part of the normal diagnostics flow below, but there appear to
752 // be subtleties in doing so, so for now we special-case const args
754 if let (UnderspecifiedArgKind
::Const { .. }
, Some(parent_data
)) =
755 (&arg_data
.kind
, &arg_data
.parent
)
757 err
.span_suggestion_verbose(
759 "consider specifying the const argument",
760 format
!("{}::<{}>", parent_data
.name
, arg_data
.name
),
761 Applicability
::MaybeIncorrect
,
767 arg_data
.cannot_infer_msg(use_diag
.filter(|d
| d
.applies_to(span
))),
774 fn trait_def_from_hir_fn(&self, hir_id
: hir
::HirId
) -> Option
<DefId
> {
775 // The DefId will be the method's trait item ID unless this is an inherent impl
776 if let Some((DefKind
::AssocFn
, def_id
)) =
777 self.in_progress_typeck_results?
.borrow().type_dependent_def(hir_id
)
782 .filter(|&parent_def_id
| self.tcx
.is_trait(parent_def_id
));
788 /// If the `FnSig` for the method call can be found and type arguments are identified as
789 /// needed, suggest annotating the call, otherwise point out the resulting type of the call.
790 fn annotate_method_call(
792 segment
: &hir
::PathSegment
<'_
>,
794 err
: &mut DiagnosticBuilder
<'_
>,
796 if let (Some(typeck_results
), None
) = (self.in_progress_typeck_results
, &segment
.args
) {
797 let borrow
= typeck_results
.borrow();
798 if let Some((DefKind
::AssocFn
, did
)) = borrow
.type_dependent_def(e
.hir_id
) {
799 let generics
= self.tcx
.generics_of(did
);
800 if !generics
.params
.is_empty() {
801 err
.span_suggestion_verbose(
802 segment
.ident
.span
.shrink_to_hi(),
804 "consider specifying the type argument{} in the method call",
805 pluralize
!(generics
.params
.len()),
812 .map(|p
| p
.name
.to_string())
813 .collect
::<Vec
<String
>>()
816 Applicability
::HasPlaceholders
,
819 let sig
= self.tcx
.fn_sig(did
);
820 let bound_output
= sig
.output();
821 let output
= bound_output
.skip_binder();
822 err
.span_label(e
.span
, &format
!("this method call resolves to `{}`", output
));
823 let kind
= output
.kind();
824 if let ty
::Projection(proj
) = kind
{
825 if let Some(span
) = self.tcx
.hir().span_if_local(proj
.item_def_id
) {
826 err
.span_label(span
, &format
!("`{}` defined here", output
));
834 pub fn need_type_info_err_in_generator(
836 kind
: hir
::GeneratorKind
,
839 ) -> DiagnosticBuilder
<'tcx
> {
840 let ty
= self.resolve_vars_if_possible(ty
);
841 let data
= self.extract_inference_diagnostics_data(ty
.into(), None
);
843 let mut err
= struct_span_err
!(
847 "type inside {} must be known in this context",
850 err
.span_label(span
, data
.cannot_infer_msg(None
));