@@ -6,7 +6,7 @@ use errors::{Applicability, DiagnosticBuilder};
6
6
use middle:: lang_items:: FnOnceTraitLangItem ;
7
7
use namespace:: Namespace ;
8
8
use rustc_data_structures:: sync:: Lrc ;
9
- use rustc:: hir:: { self , Node } ;
9
+ use rustc:: hir:: { self , ExprKind , Node , QPath } ;
10
10
use rustc:: hir:: def:: Def ;
11
11
use rustc:: hir:: def_id:: { CRATE_DEF_INDEX , LOCAL_CRATE , DefId } ;
12
12
use rustc:: hir:: map as hir_map;
@@ -60,13 +60,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
60
60
}
61
61
}
62
62
63
- pub fn report_method_error ( & self ,
64
- span : Span ,
65
- rcvr_ty : Ty < ' tcx > ,
66
- item_name : ast:: Ident ,
67
- rcvr_expr : Option < & hir :: Expr > ,
68
- error : MethodError < ' tcx > ,
69
- args : Option < & ' gcx [ hir:: Expr ] > ) {
63
+ pub fn report_method_error < ' b > ( & self ,
64
+ span : Span ,
65
+ rcvr_ty : Ty < ' tcx > ,
66
+ item_name : ast:: Ident ,
67
+ source : SelfSource < ' b > ,
68
+ error : MethodError < ' tcx > ,
69
+ args : Option < & ' gcx [ hir:: Expr ] > ) {
70
70
// Avoid suggestions when we don't know what's going on.
71
71
if rcvr_ty. references_error ( ) {
72
72
return ;
@@ -212,10 +212,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
212
212
. filter_map ( |info|
213
213
self . associated_item ( info. def_id , item_name, Namespace :: Value )
214
214
) ;
215
- if let ( true , false , Some ( expr) , Some ( _) ) = ( actual. is_numeric ( ) ,
216
- actual. has_concrete_skeleton ( ) ,
217
- rcvr_expr,
218
- candidates. next ( ) ) {
215
+ if let ( true , false , SelfSource :: MethodCall ( expr) , Some ( _) ) =
216
+ ( actual. is_numeric ( ) ,
217
+ actual. has_concrete_skeleton ( ) ,
218
+ source,
219
+ candidates. next ( ) ) {
219
220
let mut err = struct_span_err ! (
220
221
tcx. sess,
221
222
span,
@@ -231,7 +232,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
231
232
"f32"
232
233
} ;
233
234
match expr. node {
234
- hir :: ExprKind :: Lit ( ref lit) => {
235
+ ExprKind :: Lit ( ref lit) => {
235
236
// numeric literal
236
237
let snippet = tcx. sess . source_map ( ) . span_to_snippet ( lit. span )
237
238
. unwrap_or_else ( |_| "<numeric literal>" . to_owned ( ) ) ;
@@ -247,9 +248,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
247
248
Applicability :: MaybeIncorrect ,
248
249
) ;
249
250
}
250
- hir :: ExprKind :: Path ( ref qpath) => {
251
+ ExprKind :: Path ( ref qpath) => {
251
252
// local binding
252
- if let & hir :: QPath :: Resolved ( _, ref path) = & qpath {
253
+ if let & QPath :: Resolved ( _, ref path) = & qpath {
253
254
if let hir:: def:: Def :: Local ( node_id) = path. def {
254
255
let span = tcx. hir ( ) . span ( node_id) ;
255
256
let snippet = tcx. sess . source_map ( ) . span_to_snippet ( span)
@@ -294,15 +295,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
294
295
} else {
295
296
let mut err = struct_span_err ! (
296
297
tcx. sess,
297
- span,
298
+ item_name . span,
298
299
E0599 ,
299
300
"no {} named `{}` found for type `{}` in the current scope" ,
300
301
item_kind,
301
302
item_name,
302
303
ty_str
303
304
) ;
304
305
if let Some ( suggestion) = suggestion {
305
- err. note ( & format ! ( "did you mean `{}::{}`?" , ty_str, suggestion) ) ;
306
+ // enum variant
307
+ err. help ( & format ! ( "did you mean `{}`?" , suggestion) ) ;
306
308
}
307
309
err
308
310
}
@@ -326,7 +328,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
326
328
327
329
// If the method name is the name of a field with a function or closure type,
328
330
// give a helping note that it has to be called as `(x.f)(...)`.
329
- if let Some ( expr) = rcvr_expr {
331
+ if let SelfSource :: MethodCall ( expr) = source {
330
332
for ( ty, _) in self . autoderef ( span, rcvr_ty) {
331
333
if let ty:: Adt ( def, substs) = ty. sty {
332
334
if !def. is_enum ( ) {
@@ -377,10 +379,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
377
379
}
378
380
}
379
381
380
- if let Some ( expr) = rcvr_expr {
382
+ if let SelfSource :: MethodCall ( expr) = source {
381
383
if let Ok ( expr_string) = tcx. sess . source_map ( ) . span_to_snippet ( expr. span ) {
382
384
report_function ! ( expr. span, expr_string) ;
383
- } else if let hir :: ExprKind :: Path ( hir :: QPath :: Resolved ( _, ref path) ) =
385
+ } else if let ExprKind :: Path ( QPath :: Resolved ( _, ref path) ) =
384
386
expr. node
385
387
{
386
388
if let Some ( segment) = path. segments . last ( ) {
@@ -396,7 +398,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
396
398
err. span_label ( span, "this is an associated function, not a method" ) ;
397
399
}
398
400
if static_sources. len ( ) == 1 {
399
- if let Some ( expr) = rcvr_expr {
401
+ if let SelfSource :: MethodCall ( expr) = source {
400
402
err. span_suggestion_with_applicability ( expr. span . to ( span) ,
401
403
"use associated function syntax instead" ,
402
404
format ! ( "{}::{}" ,
@@ -433,7 +435,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
433
435
span,
434
436
rcvr_ty,
435
437
item_name,
436
- rcvr_expr ,
438
+ source ,
437
439
out_of_scope_traits) ;
438
440
}
439
441
@@ -571,18 +573,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
571
573
}
572
574
}
573
575
574
- fn suggest_traits_to_import ( & self ,
575
- err : & mut DiagnosticBuilder ,
576
- span : Span ,
577
- rcvr_ty : Ty < ' tcx > ,
578
- item_name : ast:: Ident ,
579
- rcvr_expr : Option < & hir :: Expr > ,
580
- valid_out_of_scope_traits : Vec < DefId > ) {
576
+ fn suggest_traits_to_import < ' b > ( & self ,
577
+ err : & mut DiagnosticBuilder ,
578
+ span : Span ,
579
+ rcvr_ty : Ty < ' tcx > ,
580
+ item_name : ast:: Ident ,
581
+ source : SelfSource < ' b > ,
582
+ valid_out_of_scope_traits : Vec < DefId > ) {
581
583
if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
582
584
return ;
583
585
}
584
586
585
- let type_is_local = self . type_derefs_to_local ( span, rcvr_ty, rcvr_expr ) ;
587
+ let type_is_local = self . type_derefs_to_local ( span, rcvr_ty, source ) ;
586
588
587
589
// There are no traits implemented, so lets suggest some traits to
588
590
// implement, by finding ones that have the item name, and are
@@ -663,14 +665,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
663
665
664
666
// This occurs for UFCS desugaring of `T::method`, where there is no
665
667
// receiver expression for the method call, and thus no autoderef.
666
- if rcvr_expr . is_none ( ) {
668
+ if let SelfSource :: QPath ( _ ) = source {
667
669
return is_local ( self . resolve_type_vars_with_obligations ( rcvr_ty) ) ;
668
670
}
669
671
670
672
self . autoderef ( span, rcvr_ty) . any ( |( ty, _) | is_local ( ty) )
671
673
}
672
674
}
673
675
676
+ #[ derive( Copy , Clone ) ]
677
+ pub enum SelfSource < ' a > {
678
+ QPath ( & ' a hir:: Ty ) ,
679
+ MethodCall ( & ' a hir:: Expr /* rcvr */ ) ,
680
+ }
681
+
674
682
#[ derive( Copy , Clone ) ]
675
683
pub struct TraitInfo {
676
684
pub def_id : DefId ,
0 commit comments