@@ -20,7 +20,7 @@ struct FindLocalByTypeVisitor<'a, 'tcx> {
20
20
found_arg_pattern : Option < & ' tcx Pat > ,
21
21
found_ty : Option < Ty < ' tcx > > ,
22
22
found_closure : Option < & ' tcx ExprKind > ,
23
- found_method_call : Option < & ' tcx ExprKind > ,
23
+ found_method_call : Option < & ' tcx Expr > ,
24
24
}
25
25
26
26
impl < ' a , ' tcx > FindLocalByTypeVisitor < ' a , ' tcx > {
@@ -99,7 +99,7 @@ impl<'a, 'tcx> Visitor<'tcx> for FindLocalByTypeVisitor<'a, 'tcx> {
99
99
if self . node_matches_type ( expr. hir_id ) . is_some ( ) {
100
100
match expr. kind {
101
101
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) ,
103
103
_ => { }
104
104
}
105
105
}
@@ -211,8 +211,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
211
211
let mut printer = ty:: print:: FmtPrinter :: new ( self . tcx , & mut s, Namespace :: TypeNS ) ;
212
212
let ty_vars = self . type_variables . borrow ( ) ;
213
213
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 {
216
216
return Some ( name. to_string ( ) ) ;
217
217
}
218
218
None
@@ -238,7 +238,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
238
238
span
239
239
} else if let Some (
240
240
ExprKind :: MethodCall ( _, call_span, _) ,
241
- ) = local_visitor. found_method_call {
241
+ ) = local_visitor. found_method_call . map ( |e| & e . kind ) {
242
242
// Point at the call instead of the whole expression:
243
243
// error[E0284]: type annotations needed
244
244
// --> file.rs:2:5
@@ -375,16 +375,48 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
375
375
format ! ( "consider giving this pattern {}" , suffix)
376
376
} ;
377
377
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
+ }
388
420
}
389
421
}
390
422
}
0 commit comments