@@ -17,7 +17,8 @@ use rustc::traits::ObligationCause;
17
17
use syntax:: ast;
18
18
use syntax_pos:: { self , Span } ;
19
19
use rustc:: hir;
20
- use rustc:: ty:: { self , ImplOrTraitItem } ;
20
+ use rustc:: hir:: def:: Def ;
21
+ use rustc:: ty:: { self , AssociatedItem } ;
21
22
22
23
use super :: method:: probe;
23
24
@@ -31,11 +32,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
31
32
self . register_predicates ( obligations) ;
32
33
} ,
33
34
Err ( e) => {
34
- <<<<<<< HEAD
35
- self. report_mismatched_types( & cause , expected , actual , e ) ;
36
- =======
37
- self . report_mismatched_types ( origin , expected , actual , e ) . emit ( ) ;
38
- >>>>>>> Return DiagnosticBuilder to add help suggestions
35
+ self . report_mismatched_types ( & cause, expected, actual, e) . emit ( ) ;
39
36
}
40
37
}
41
38
}
@@ -59,128 +56,47 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
59
56
}
60
57
}
61
58
62
- /// This function is used to determine potential "simple" improvements or users' errors and
63
- /// provide them useful help. For example:
64
- ///
65
- /// ```
66
- /// fn some_fn(s: &str) {}
67
- ///
68
- /// let x = "hey!".to_owned();
69
- /// some_fn(x); // error
70
- /// ```
71
- ///
72
- /// No need to find every potential function which could make a coercion to transform a
73
- /// `String` into a `&str` since a `&` would do the trick!
74
- ///
75
- /// In addition of this check, it also checks between references mutability state. If the
76
- /// expected is mutable but the provided isn't, maybe we could just say "Hey, try with
77
- /// `&mut`!".
78
- fn check_ref ( & self ,
79
- expr : & hir:: Expr ,
80
- checked_ty : Ty < ' tcx > ,
81
- expected : Ty < ' tcx > )
82
- -> Option < String > {
83
- match ( & expected. sty , & checked_ty. sty ) {
84
- ( & ty:: TyRef ( _, expected_mutability) ,
85
- & ty:: TyRef ( _, checked_mutability) ) => {
86
- // check if there is a mutability difference
87
- if checked_mutability. mutbl == hir:: Mutability :: MutImmutable &&
88
- checked_mutability. mutbl != expected_mutability. mutbl &&
89
- self . can_sub_types ( & checked_mutability. ty ,
90
- expected_mutability. ty ) . is_ok ( ) {
91
- if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
92
- return Some ( format ! ( "try with `&mut {}`" , & src. replace( "&" , "" ) ) ) ;
93
- }
94
- }
95
- None
96
- }
97
- ( & ty:: TyRef ( _, mutability) , _) => {
98
- // Check if it can work when put into a ref. For example:
99
- //
100
- // ```
101
- // fn bar(x: &mut i32) {}
102
- //
103
- // let x = 0u32;
104
- // bar(&x); // error, expected &mut
105
- // ```
106
- let ref_ty = match mutability. mutbl {
107
- hir:: Mutability :: MutMutable => self . tcx . mk_mut_ref (
108
- self . tcx . mk_region ( ty:: ReStatic ) ,
109
- checked_ty) ,
110
- hir:: Mutability :: MutImmutable => self . tcx . mk_imm_ref (
111
- self . tcx . mk_region ( ty:: ReStatic ) ,
112
- checked_ty) ,
113
- } ;
114
- if self . try_coerce ( expr, ref_ty, expected) . is_ok ( ) {
115
- if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
116
- return Some ( format ! ( "try with `{}{}`" ,
117
- match mutability. mutbl {
118
- hir:: Mutability :: MutMutable => "&mut " ,
119
- hir:: Mutability :: MutImmutable => "&" ,
120
- } ,
121
- & src) ) ;
122
- }
123
- }
124
- None
125
- }
126
- _ => None ,
127
- }
128
- }
129
-
130
59
// Checks that the type of `expr` can be coerced to `expected`.
131
60
pub fn demand_coerce ( & self , expr : & hir:: Expr , checked_ty : Ty < ' tcx > , expected : Ty < ' tcx > ) {
132
61
let expected = self . resolve_type_vars_with_obligations ( expected) ;
133
62
if let Err ( e) = self . try_coerce ( expr, checked_ty, expected) {
134
63
let cause = self . misc ( expr. span ) ;
135
64
let expr_ty = self . resolve_type_vars_with_obligations ( checked_ty) ;
136
65
let mode = probe:: Mode :: MethodCall ;
137
- let suggestions = if let Some ( s) = self . check_ref ( expr, checked_ty, expected) {
138
- Some ( s)
139
- } else {
140
- let suggestions = self . probe_for_return_type ( syntax_pos:: DUMMY_SP ,
141
- mode,
142
- expected,
143
- checked_ty,
144
- ast:: DUMMY_NODE_ID ) ;
145
- if suggestions. len ( ) > 0 {
146
- Some ( format ! ( "here are some functions which \
147
- might fulfill your needs:\n - {}",
148
- self . get_best_match( & suggestions) ) )
149
- } else {
150
- None
151
- }
66
+ let suggestions = self . probe_for_return_type ( syntax_pos:: DUMMY_SP ,
67
+ mode,
68
+ expected,
69
+ checked_ty,
70
+ ast:: DUMMY_NODE_ID ) ;
71
+ let mut err = self . report_mismatched_types ( & cause, expected, expr_ty, e) ;
72
+ if suggestions. len ( ) > 0 {
73
+ err. help ( & format ! ( "here are some functions which \
74
+ might fulfill your needs:\n - {}",
75
+ self . get_best_match( & suggestions) ) ) ;
152
76
} ;
153
- let mut err = self . report_mismatched_types ( origin, expected, expr_ty, e) ;
154
- if let Some ( suggestions) = suggestions {
155
- err. help ( & suggestions) ;
156
- }
157
- <<<<<<< HEAD
158
- self. report_mismatched_types( & cause , expected , expr_ty , e ) ;
159
- =======
160
77
err. emit ( ) ;
161
- >>>>>>> Return DiagnosticBuilder to add help suggestions
162
78
}
163
79
}
164
80
165
- fn format_method_suggestion ( & self , method : & ImplOrTraitItem < ' tcx > ) -> String {
81
+ fn format_method_suggestion ( & self , method : & AssociatedItem ) -> String {
166
82
format ! ( ".{}({})" ,
167
- method. name( ) ,
83
+ method. name,
168
84
if self . has_not_input_arg( method) {
169
85
""
170
86
} else {
171
87
"..."
172
88
} )
173
89
}
174
90
175
- fn display_suggested_methods ( & self , methods : & [ ImplOrTraitItem < ' tcx > ] ) -> String {
91
+ fn display_suggested_methods ( & self , methods : & [ AssociatedItem ] ) -> String {
176
92
methods. iter ( )
177
93
. take ( 5 )
178
94
. map ( |method| self . format_method_suggestion ( & * method) )
179
95
. collect :: < Vec < String > > ( )
180
96
. join ( "\n - " )
181
97
}
182
98
183
- fn get_best_match ( & self , methods : & [ ImplOrTraitItem < ' tcx > ] ) -> String {
99
+ fn get_best_match ( & self , methods : & [ AssociatedItem ] ) -> String {
184
100
let no_argument_methods: Vec < _ > =
185
101
methods. iter ( )
186
102
. filter ( |ref x| self . has_not_input_arg ( & * x) )
@@ -194,10 +110,15 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
194
110
}
195
111
196
112
// This function checks if the method isn't static and takes other arguments than `self`.
197
- fn has_not_input_arg ( & self , method : & ImplOrTraitItem < ' tcx > ) -> bool {
198
- match * method {
199
- ImplOrTraitItem : : MethodTraitItem ( ref x) => {
200
- x. fty. sig. skip_binder( ) . inputs. len( ) == 1
113
+ fn has_not_input_arg ( & self , method : & AssociatedItem ) -> bool {
114
+ match method. def ( ) {
115
+ Def :: Method ( def_id) => {
116
+ match self . tcx . item_type ( def_id) . sty {
117
+ ty:: TypeVariants :: TyFnDef ( _, _, fty) => {
118
+ fty. sig . skip_binder ( ) . inputs . len ( ) == 1
119
+ }
120
+ _ => false ,
121
+ }
201
122
}
202
123
_ => false ,
203
124
}
0 commit comments