@@ -15,8 +15,11 @@ use CrateCtxt;
15
15
16
16
use astconv:: AstConv ;
17
17
use check:: { self , FnCtxt } ;
18
- use middle:: ty:: { self , Ty } ;
18
+ use middle:: ty:: { self , Ty , ToPolyTraitRef , AsPredicate } ;
19
19
use middle:: def;
20
+ use middle:: lang_items:: FnOnceTraitLangItem ;
21
+ use middle:: subst:: Substs ;
22
+ use middle:: traits:: { Obligation , SelectionContext } ;
20
23
use metadata:: { csearch, cstore, decoder} ;
21
24
22
25
use syntax:: { ast, ast_util} ;
@@ -65,31 +68,38 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
65
68
if let Some ( field) = fields. iter ( ) . find ( |f| f. name == item_name) {
66
69
let expr_string = match cx. sess . codemap ( ) . span_to_snippet ( expr. span ) {
67
70
Ok ( expr_string) => expr_string,
68
- _ => "s" . into ( ) // default to generic placeholder for expression
71
+ _ => "s" . into ( ) // Default to a generic placeholder for the
72
+ // expression when we can't generate a string
73
+ // snippet
69
74
} ;
70
75
71
- // TODO Fix when closure note is displayed
72
- // below commented code from eddyb on irc
73
- // let substs = subst::Substs::new_trait(vec![fcx.inh.infcx.next_ty_var()], Vec::new(), field_ty);
74
- // let trait_ref = ty::TraitRef::new(trait_def_id, fcx.tcx().mk_substs(substs));
75
- // let poly_trait_ref = trait_ref.to_poly_trait_ref();
76
- // let obligation = traits::Obligation::misc(span, fcx.body_id, poly_trait_ref.as_predicate());
77
- // let mut selcx = traits::SelectionContext::new(fcx.infcx(), fcx);
78
- // if selcx.evaluate_obligation(&obligation) { /* suggest */ }
79
-
80
- match ty:: lookup_field_type ( cx, did, field. id , substs) . sty {
81
- ty:: TyClosure ( _, _) | ty:: TyBareFn ( _, _) => {
82
- cx. sess . span_note ( span,
83
- & format ! ( "use `({0}.{1})(...)` if you meant to call the \
84
- function stored in the `{1}` field",
85
- expr_string, item_name) ) ;
86
- } ,
87
- _ => {
88
- cx. sess . span_note ( span,
89
- & format ! ( "did you mean to write `{0}.{1}`?" ,
90
- expr_string, item_name) ) ;
91
- } ,
76
+ // Determine if the field can be used as a function in some way
77
+ let fn_once_trait_did = match cx. lang_items . require ( FnOnceTraitLangItem ) {
78
+ Ok ( trait_did) => trait_did,
79
+ Err ( err) => cx. sess . fatal ( & err[ ..] )
92
80
} ;
81
+
82
+ let field_ty = ty:: lookup_field_type ( cx, did, field. id , substs) ;
83
+ let field_ty_substs = Substs :: new_trait ( vec ! [ fcx. inh. infcx. next_ty_var( ) ] ,
84
+ Vec :: new ( ) ,
85
+ field_ty) ;
86
+ let trait_ref = ty:: TraitRef :: new ( fn_once_trait_did,
87
+ cx. mk_substs ( field_ty_substs) ) ;
88
+ let poly_trait_ref = trait_ref. to_poly_trait_ref ( ) ;
89
+ let obligation = Obligation :: misc ( span,
90
+ fcx. body_id ,
91
+ poly_trait_ref. as_predicate ( ) ) ;
92
+ let mut selcx = SelectionContext :: new ( fcx. infcx ( ) , fcx) ;
93
+
94
+ if selcx. evaluate_obligation ( & obligation) {
95
+ cx. sess . span_note ( span,
96
+ & format ! ( "use `({0}.{1})(...)` if you meant to call the \
97
+ function stored in the `{1}` field",
98
+ expr_string, item_name) ) ;
99
+ } else {
100
+ cx. sess . span_note ( span, & format ! ( "did you mean to write `{0}.{1}`?" ,
101
+ expr_string, item_name) ) ;
102
+ }
93
103
}
94
104
}
95
105
0 commit comments