@@ -17,23 +17,27 @@ use std::borrow::Cow;
1717struct FindHirNodeVisitor < ' a , ' tcx > {
1818 infcx : & ' a InferCtxt < ' a , ' tcx > ,
1919 target : GenericArg < ' tcx > ,
20+ target_span : Span ,
2021 found_node_ty : Option < Ty < ' tcx > > ,
2122 found_local_pattern : Option < & ' tcx Pat < ' tcx > > ,
2223 found_arg_pattern : Option < & ' tcx Pat < ' tcx > > ,
2324 found_closure : Option < & ' tcx Expr < ' tcx > > ,
2425 found_method_call : Option < & ' tcx Expr < ' tcx > > ,
26+ found_exact_method_call : Option < & ' tcx Expr < ' tcx > > ,
2527}
2628
2729impl < ' 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 {
2931 Self {
3032 infcx,
3133 target,
34+ target_span,
3235 found_node_ty : None ,
3336 found_local_pattern : None ,
3437 found_arg_pattern : None ,
3538 found_closure : None ,
3639 found_method_call : None ,
40+ found_exact_method_call : None ,
3741 }
3842 }
3943
@@ -103,6 +107,17 @@ impl<'a, 'tcx> Visitor<'tcx> for FindHirNodeVisitor<'a, 'tcx> {
103107 }
104108
105109 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+ }
106121 if self . node_ty_contains_target ( expr. hir_id ) . is_some ( ) {
107122 match expr. kind {
108123 ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr) ,
@@ -234,7 +249,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
234249 let ty = self . resolve_vars_if_possible ( & ty) ;
235250 let ( name, name_sp, descr, parent_name, parent_descr) = self . extract_type_name ( & ty, None ) ;
236251
237- let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty. into ( ) ) ;
252+ let mut local_visitor = FindHirNodeVisitor :: new ( & self , ty. into ( ) , span ) ;
238253 let ty_to_string = |ty : Ty < ' tcx > | -> String {
239254 let mut s = String :: new ( ) ;
240255 let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
@@ -287,14 +302,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
287302 ( !ty. is_impl_trait ( ) || self . tcx . features ( ) . impl_trait_in_bindings )
288303 } ;
289304
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) , .. } ) , _) => {
292308 let fn_sig = substs. as_closure ( ) . sig ( ) ;
293309 let args = closure_args ( & fn_sig) ;
294310 let ret = fn_sig. output ( ) . skip_binder ( ) . to_string ( ) ;
295311 format ! ( " for the closure `fn({}) -> {}`" , args, ret)
296312 }
297- Some ( ty) if is_named_and_not_impl_trait ( ty) => {
313+ ( Some ( ty) , _ ) if is_named_and_not_impl_trait ( ty) => {
298314 let ty = ty_to_string ( ty) ;
299315 format ! ( " for `{}`" , ty)
300316 }
@@ -370,7 +386,37 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
370386 _ => "a type" . to_string ( ) ,
371387 } ;
372388
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 {
374420 // We don't want to show the default label for closures.
375421 //
376422 // So, before clearing, the output would look something like this:
0 commit comments