@@ -18,8 +18,6 @@ use rustc_span::symbol::sym;
18
18
use rustc_span:: Span ;
19
19
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt ;
20
20
21
- use std:: iter;
22
-
23
21
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
24
22
pub ( in super :: super ) fn suggest_semicolon_at_end ( & self , span : Span , err : & mut Diagnostic ) {
25
23
err. span_suggestion_short (
@@ -187,55 +185,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187
185
err. span_label ( sp, format ! ( "{found} defined here" ) ) ;
188
186
}
189
187
} 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 ( ) ;
192
188
let methods = self . get_conversion_methods ( expr. span , expected, found, expr. hir_id ) ;
193
189
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
+ ) ;
239
238
}
240
239
} else if let ty:: Adt ( found_adt, found_substs) = found. kind ( )
241
240
&& self . tcx . is_diagnostic_item ( sym:: Option , found_adt. did ( ) )
0 commit comments