@@ -14,12 +14,10 @@ use rustc_infer::infer::{self, TyCtxtInferExt};
14
14
use rustc_infer:: traits;
15
15
use rustc_middle:: lint:: in_external_macro;
16
16
use rustc_middle:: ty:: { self , Binder , IsSuggestable , Subst , ToPredicate , Ty } ;
17
- use rustc_span:: symbol:: { sym, Ident } ;
17
+ 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,54 +185,48 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
187
185
err. span_label ( self . tcx . def_span ( def_id) , & format ! ( "{} defined here" , found) ) ;
188
186
}
189
187
} 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) ;
191
188
let methods = self . get_conversion_methods ( expr. span , expected, found, expr. hir_id ) ;
192
189
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)
202
197
}
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.
206
207
{
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
+ ]
208
219
} 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
+ ) ;
237
228
}
229
+ Some ( sugg)
238
230
} )
239
231
. peekable ( ) ;
240
232
if suggestions. peek ( ) . is_some ( ) {
0 commit comments