@@ -16,7 +16,7 @@ use errors::{Applicability, DiagnosticBuilder};
16
16
use middle:: lang_items:: FnOnceTraitLangItem ;
17
17
use namespace:: Namespace ;
18
18
use rustc_data_structures:: sync:: Lrc ;
19
- use rustc:: hir:: { self , Node } ;
19
+ use rustc:: hir:: { self , ExprKind , Node , QPath } ;
20
20
use rustc:: hir:: def:: Def ;
21
21
use rustc:: hir:: def_id:: { CRATE_DEF_INDEX , LOCAL_CRATE , DefId } ;
22
22
use rustc:: hir:: map as hir_map;
@@ -70,13 +70,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
70
70
}
71
71
}
72
72
73
- pub fn report_method_error ( & self ,
74
- span : Span ,
75
- rcvr_ty : Ty < ' tcx > ,
76
- item_name : ast:: Ident ,
77
- rcvr_expr : Option < & hir :: Expr > ,
78
- error : MethodError < ' tcx > ,
79
- args : Option < & ' gcx [ hir:: Expr ] > ) {
73
+ pub fn report_method_error < ' b > ( & self ,
74
+ span : Span ,
75
+ rcvr_ty : Ty < ' tcx > ,
76
+ item_name : ast:: Ident ,
77
+ source : SelfSource < ' b > ,
78
+ error : MethodError < ' tcx > ,
79
+ args : Option < & ' gcx [ hir:: Expr ] > ) {
80
80
// Avoid suggestions when we don't know what's going on.
81
81
if rcvr_ty. references_error ( ) {
82
82
return ;
@@ -222,10 +222,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
222
222
. filter_map ( |info|
223
223
self . associated_item ( info. def_id , item_name, Namespace :: Value )
224
224
) ;
225
- if let ( true , false , Some ( expr) , Some ( _) ) = ( actual. is_numeric ( ) ,
226
- actual. has_concrete_skeleton ( ) ,
227
- rcvr_expr,
228
- candidates. next ( ) ) {
225
+ if let ( true , false , SelfSource :: MethodCall ( expr) , Some ( _) ) =
226
+ ( actual. is_numeric ( ) ,
227
+ actual. has_concrete_skeleton ( ) ,
228
+ source,
229
+ candidates. next ( ) ) {
229
230
let mut err = struct_span_err ! (
230
231
tcx. sess,
231
232
span,
@@ -241,7 +242,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
241
242
"f32"
242
243
} ;
243
244
match expr. node {
244
- hir :: ExprKind :: Lit ( ref lit) => {
245
+ ExprKind :: Lit ( ref lit) => {
245
246
// numeric literal
246
247
let snippet = tcx. sess . source_map ( ) . span_to_snippet ( lit. span )
247
248
. unwrap_or_else ( |_| "<numeric literal>" . to_owned ( ) ) ;
@@ -257,9 +258,9 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
257
258
Applicability :: MaybeIncorrect ,
258
259
) ;
259
260
}
260
- hir :: ExprKind :: Path ( ref qpath) => {
261
+ ExprKind :: Path ( ref qpath) => {
261
262
// local binding
262
- if let & hir :: QPath :: Resolved ( _, ref path) = & qpath {
263
+ if let & QPath :: Resolved ( _, ref path) = & qpath {
263
264
if let hir:: def:: Def :: Local ( node_id) = path. def {
264
265
let span = tcx. hir ( ) . span ( node_id) ;
265
266
let snippet = tcx. sess . source_map ( ) . span_to_snippet ( span)
@@ -304,15 +305,16 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
304
305
} else {
305
306
let mut err = struct_span_err ! (
306
307
tcx. sess,
307
- span,
308
+ item_name . span,
308
309
E0599 ,
309
310
"no {} named `{}` found for type `{}` in the current scope" ,
310
311
item_kind,
311
312
item_name,
312
313
ty_str
313
314
) ;
314
315
if let Some ( suggestion) = suggestion {
315
- err. note ( & format ! ( "did you mean `{}::{}`?" , ty_str, suggestion) ) ;
316
+ // enum variant
317
+ err. help ( & format ! ( "did you mean `{}`?" , suggestion) ) ;
316
318
}
317
319
err
318
320
}
@@ -336,7 +338,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
336
338
337
339
// If the method name is the name of a field with a function or closure type,
338
340
// give a helping note that it has to be called as `(x.f)(...)`.
339
- if let Some ( expr) = rcvr_expr {
341
+ if let SelfSource :: MethodCall ( expr) = source {
340
342
for ( ty, _) in self . autoderef ( span, rcvr_ty) {
341
343
if let ty:: Adt ( def, substs) = ty. sty {
342
344
if !def. is_enum ( ) {
@@ -387,10 +389,10 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
387
389
}
388
390
}
389
391
390
- if let Some ( expr) = rcvr_expr {
392
+ if let SelfSource :: MethodCall ( expr) = source {
391
393
if let Ok ( expr_string) = tcx. sess . source_map ( ) . span_to_snippet ( expr. span ) {
392
394
report_function ! ( expr. span, expr_string) ;
393
- } else if let hir :: ExprKind :: Path ( hir :: QPath :: Resolved ( _, ref path) ) =
395
+ } else if let ExprKind :: Path ( QPath :: Resolved ( _, ref path) ) =
394
396
expr. node
395
397
{
396
398
if let Some ( segment) = path. segments . last ( ) {
@@ -406,7 +408,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
406
408
err. span_label ( span, "this is an associated function, not a method" ) ;
407
409
}
408
410
if static_sources. len ( ) == 1 {
409
- if let Some ( expr) = rcvr_expr {
411
+ if let SelfSource :: MethodCall ( expr) = source {
410
412
err. span_suggestion_with_applicability ( expr. span . to ( span) ,
411
413
"use associated function syntax instead" ,
412
414
format ! ( "{}::{}" ,
@@ -441,7 +443,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
441
443
span,
442
444
rcvr_ty,
443
445
item_name,
444
- rcvr_expr ,
446
+ source ,
445
447
out_of_scope_traits) ;
446
448
}
447
449
@@ -579,18 +581,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
579
581
}
580
582
}
581
583
582
- fn suggest_traits_to_import ( & self ,
583
- err : & mut DiagnosticBuilder ,
584
- span : Span ,
585
- rcvr_ty : Ty < ' tcx > ,
586
- item_name : ast:: Ident ,
587
- rcvr_expr : Option < & hir :: Expr > ,
588
- valid_out_of_scope_traits : Vec < DefId > ) {
584
+ fn suggest_traits_to_import < ' b > ( & self ,
585
+ err : & mut DiagnosticBuilder ,
586
+ span : Span ,
587
+ rcvr_ty : Ty < ' tcx > ,
588
+ item_name : ast:: Ident ,
589
+ source : SelfSource < ' b > ,
590
+ valid_out_of_scope_traits : Vec < DefId > ) {
589
591
if self . suggest_valid_traits ( err, valid_out_of_scope_traits) {
590
592
return ;
591
593
}
592
594
593
- let type_is_local = self . type_derefs_to_local ( span, rcvr_ty, rcvr_expr ) ;
595
+ let type_is_local = self . type_derefs_to_local ( span, rcvr_ty, source ) ;
594
596
595
597
// There are no traits implemented, so lets suggest some traits to
596
598
// implement, by finding ones that have the item name, and are
@@ -671,14 +673,20 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
671
673
672
674
// This occurs for UFCS desugaring of `T::method`, where there is no
673
675
// receiver expression for the method call, and thus no autoderef.
674
- if rcvr_expr . is_none ( ) {
676
+ if let SelfSource :: QPath ( _ ) = source {
675
677
return is_local ( self . resolve_type_vars_with_obligations ( rcvr_ty) ) ;
676
678
}
677
679
678
680
self . autoderef ( span, rcvr_ty) . any ( |( ty, _) | is_local ( ty) )
679
681
}
680
682
}
681
683
684
+ #[ derive( Copy , Clone ) ]
685
+ pub enum SelfSource < ' a > {
686
+ QPath ( & ' a hir:: Ty ) ,
687
+ MethodCall ( & ' a hir:: Expr /* rcvr */ ) ,
688
+ }
689
+
682
690
#[ derive( Copy , Clone ) ]
683
691
pub struct TraitInfo {
684
692
pub def_id : DefId ,
0 commit comments