8
8
// option. This file may not be copied, modified, or distributed
9
9
// except according to those terms.
10
10
11
+ use std:: ops:: Deref ;
11
12
12
13
use check:: FnCtxt ;
13
14
use rustc:: infer:: InferOk ;
@@ -18,7 +19,7 @@ use syntax_pos::{self, Span};
18
19
use rustc:: hir;
19
20
use rustc:: hir:: print;
20
21
use rustc:: hir:: def:: Def ;
21
- use rustc:: ty:: { self , Ty , AssociatedItem } ;
22
+ use rustc:: ty:: { self , Ty , AssociatedItem , AssociatedItemContainer } ;
22
23
use errors:: { DiagnosticBuilder , CodeMapper } ;
23
24
24
25
use super :: method:: probe;
@@ -146,7 +147,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
146
147
checked_ty,
147
148
ast:: DUMMY_NODE_ID ) ;
148
149
if suggestions. len ( ) > 0 {
149
- err. help ( & format ! ( "here are some functions which \
150
+ err. help ( & format ! ( "here are some methods which \
150
151
might fulfill your needs:\n {}",
151
152
self . get_best_match( & suggestions) . join( "\n " ) ) ) ;
152
153
}
@@ -165,18 +166,39 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
165
166
}
166
167
167
168
fn display_suggested_methods ( & self , methods : & [ AssociatedItem ] ) -> Vec < String > {
169
+ let limit = if methods. len ( ) == 4 { 4 } else { 3 } ; // never omit just one method
168
170
methods. iter ( )
169
- . take ( 5 )
171
+ . take ( limit )
170
172
. map ( |method| self . format_method_suggestion ( & * method) )
171
173
. collect :: < Vec < String > > ( )
172
174
}
173
175
174
176
fn get_best_match ( & self , methods : & [ AssociatedItem ] ) -> Vec < String > {
175
- let no_argument_methods: Vec < _ > =
177
+ let mut no_argument_methods: Vec < _ > =
176
178
methods. iter ( )
177
179
. filter ( |ref x| self . has_no_input_arg ( & * x) )
178
- . map ( |x| x . clone ( ) )
180
+ . cloned ( )
179
181
. collect ( ) ;
182
+
183
+ // We want the list to prioritize methods that are plausibly
184
+ // conversions: we do so first by name, and then by whether the method
185
+ // comes from a trait (so that methods from actual conversion traits
186
+ // like `Into<_>` and `ToString` come before methods that merely have a
187
+ // suggestive name)
188
+ let conversion_method_name = |n : & str | {
189
+ n. starts_with ( "to_" ) || n. starts_with ( "into" ) ||
190
+ n. starts_with ( "as_" ) || n. starts_with ( "borrow" )
191
+ } ;
192
+ no_argument_methods. sort_by_key ( |m| {
193
+ let name = m. name . as_str ( ) ;
194
+ let name_fit = if conversion_method_name ( name. deref ( ) ) { 0 } else { 1 } ;
195
+ let traitness = match m. container {
196
+ AssociatedItemContainer :: TraitContainer ( _) => 0 ,
197
+ AssociatedItemContainer :: ImplContainer ( _) => 1 ,
198
+ } ;
199
+ ( name_fit, traitness, name)
200
+ } ) ;
201
+
180
202
if no_argument_methods. len ( ) > 0 {
181
203
self . display_suggested_methods ( & no_argument_methods)
182
204
} else {
0 commit comments