@@ -35,7 +35,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
3535 error : MethodError )
3636{
3737 match error {
38- MethodError :: NoMatch ( static_sources) => {
38+ MethodError :: NoMatch ( static_sources, out_of_scope_traits ) => {
3939 let cx = fcx. tcx ( ) ;
4040 let method_ustring = method_name. user_string ( cx) ;
4141
@@ -75,7 +75,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
7575 report_candidates ( fcx, span, method_name, static_sources) ;
7676 }
7777
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 )
7979 }
8080
8181 MethodError :: Ambiguity ( sources) => {
@@ -136,10 +136,35 @@ pub type AllTraitsVec = Vec<TraitInfo>;
136136fn suggest_traits_to_import < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
137137 span : Span ,
138138 _rcvr_ty : Ty < ' tcx > ,
139- method_name : ast:: Name )
139+ method_name : ast:: Name ,
140+ valid_out_of_scope_traits : Vec < ast:: DefId > )
140141{
141142 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+ }
142166
167+ // there's no implemented traits, so lets suggest some traits to implement
143168 let mut candidates = all_traits ( fcx. ccx )
144169 . filter ( |info| trait_method ( tcx, info. def_id , method_name) . is_some ( ) )
145170 . collect :: < Vec < _ > > ( ) ;
@@ -148,22 +173,16 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
148173 // sort from most relevant to least relevant
149174 candidates. sort_by ( |a, b| a. cmp ( b) . reverse ( ) ) ;
150175
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) ;
152181
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[ ] ) ;
159183
160184 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,
167186 & * format ! ( "candidate #{}: `{}`" ,
168187 i + 1 ,
169188 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>,
173192
174193#[ derive( Copy ) ]
175194pub struct TraitInfo {
176- def_id : ast:: DefId ,
195+ pub def_id : ast:: DefId ,
177196}
178197
179198impl TraitInfo {
@@ -206,7 +225,7 @@ impl Ord for TraitInfo {
206225}
207226
208227/// 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 > {
210229 if ccx. all_traits . borrow ( ) . is_none ( ) {
211230 use syntax:: visit;
212231
@@ -268,7 +287,7 @@ fn all_traits<'a>(ccx: &'a CrateCtxt) -> AllTraits<'a> {
268287 }
269288}
270289
271- struct AllTraits < ' a > {
290+ pub struct AllTraits < ' a > {
272291 borrow : cell:: Ref < ' a Option <AllTraitsVec > >,
273292 idx : usize
274293}
0 commit comments