@@ -17,23 +17,27 @@ use std::borrow::Cow;
17
17
struct FindHirNodeVisitor < ' a , ' tcx > {
18
18
infcx : & ' a InferCtxt < ' a , ' tcx > ,
19
19
target : GenericArg < ' tcx > ,
20
+ target_span : Span ,
20
21
found_node_ty : Option < Ty < ' tcx > > ,
21
22
found_local_pattern : Option < & ' tcx Pat < ' tcx > > ,
22
23
found_arg_pattern : Option < & ' tcx Pat < ' tcx > > ,
23
24
found_closure : Option < & ' tcx Expr < ' tcx > > ,
24
25
found_method_call : Option < & ' tcx Expr < ' tcx > > ,
26
+ found_exact_method_call : Option < & ' tcx Expr < ' tcx > > ,
25
27
}
26
28
27
29
impl < ' a , ' tcx > FindHirNodeVisitor < ' a , ' tcx > {
28
- fn new ( infcx : & ' a InferCtxt < ' a , ' tcx > , target : GenericArg < ' tcx > ) -> Self {
30
+ fn new ( infcx : & ' a InferCtxt < ' a , ' tcx > , target : GenericArg < ' tcx > , target_span : Span ) -> Self {
29
31
Self {
30
32
infcx,
31
33
target,
34
+ target_span,
32
35
found_node_ty : None ,
33
36
found_local_pattern : None ,
34
37
found_arg_pattern : None ,
35
38
found_closure : None ,
36
39
found_method_call : None ,
40
+ found_exact_method_call : None ,
37
41
}
38
42
}
39
43
@@ -103,6 +107,17 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
103
107
}
104
108
105
109
fn visit_expr ( & mut self , expr : & ' tcx Expr < ' tcx > ) {
110
+ if let ExprKind :: MethodCall ( _, call_span, exprs) = expr. kind {
111
+ if call_span == self . target_span
112
+ && Some ( self . target )
113
+ == self . infcx . in_progress_tables . and_then ( |tables| {
114
+ tables. borrow ( ) . node_type_opt ( exprs. first ( ) . unwrap ( ) . hir_id ) . map ( Into :: into)
115
+ } )
116
+ {
117
+ self . found_exact_method_call = Some ( & expr) ;
118
+ return ;
119
+ }
120
+ }
106
121
if self . node_ty_contains_target ( expr. hir_id ) . is_some ( ) {
107
122
match expr. kind {
108
123
ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr) ,
@@ -234,7 +249,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
234
249
let ty = self . resolve_vars_if_possible ( & ty) ;
235
250
let ( name, name_sp, descr, parent_name, parent_descr) = self . extract_type_name ( & ty, None ) ;
236
251
237
- let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty. into ( ) ) ;
252
+ let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty. into ( ) , span ) ;
238
253
let ty_to_string = |ty : Ty < ' tcx > | -> String {
239
254
let mut s = String :: new ( ) ;
240
255
let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
@@ -287,14 +302,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
287
302
( !ty. is_impl_trait ( ) || self . tcx . features ( ) . impl_trait_in_bindings )
288
303
} ;
289
304
290
- let ty_msg = match local_visitor. found_node_ty {
291
- Some ( ty:: TyS { kind : ty:: Closure ( _, substs) , .. } ) => {
305
+ let ty_msg = match ( local_visitor. found_node_ty , local_visitor. found_exact_method_call ) {
306
+ ( _, Some ( _) ) => String :: new ( ) ,
307
+ ( Some ( ty:: TyS { kind : ty:: Closure ( _, substs) , .. } ) , _) => {
292
308
let fn_sig = substs. as_closure ( ) . sig ( ) ;
293
309
let args = closure_args ( & fn_sig) ;
294
310
let ret = fn_sig. output ( ) . skip_binder ( ) . to_string ( ) ;
295
311
format ! ( " for the closure `fn({}) -> {}`" , args, ret)
296
312
}
297
- Some ( ty) if is_named_and_not_impl_trait ( ty) => {
313
+ ( Some ( ty) , _ ) if is_named_and_not_impl_trait ( ty) => {
298
314
let ty = ty_to_string ( ty) ;
299
315
format ! ( " for `{}`" , ty)
300
316
}
@@ -370,7 +386,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
370
386
_ => "a type" . to_string ( ) ,
371
387
} ;
372
388
373
- if let Some ( pattern) = local_visitor. found_arg_pattern {
389
+ if let Some ( e) = local_visitor. found_exact_method_call {
390
+ if let ExprKind :: MethodCall ( segment, ..) = & e. kind {
391
+ // Suggest specifying type params or point out the return type of the call:
392
+ //
393
+ // error[E0282]: type annotations needed
394
+ // --> $DIR/type-annotations-needed-expr.rs:2:39
395
+ // |
396
+ // LL | let _ = x.into_iter().sum() as f64;
397
+ // | ^^^
398
+ // | |
399
+ // | cannot infer type for `S`
400
+ // | help: consider specifying the type argument in
401
+ // | the method call: `sum::<S>`
402
+ // |
403
+ // = note: type must be known at this point
404
+ //
405
+ // or
406
+ //
407
+ // error[E0282]: type annotations needed
408
+ // --> $DIR/issue-65611.rs:59:20
409
+ // |
410
+ // LL | let x = buffer.last().unwrap().0.clone();
411
+ // | -------^^^^--
412
+ // | | |
413
+ // | | cannot infer type for `T`
414
+ // | this method call resolves to `std::option::Option<&T>`
415
+ // |
416
+ // = note: type must be known at this point
417
+ self . annotate_method_call ( segment, e, & mut err) ;
418
+ }
419
+ } else if let Some ( pattern) = local_visitor. found_arg_pattern {
374
420
// We don't want to show the default label for closures.
375
421
//
376
422
// So, before clearing, the output would look something like this:
0 commit comments