@@ -14,7 +14,7 @@ use rustc_infer::infer::{self, TyCtxtInferExt};
1414use rustc_infer:: traits;
1515use rustc_middle:: lint:: in_external_macro;
1616use rustc_middle:: ty:: { self , Binder , IsSuggestable , Subst , ToPredicate , Ty } ;
17- use rustc_span:: symbol:: sym;
17+ use rustc_span:: symbol:: { sym, Ident } ;
1818use rustc_span:: Span ;
1919use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
2020
@@ -187,55 +187,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187187 err. span_label ( self . tcx . def_span ( def_id) , & format ! ( "{} defined here" , found) ) ;
188188 }
189189 } else if !self . check_for_cast ( err, expr, found, expected, expected_ty_expr) {
190- let is_struct_pat_shorthand_field =
191- self . maybe_get_struct_pattern_shorthand_field ( expr) . is_some ( ) ;
190+ let struct_pat_shorthand_field = self . maybe_get_struct_pattern_shorthand_field ( expr) ;
192191 let methods = self . get_conversion_methods ( expr. span , expected, found, expr. hir_id ) ;
193192 if !methods. is_empty ( ) {
194- if let Ok ( expr_text) = self . sess ( ) . source_map ( ) . span_to_snippet ( expr. span ) {
195- let mut suggestions = iter:: zip ( iter:: repeat ( & expr_text) , & methods)
196- . filter_map ( |( receiver, method) | {
197- let method_call = format ! ( ".{}()" , method. name) ;
198- if receiver. ends_with ( & method_call) {
199- None // do not suggest code that is already there (#53348)
193+ let mut suggestions = iter:: zip ( iter:: repeat ( & expr) , & methods)
194+ . filter_map ( |( receiver_expr, method) | {
195+ let method_call = format ! ( ".{}()" , method. name) ;
196+ fn method_ident ( expr : & hir:: Expr < ' _ > ) -> Option < Ident > {
197+ match expr. kind {
198+ ExprKind :: MethodCall ( receiver_method, ..) => Some ( receiver_method. ident ) ,
199+ ExprKind :: Unary ( _, expr) | ExprKind :: AddrOf ( .., expr) => method_ident ( expr) ,
200+ _ => None
201+ }
202+ }
203+ let method_ident = method_ident ( & receiver_expr) ;
204+ if let Some ( method_ident) = method_ident
205+ && method_ident. name == method. name
206+ {
207+ None // do not suggest code that is already there (#53348)
208+ } else {
209+ let method_call_list = [ ".to_vec()" , ".to_string()" ] ;
210+ let mut sugg = if let ExprKind :: MethodCall ( receiver_method, ..) = receiver_expr. kind
211+ && receiver_method. ident . name == sym:: clone
212+ && method_call_list. contains ( & method_call. as_str ( ) )
213+ {
214+ vec ! [ (
215+ receiver_method. ident. span,
216+ method. name. to_string( )
217+ ) ]
200218 } else {
201- let method_call_list = [ ".to_vec()" , ".to_string()" ] ;
202- let mut sugg = if receiver. ends_with ( ".clone()" )
203- && method_call_list. contains ( & method_call. as_str ( ) )
219+ if expr. precedence ( ) . order ( )
220+ < ExprPrecedence :: MethodCall . order ( )
204221 {
205- let max_len = receiver. rfind ( '.' ) . unwrap ( ) ;
206- vec ! [ (
207- expr. span,
208- format!( "{}{}" , & receiver[ ..max_len] , method_call) ,
209- ) ]
222+ vec ! [
223+ ( expr. span. shrink_to_lo( ) , "(" . to_string( ) ) ,
224+ ( expr. span. shrink_to_hi( ) , format!( "){}" , method_call) ) ,
225+ ]
210226 } else {
211- if expr. precedence ( ) . order ( )
212- < ExprPrecedence :: MethodCall . order ( )
213- {
214- vec ! [
215- ( expr. span. shrink_to_lo( ) , "(" . to_string( ) ) ,
216- ( expr. span. shrink_to_hi( ) , format!( "){}" , method_call) ) ,
217- ]
218- } else {
219- vec ! [ ( expr. span. shrink_to_hi( ) , method_call) ]
220- }
221- } ;
222- if is_struct_pat_shorthand_field {
223- sugg. insert (
224- 0 ,
225- ( expr. span . shrink_to_lo ( ) , format ! ( "{}: " , receiver) ) ,
226- ) ;
227+ vec ! [ ( expr. span. shrink_to_hi( ) , method_call) ]
227228 }
228- Some ( sugg)
229+ } ;
230+ if let Some ( name) = struct_pat_shorthand_field {
231+ sugg. insert (
232+ 0 ,
233+ ( expr. span . shrink_to_lo ( ) , format ! ( "{}: " , name) ) ,
234+ ) ;
229235 }
230- } )
231- . peekable ( ) ;
232- if suggestions. peek ( ) . is_some ( ) {
233- err. multipart_suggestions (
234- "try using a conversion method" ,
235- suggestions,
236- Applicability :: MaybeIncorrect ,
237- ) ;
238- }
236+ Some ( sugg)
237+ }
238+ } )
239+ . peekable ( ) ;
240+ if suggestions. peek ( ) . is_some ( ) {
241+ err. multipart_suggestions (
242+ "try using a conversion method" ,
243+ suggestions,
244+ Applicability :: MaybeIncorrect ,
245+ ) ;
239246 }
240247 } else if let ty:: Adt ( found_adt, found_substs) = found. kind ( )
241248 && self . tcx . is_diagnostic_item ( sym:: Option , found_adt. did ( ) )
0 commit comments