@@ -20,7 +20,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
2020 found_arg_pattern : Option < & ' tcx Pat > ,
2121 found_ty : Option < Ty < ' tcx > > ,
2222 found_closure : Option < & ' tcx ExprKind > ,
23- found_method_call : Option < & ' tcx ExprKind > ,
23+ found_method_call : Option < & ' tcx Expr > ,
2424}
2525
2626impl < ' a , ' tcx > FindLocalByTypeVisitor < ' a , ' tcx > {
@@ -99,7 +99,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
9999 if self . node_matches_type ( expr. hir_id ) . is_some ( ) {
100100 match expr. kind {
101101 ExprKind :: Closure ( ..) => self . found_closure = Some ( & expr. kind ) ,
102- ExprKind :: MethodCall ( ..) => self . found_method_call = Some ( & expr. kind ) ,
102+ ExprKind :: MethodCall ( ..) => self . found_method_call = Some ( & expr) ,
103103 _ => { }
104104 }
105105 }
@@ -211,8 +211,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
211211 let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
212212 let ty_vars = self . type_variables . borrow ( ) ;
213213 let getter = move |ty_vid| {
214- if let TypeVariableOriginKind :: TypeParameterDefinition ( name ) =
215- ty_vars . var_origin ( ty_vid ) . kind {
214+ let var_origin = ty_vars . var_origin ( ty_vid ) ;
215+ if let TypeVariableOriginKind :: TypeParameterDefinition ( name ) = var_origin. kind {
216216 return Some ( name. to_string ( ) ) ;
217217 }
218218 None
@@ -238,7 +238,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
238238 span
239239 } else if let Some (
240240 ExprKind :: MethodCall ( _, call_span, _) ,
241- ) = local_visitor. found_method_call {
241+ ) = local_visitor. found_method_call . map ( |e| & e . kind ) {
242242 // Point at the call instead of the whole expression:
243243 // error[E0284]: type annotations needed
244244 // --> file.rs:2:5
@@ -375,16 +375,48 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
375375 format ! ( "consider giving this pattern {}" , suffix)
376376 } ;
377377 err. span_label ( pattern. span , msg) ;
378- } else if let Some ( ExprKind :: MethodCall ( segment, ..) ) = local_visitor. found_method_call {
379- if let Ok ( snippet) = self . tcx . sess . source_map ( ) . span_to_snippet ( segment. ident . span ) {
380- if segment. args . is_none ( ) {
381- err. span_suggestion (
382- segment. ident . span ,
383- "consider specifying the type argument in the method call" ,
384- // FIXME: we don't know how many type arguments should be set here.
385- format ! ( "{}::<_>" , snippet) ,
386- Applicability :: HasPlaceholders ,
387- ) ;
378+ } else if let Some ( e) = local_visitor. found_method_call {
379+ if let ExprKind :: MethodCall ( segment, _call_sp, _args) = & e. kind {
380+ if let ( Ok ( snippet) , Some ( tables) , None ) = (
381+ self . tcx . sess . source_map ( ) . span_to_snippet ( segment. ident . span ) ,
382+ self . in_progress_tables ,
383+ & segment. args ,
384+ ) {
385+ let borrow = tables. borrow ( ) ;
386+ let sigs = borrow. node_method_sig ( ) ;
387+ if let Some ( sig) = sigs. get ( e. hir_id ) {
388+ let mut params = vec ! [ ] ;
389+ for arg in sig. inputs_and_output ( ) . skip_binder ( ) . iter ( ) {
390+ if let ty:: Param ( param) = arg. kind {
391+ if param. name != kw:: SelfUpper {
392+ let name = param. name . to_string ( ) ;
393+ if !params. contains ( & name) {
394+ params. push ( name) ;
395+ }
396+ }
397+ }
398+ }
399+ if !params. is_empty ( ) {
400+ err. span_suggestion (
401+ segment. ident . span ,
402+ & format ! (
403+ "consider specifying the type argument{} in the method call" ,
404+ if params. len( ) > 1 {
405+ "s"
406+ } else {
407+ ""
408+ } ,
409+ ) ,
410+ format ! ( "{}::<{}>" , snippet, params. join( ", " ) ) ,
411+ Applicability :: HasPlaceholders ,
412+ ) ;
413+ } else {
414+ err. span_label ( e. span , & format ! (
415+ "this method call resolves to `{:?}`" ,
416+ sig. output( ) . skip_binder( ) ,
417+ ) ) ;
418+ }
419+ }
388420 }
389421 }
390422 }
0 commit comments