@@ -14,6 +14,7 @@ use rustc_middle::lint::in_external_macro;
14
14
use rustc_middle:: ty:: { self , Binder , Ty } ;
15
15
use rustc_span:: symbol:: { kw, sym} ;
16
16
17
+ use rustc_middle:: ty:: subst:: GenericArgKind ;
17
18
use std:: iter;
18
19
19
20
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
@@ -232,48 +233,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
232
233
let is_struct_pat_shorthand_field =
233
234
self . is_hir_id_from_struct_pattern_shorthand_field ( expr. hir_id , expr. span ) ;
234
235
let methods = self . get_conversion_methods ( expr. span , expected, found, expr. hir_id ) ;
235
- if let Ok ( expr_text) = self . sess ( ) . source_map ( ) . span_to_snippet ( expr. span ) {
236
- let mut suggestions = iter:: zip ( iter:: repeat ( & expr_text) , & methods)
237
- . filter_map ( |( receiver, method) | {
238
- let method_call = format ! ( ".{}()" , method. ident) ;
239
- if receiver. ends_with ( & method_call) {
240
- None // do not suggest code that is already there (#53348)
241
- } else {
242
- let method_call_list = [ ".to_vec()" , ".to_string()" ] ;
243
- let mut sugg = if receiver. ends_with ( ".clone()" )
244
- && method_call_list. contains ( & method_call. as_str ( ) )
245
- {
246
- let max_len = receiver. rfind ( '.' ) . unwrap ( ) ;
247
- vec ! [ (
248
- expr. span,
249
- format!( "{}{}" , & receiver[ ..max_len] , method_call) ,
250
- ) ]
236
+ if !methods. is_empty ( ) {
237
+ if let Ok ( expr_text) = self . sess ( ) . source_map ( ) . span_to_snippet ( expr. span ) {
238
+ let mut suggestions = iter:: zip ( iter:: repeat ( & expr_text) , & methods)
239
+ . filter_map ( |( receiver, method) | {
240
+ let method_call = format ! ( ".{}()" , method. ident) ;
241
+ if receiver. ends_with ( & method_call) {
242
+ None // do not suggest code that is already there (#53348)
251
243
} else {
252
- if expr. precedence ( ) . order ( ) < ExprPrecedence :: MethodCall . order ( ) {
253
- vec ! [
254
- ( expr. span. shrink_to_lo( ) , "(" . to_string( ) ) ,
255
- ( expr. span. shrink_to_hi( ) , format!( "){}" , method_call) ) ,
256
- ]
244
+ let method_call_list = [ ".to_vec()" , ".to_string()" ] ;
245
+ let mut sugg = if receiver. ends_with ( ".clone()" )
246
+ && method_call_list. contains ( & method_call. as_str ( ) )
247
+ {
248
+ let max_len = receiver. rfind ( '.' ) . unwrap ( ) ;
249
+ vec ! [ (
250
+ expr. span,
251
+ format!( "{}{}" , & receiver[ ..max_len] , method_call) ,
252
+ ) ]
257
253
} else {
258
- vec ! [ ( expr. span. shrink_to_hi( ) , method_call) ]
254
+ if expr. precedence ( ) . order ( )
255
+ < ExprPrecedence :: MethodCall . order ( )
256
+ {
257
+ vec ! [
258
+ ( expr. span. shrink_to_lo( ) , "(" . to_string( ) ) ,
259
+ ( expr. span. shrink_to_hi( ) , format!( "){}" , method_call) ) ,
260
+ ]
261
+ } else {
262
+ vec ! [ ( expr. span. shrink_to_hi( ) , method_call) ]
263
+ }
264
+ } ;
265
+ if is_struct_pat_shorthand_field {
266
+ sugg. insert (
267
+ 0 ,
268
+ ( expr. span . shrink_to_lo ( ) , format ! ( "{}: " , receiver) ) ,
269
+ ) ;
259
270
}
260
- } ;
261
- if is_struct_pat_shorthand_field {
262
- sugg. insert (
263
- 0 ,
264
- ( expr. span . shrink_to_lo ( ) , format ! ( "{}: " , receiver) ) ,
271
+ Some ( sugg)
272
+ }
273
+ } )
274
+ . peekable ( ) ;
275
+ if suggestions. peek ( ) . is_some ( ) {
276
+ err. multipart_suggestions (
277
+ "try using a conversion method" ,
278
+ suggestions,
279
+ Applicability :: MaybeIncorrect ,
280
+ ) ;
281
+ }
282
+ }
283
+ } else if found. to_string ( ) . starts_with ( "Option<" )
284
+ && expected. to_string ( ) == "Option<&str>"
285
+ {
286
+ if let ty:: Adt ( _def, subst) = found. kind ( ) {
287
+ if subst. len ( ) != 0 {
288
+ if let GenericArgKind :: Type ( ty) = subst[ 0 ] . unpack ( ) {
289
+ let peeled = ty. peel_refs ( ) . to_string ( ) ;
290
+ if peeled == "String" {
291
+ let ref_cnt = ty. to_string ( ) . len ( ) - peeled. len ( ) ;
292
+ let result = format ! ( ".map(|x| &*{}x)" , "*" . repeat( ref_cnt) ) ;
293
+ err. span_suggestion_verbose (
294
+ expr. span . shrink_to_hi ( ) ,
295
+ "try converting the passed type into a `&str`" ,
296
+ result,
297
+ Applicability :: MaybeIncorrect ,
265
298
) ;
266
299
}
267
- Some ( sugg)
268
300
}
269
- } )
270
- . peekable ( ) ;
271
- if suggestions. peek ( ) . is_some ( ) {
272
- err. multipart_suggestions (
273
- "try using a conversion method" ,
274
- suggestions,
275
- Applicability :: MaybeIncorrect ,
276
- ) ;
301
+ }
277
302
}
278
303
}
279
304
}
0 commit comments