@@ -37,6 +37,42 @@ use std::cmp::Ordering;
37
37
use super :: { MethodError , NoMatchData , CandidateSource , impl_item, trait_item} ;
38
38
use super :: probe:: Mode ;
39
39
40
+ fn is_fn_ty < ' a , ' tcx > ( ty : & Ty < ' tcx > , fcx : & FnCtxt < ' a , ' tcx > , span : Span ) -> bool {
41
+ let cx = fcx. tcx ( ) ;
42
+ println ! ( "{:?}" , ty) ;
43
+ match ty. sty {
44
+ // Not all of these (e.g. unsafe fns) implement FnOnce
45
+ // so we look for these beforehand
46
+ ty:: TyClosure ( ..) | ty:: TyFnDef ( ..) | ty:: TyFnPtr ( _) => true ,
47
+ // If it's not a simple function, look for things which implement FnOnce
48
+ _ => {
49
+ if let Ok ( fn_once_trait_did) =
50
+ cx. lang_items . require ( FnOnceTraitLangItem ) {
51
+ let infcx = fcx. infcx ( ) ;
52
+ infcx. probe ( |_| {
53
+ let fn_once_substs =
54
+ Substs :: new_trait ( vec ! [ infcx. next_ty_var( ) ] ,
55
+ Vec :: new ( ) ,
56
+ ty) ;
57
+ let trait_ref =
58
+ ty:: TraitRef :: new ( fn_once_trait_did,
59
+ cx. mk_substs ( fn_once_substs) ) ;
60
+ let poly_trait_ref = trait_ref. to_poly_trait_ref ( ) ;
61
+ let obligation = Obligation :: misc ( span,
62
+ fcx. body_id ,
63
+ poly_trait_ref
64
+ . to_predicate ( ) ) ;
65
+ let mut selcx = SelectionContext :: new ( infcx) ;
66
+
67
+ return selcx. evaluate_obligation ( & obligation)
68
+ } )
69
+ } else {
70
+ false
71
+ }
72
+ }
73
+ }
74
+ }
75
+
40
76
pub fn report_error < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
41
77
span : Span ,
42
78
rcvr_ty : Ty < ' tcx > ,
@@ -79,65 +115,35 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
79
115
// snippet
80
116
} ;
81
117
82
- macro_rules! span_stored_function {
83
- ( ) => {
84
- err. span_note( span,
85
- & format!( "use `({0}.{1})(...)` if you meant to call \
86
- the function stored in the `{1}` field",
87
- expr_string, item_name) ) ;
88
- }
89
- }
90
-
91
- macro_rules! span_did_you_mean {
92
- ( ) => {
93
- err. span_note( span, & format!( "did you mean to write `{0}.{1}`?" ,
94
- expr_string, item_name) ) ;
95
- }
96
- }
97
-
98
- // Determine if the field can be used as a function in some way
99
118
let field_ty = field. ty ( cx, substs) ;
100
119
101
- match field_ty. sty {
102
- // Not all of these (e.g. unsafe fns) implement FnOnce
103
- // so we look for these beforehand
104
- ty:: TyClosure ( ..) | ty:: TyFnDef ( ..) | ty:: TyFnPtr ( _) => {
105
- span_stored_function ! ( ) ;
106
- }
107
- // If it's not a simple function, look for things which implement FnOnce
108
- _ => {
109
- if let Ok ( fn_once_trait_did) =
110
- cx. lang_items . require ( FnOnceTraitLangItem ) {
111
- let infcx = fcx. infcx ( ) ;
112
- infcx. probe ( |_| {
113
- let fn_once_substs =
114
- Substs :: new_trait ( vec ! [ infcx. next_ty_var( ) ] ,
115
- Vec :: new ( ) ,
116
- field_ty) ;
117
- let trait_ref =
118
- ty:: TraitRef :: new ( fn_once_trait_did,
119
- cx. mk_substs ( fn_once_substs) ) ;
120
- let poly_trait_ref = trait_ref. to_poly_trait_ref ( ) ;
121
- let obligation = Obligation :: misc ( span,
122
- fcx. body_id ,
123
- poly_trait_ref
124
- . to_predicate ( ) ) ;
125
- let mut selcx = SelectionContext :: new ( infcx) ;
126
-
127
- if selcx. evaluate_obligation ( & obligation) {
128
- span_stored_function ! ( ) ;
129
- } else {
130
- span_did_you_mean ! ( ) ;
131
- }
132
- } ) ;
133
- } else {
134
- span_did_you_mean ! ( ) ;
135
- }
136
- }
120
+ if is_fn_ty ( & field_ty, & fcx, span) {
121
+ err. span_note ( span,
122
+ & format ! ( "use `({0}.{1})(...)` if you meant to call \
123
+ the function stored in the `{1}` field",
124
+ expr_string, item_name) ) ;
125
+ } else {
126
+ err. span_note ( span, & format ! ( "did you mean to write `{0}.{1}`?" ,
127
+ expr_string, item_name) ) ;
137
128
}
138
129
}
139
130
}
140
131
132
+ if is_fn_ty ( & rcvr_ty, & fcx, span) {
133
+ let expr_string = match rcvr_expr {
134
+ Some ( expr) => match cx. sess . codemap ( ) . span_to_snippet ( expr. span ) {
135
+ Ok ( expr_string) => expr_string,
136
+ _ => "s" . into ( )
137
+ } ,
138
+ _ => "s" . into ( )
139
+ } ;
140
+ err. fileline_note (
141
+ span,
142
+ & format ! ( "method invoked on function type. did you \
143
+ mean `{}().{}(...)`?",
144
+ expr_string, item_name) ) ;
145
+ }
146
+
141
147
if !static_sources. is_empty ( ) {
142
148
err. fileline_note (
143
149
span,
0 commit comments