@@ -19,28 +19,10 @@ use syntax_pos::{self, Span};
1919use rustc:: hir;
2020use rustc:: ty:: { self , ImplOrTraitItem } ;
2121
22- use hir:: def_id:: DefId ;
23-
2422use std:: rc:: Rc ;
2523
2624use super :: method:: probe;
2725
28- struct MethodInfo < ' tcx > {
29- ast : Option < ast:: Attribute > ,
30- id : DefId ,
31- item : Rc < ImplOrTraitItem < ' tcx > > ,
32- }
33-
34- impl < ' tcx > MethodInfo < ' tcx > {
35- fn new ( ast : Option < ast:: Attribute > , id : DefId , item : Rc < ImplOrTraitItem < ' tcx > > ) -> MethodInfo {
36- MethodInfo {
37- ast : ast,
38- id : id,
39- item : item,
40- }
41- }
42- }
43-
4426impl < ' a , ' gcx , ' tcx > FnCtxt < ' a , ' gcx , ' tcx > {
4527 // Requires that the two types unify, and prints an error message if
4628 // they don't.
@@ -79,41 +61,70 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
7961 }
8062 }
8163
64+ fn check_ref ( & self , expr : & hir:: Expr , checked_ty : Ty < ' tcx > ,
65+ expected : Ty < ' tcx > ) -> Option < String > {
66+ match ( & checked_ty. sty , & expected. sty ) {
67+ ( & ty:: TyRef ( _, x_mutability) , & ty:: TyRef ( _, y_mutability) ) => {
68+ // check if there is a mutability difference
69+ if x_mutability. mutbl == hir:: Mutability :: MutImmutable &&
70+ x_mutability. mutbl != y_mutability. mutbl &&
71+ self . can_sub_types ( & x_mutability. ty , y_mutability. ty ) . is_ok ( ) {
72+ if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
73+ return Some ( format ! ( "try with `&mut {}`" , & src. replace( "&" , "" ) ) ) ;
74+ }
75+ }
76+ None
77+ }
78+ ( _, & ty:: TyRef ( _, mutability) ) => {
79+ // check if it can work when put into a ref
80+ let ref_ty = match mutability. mutbl {
81+ hir:: Mutability :: MutMutable => self . tcx . mk_mut_ref (
82+ self . tcx . mk_region ( ty:: ReStatic ) ,
83+ checked_ty) ,
84+ hir:: Mutability :: MutImmutable => self . tcx . mk_imm_ref (
85+ self . tcx . mk_region ( ty:: ReStatic ) ,
86+ checked_ty) ,
87+ } ;
88+ if self . try_coerce ( expr, ref_ty, expected) . is_ok ( ) {
89+ if let Ok ( src) = self . tcx . sess . codemap ( ) . span_to_snippet ( expr. span ) {
90+ return Some ( format ! ( "try with `{}{}`" ,
91+ match mutability. mutbl {
92+ hir:: Mutability :: MutMutable => "&mut " ,
93+ hir:: Mutability :: MutImmutable => "&" ,
94+ } ,
95+ & src) ) ;
96+ }
97+ }
98+ None
99+ }
100+ _ => None ,
101+ }
102+ }
103+
82104 // Checks that the type of `expr` can be coerced to `expected`.
83105 pub fn demand_coerce( & self , expr : & hir:: Expr , checked_ty : Ty < ' tcx > , expected : Ty < ' tcx > ) {
84106 let expected = self . resolve_type_vars_with_obligations ( expected) ;
85107 if let Err ( e) = self . try_coerce ( expr, checked_ty, expected) {
86108 let cause = self . misc ( expr. span ) ;
87109 let expr_ty = self . resolve_type_vars_with_obligations ( checked_ty) ;
88110 let mode = probe:: Mode :: MethodCall ;
89- let suggestions =
90- if let Ok ( methods) = self . probe_return ( syntax_pos:: DUMMY_SP , mode, expected,
91- checked_ty, ast:: DUMMY_NODE_ID ) {
111+ let suggestions = if let Some ( s) = self . check_ref ( expr, checked_ty, expected) {
112+ Some ( s)
113+ } else if let Ok ( methods) = self . probe_return ( syntax_pos:: DUMMY_SP ,
114+ mode,
115+ expected,
116+ checked_ty,
117+ ast:: DUMMY_NODE_ID ) {
92118 let suggestions: Vec < _ > =
93119 methods. iter ( )
94- . filter_map ( |ref x| {
95- if let Some ( id) = self . get_impl_id ( & x. item ) {
96- Some ( MethodInfo :: new ( None , id, Rc :: new ( x. item . clone ( ) ) ) )
97- } else {
98- None
99- } } )
120+ . map ( |ref x| {
121+ Rc :: new ( x. item . clone ( ) )
122+ } )
100123 . collect ( ) ;
101124 if suggestions. len ( ) > 0 {
102- let safe_suggestions: Vec < _ > =
103- suggestions. iter ( )
104- . map ( |ref x| MethodInfo :: new (
105- self . find_attr ( x. id , "safe_suggestion" ) ,
106- x. id ,
107- x. item . clone ( ) ) )
108- . filter ( |ref x| x. ast . is_some ( ) )
109- . collect ( ) ;
110- Some ( if safe_suggestions. len ( ) > 0 {
111- self . get_best_match ( & safe_suggestions)
112- } else {
113- format ! ( "no safe suggestion found, here are functions which match your \
114- needs but be careful:\n - {}",
115- self . get_best_match( & suggestions) )
116- } )
125+ Some ( format ! ( "here are some functions which \
126+ might fulfill your needs:\n - {}",
127+ self . get_best_match( & suggestions) ) )
117128 } else {
118129 None
119130 }
@@ -132,34 +143,29 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
132143 }
133144 }
134145
135- fn get_best_match ( & self , methods : & [ MethodInfo < ' tcx > ] ) -> String {
146+ fn get_best_match ( & self , methods : & [ Rc < ImplOrTraitItem < ' tcx > > ] ) -> String {
136147 if methods. len ( ) == 1 {
137- return format ! ( " - {}" , methods[ 0 ] . item . name( ) ) ;
148+ return format ! ( " - {}" , methods[ 0 ] . name( ) ) ;
138149 }
139- let no_argument_methods : Vec < & MethodInfo > =
150+ let no_argument_methods : Vec < & Rc < ImplOrTraitItem < ' tcx > > > =
140151 methods. iter( )
141- . filter( |ref x| self . has_not_input_arg ( & * x. item ) )
152+ . filter( |ref x| self . has_not_input_arg ( & * x) )
142153 . collect( ) ;
143154 if no_argument_methods. len( ) > 0 {
144155 no_argument_methods. iter( )
145- . map( |method| format ! ( "{}" , method. item. name( ) ) )
156+ . take( 5 )
157+ . map( |method| format ! ( "{}" , method. name( ) ) )
146158 . collect :: < Vec < String > > ( )
147159 . join( "\n - " )
148160 } else {
149161 methods. iter( )
150- . map( |method| format ! ( "{}" , method. item. name( ) ) )
162+ . take( 5 )
163+ . map( |method| format ! ( "{}" , method. name( ) ) )
151164 . collect :: < Vec < String > > ( )
152165 . join( "\n - " )
153166 }
154167 }
155168
156- fn get_impl_id( & self , impl_: & ImplOrTraitItem < ' tcx > ) -> Option < DefId > {
157- match * impl_ {
158- ty : : ImplOrTraitItem :: MethodTraitItem ( ref m) => Some ( ( * m) . def_id) ,
159- _ => None,
160- }
161- }
162-
163169 fn has_not_input_arg( & self , method: & ImplOrTraitItem < ' tcx > ) -> bool {
164170 match * method {
165171 ImplOrTraitItem : : MethodTraitItem ( ref x) => {
0 commit comments