@@ -14,12 +14,10 @@ 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, Ident } ;
17+ use rustc_span:: symbol:: sym;
1818use rustc_span:: Span ;
1919use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
2020
21- use std:: iter;
22-
2321impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
2422 pub ( in super :: super ) fn suggest_semicolon_at_end ( & self , span : Span , err : & mut Diagnostic ) {
2523 err. span_suggestion_short (
@@ -187,54 +185,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187185 err. span_label ( self . tcx . def_span ( def_id) , & format ! ( "{} defined here" , found) ) ;
188186 }
189187 } else if !self . check_for_cast ( err, expr, found, expected, expected_ty_expr) {
190- let struct_pat_shorthand_field = self . maybe_get_struct_pattern_shorthand_field ( expr) ;
191188 let methods = self . get_conversion_methods ( expr. span , expected, found, expr. hir_id ) ;
192189 if !methods. is_empty ( ) {
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- }
190+ let mut suggestions = methods. iter ( )
191+ . filter_map ( |conversion_method| {
192+ let receiver_method_ident = expr. method_ident ( ) ;
193+ if let Some ( method_ident) = receiver_method_ident
194+ && method_ident. name == conversion_method. name
195+ {
196+ return None // do not suggest code that is already there (#53348)
202197 }
203- let method_ident = method_ident ( & receiver_expr) ;
204- if let Some ( method_ident) = method_ident
205- && method_ident. name == method. name
198+
199+ let method_call_list = [ sym:: to_vec, sym:: to_string] ;
200+ let mut sugg = if let ExprKind :: MethodCall ( receiver_method, ..) = expr. kind
201+ && receiver_method. ident . name == sym:: clone
202+ && method_call_list. contains ( & conversion_method. name )
203+ // If receiver is `.clone()` and found type has one of those methods,
204+ // we guess that the user wants to convert from a slice type (`&[]` or `&str`)
205+ // to an owned type (`Vec` or `String`). These conversions clone internally,
206+ // so we remove the user's `clone` call.
206207 {
207- None // do not suggest code that is already there (#53348)
208+ vec ! [ (
209+ receiver_method. ident. span,
210+ conversion_method. name. to_string( )
211+ ) ]
212+ } else if expr. precedence ( ) . order ( )
213+ < ExprPrecedence :: MethodCall . order ( )
214+ {
215+ vec ! [
216+ ( expr. span. shrink_to_lo( ) , "(" . to_string( ) ) ,
217+ ( expr. span. shrink_to_hi( ) , format!( ").{}()" , conversion_method. name) ) ,
218+ ]
208219 } 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- ) ]
218- } else {
219- if expr. precedence ( ) . order ( )
220- < ExprPrecedence :: MethodCall . order ( )
221- {
222- vec ! [
223- ( expr. span. shrink_to_lo( ) , "(" . to_string( ) ) ,
224- ( expr. span. shrink_to_hi( ) , format!( "){}" , method_call) ) ,
225- ]
226- } else {
227- vec ! [ ( expr. span. shrink_to_hi( ) , method_call) ]
228- }
229- } ;
230- if let Some ( name) = struct_pat_shorthand_field {
231- sugg. insert (
232- 0 ,
233- ( expr. span . shrink_to_lo ( ) , format ! ( "{}: " , name) ) ,
234- ) ;
235- }
236- Some ( sugg)
220+ vec ! [ ( expr. span. shrink_to_hi( ) , format!( ".{}()" , conversion_method. name) ) ]
221+ } ;
222+ let struct_pat_shorthand_field = self . maybe_get_struct_pattern_shorthand_field ( expr) ;
223+ if let Some ( name) = struct_pat_shorthand_field {
224+ sugg. insert (
225+ 0 ,
226+ ( expr. span . shrink_to_lo ( ) , format ! ( "{}: " , name) ) ,
227+ ) ;
237228 }
229+ Some ( sugg)
238230 } )
239231 . peekable ( ) ;
240232 if suggestions. peek ( ) . is_some ( ) {
0 commit comments