@@ -18,8 +18,6 @@ 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,55 +185,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187185 err. span_label ( sp, format ! ( "{found} defined here" ) ) ;
188186 }
189187 } 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 ( ) ;
192188 let methods = self . get_conversion_methods ( expr. span , expected, found, expr. hir_id ) ;
193189 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)
200- } 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 ( ) )
204- {
205- let max_len = receiver. rfind ( '.' ) . unwrap ( ) ;
206- vec ! [ (
207- expr. span,
208- format!( "{}{}" , & receiver[ ..max_len] , method_call) ,
209- ) ]
210- } 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- }
228- Some ( sugg)
229- }
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- }
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)
197+ }
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.
207+ {
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+ ]
219+ } else {
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+ ) ;
228+ }
229+ Some ( sugg)
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+ ) ;
239238 }
240239 } else if let ty:: Adt ( found_adt, found_substs) = found. kind ( )
241240 && self . tcx . is_diagnostic_item ( sym:: Option , found_adt. did ( ) )
0 commit comments