@@ -35,7 +35,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
35
35
error : MethodError )
36
36
{
37
37
match error {
38
- MethodError :: NoMatch ( static_sources) => {
38
+ MethodError :: NoMatch ( static_sources, out_of_scope_traits ) => {
39
39
let cx = fcx. tcx ( ) ;
40
40
let method_ustring = method_name. user_string ( cx) ;
41
41
@@ -75,7 +75,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
75
75
report_candidates ( fcx, span, method_name, static_sources) ;
76
76
}
77
77
78
- suggest_traits_to_import ( fcx, span, rcvr_ty, method_name)
78
+ suggest_traits_to_import ( fcx, span, rcvr_ty, method_name, out_of_scope_traits )
79
79
}
80
80
81
81
MethodError :: Ambiguity ( sources) => {
@@ -136,10 +136,35 @@ pub type AllTraitsVec = Vec<TraitInfo>;
136
136
fn suggest_traits_to_import < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
137
137
span : Span ,
138
138
_rcvr_ty : Ty < ' tcx > ,
139
- method_name : ast:: Name )
139
+ method_name : ast:: Name ,
140
+ valid_out_of_scope_traits : Vec < ast:: DefId > )
140
141
{
141
142
let tcx = fcx. tcx ( ) ;
143
+ let method_ustring = method_name. user_string ( tcx) ;
144
+
145
+ if !valid_out_of_scope_traits. is_empty ( ) {
146
+ let mut candidates = valid_out_of_scope_traits;
147
+ candidates. sort ( ) ;
148
+ let msg = format ! (
149
+ "methods from traits can only be called if the trait is in scope; \
150
+ the following {traits_are} implemented and {define} a method `{name}`:",
151
+ traits_are = if candidates. len( ) == 1 { "trait is" } else { "traits are" } ,
152
+ define = if candidates. len( ) == 1 { "defines" } else { "define" } ,
153
+ name = method_ustring) ;
154
+
155
+ fcx. sess ( ) . fileline_help ( span, & msg[ ] ) ;
156
+
157
+ for ( i, trait_did) in candidates. iter ( ) . enumerate ( ) {
158
+ fcx. sess ( ) . fileline_help ( span,
159
+ & * format ! ( "candidate #{}: `{}`" ,
160
+ i + 1 ,
161
+ ty:: item_path_str( fcx. tcx( ) , * trait_did) ) )
162
+
163
+ }
164
+ return
165
+ }
142
166
167
+ // there's no implemented traits, so lets suggest some traits to implement
143
168
let mut candidates = all_traits ( fcx. ccx )
144
169
. filter ( |info| trait_method ( tcx, info. def_id , method_name) . is_some ( ) )
145
170
. collect :: < Vec < _ > > ( ) ;
@@ -148,22 +173,16 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
148
173
// sort from most relevant to least relevant
149
174
candidates. sort_by ( |a, b| a. cmp ( b) . reverse ( ) ) ;
150
175
151
- let method_ustring = method_name. user_string ( tcx) ;
176
+ let msg = format ! (
177
+ "methods from traits can only be called if the trait is implemented and \
178
+ in scope; no such traits are but the following {traits_define} a method `{name}`:",
179
+ traits_define = if candidates. len( ) == 1 { "trait defines" } else { "traits define" } ,
180
+ name = method_ustring) ;
152
181
153
- span_help ! ( fcx. sess( ) , span,
154
- "methods from traits can only be called if the trait is implemented \
155
- and in scope; the following trait{s} define{inv_s} a method `{name}`:",
156
- s = if candidates. len( ) == 1 { "" } else { "s" } ,
157
- inv_s = if candidates. len( ) == 1 { "s" } else { "" } ,
158
- name = method_ustring) ;
182
+ fcx. sess ( ) . fileline_help ( span, & msg[ ] ) ;
159
183
160
184
for ( i, trait_info) in candidates. iter ( ) . enumerate ( ) {
161
- // provide a good-as-possible span; the span of
162
- // the trait if it is local, or the span of the
163
- // method call itself if not
164
- let trait_span = fcx. tcx ( ) . map . def_id_span ( trait_info. def_id , span) ;
165
-
166
- fcx. sess ( ) . fileline_help ( trait_span,
185
+ fcx. sess ( ) . fileline_help ( span,
167
186
& * format ! ( "candidate #{}: `{}`" ,
168
187
i + 1 ,
169
188
ty:: item_path_str( fcx. tcx( ) , trait_info. def_id) ) )
@@ -173,7 +192,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
173
192
174
193
#[ derive( Copy ) ]
175
194
pub struct TraitInfo {
176
- def_id : ast:: DefId ,
195
+ pub def_id : ast:: DefId ,
177
196
}
178
197
179
198
impl TraitInfo {
@@ -206,7 +225,7 @@ impl Ord for TraitInfo {
206
225
}
207
226
208
227
/// Retrieve all traits in this crate and any dependent crates.
209
- fn all_traits < ' a > ( ccx : & ' a CrateCtxt ) -> AllTraits < ' a > {
228
+ pub fn all_traits < ' a > ( ccx : & ' a CrateCtxt ) -> AllTraits < ' a > {
210
229
if ccx. all_traits . borrow ( ) . is_none ( ) {
211
230
use syntax:: visit;
212
231
@@ -268,7 +287,7 @@ fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
268
287
}
269
288
}
270
289
271
- struct AllTraits < ' a > {
290
+ pub struct AllTraits < ' a > {
272
291
borrow : cell:: Ref < ' a Option <AllTraitsVec > >,
273
292
idx : usize
274
293
}
0 commit comments