@@ -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- \n  - {}", 
115-                                 self . get_best_match( & suggestions) ) 
116-                     } ) 
125+                     Some ( format ! ( "here are some functions which \  
126+ \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