@@ -14,6 +14,7 @@ use rustc_middle::lint::in_external_macro;
1414use rustc_middle:: ty:: { self , Binder , Ty } ;
1515use rustc_span:: symbol:: { kw, sym} ;
1616
17+ use rustc_middle:: ty:: subst:: GenericArgKind ;
1718use std:: iter;
1819
1920impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
@@ -232,48 +233,72 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
232233 let is_struct_pat_shorthand_field =
233234 self . is_hir_id_from_struct_pattern_shorthand_field ( expr. hir_id , expr. span ) ;
234235 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)
251243 } 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+ ) ]
257253 } 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+ ) ;
259270 }
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 ,
265298 ) ;
266299 }
267- Some ( sugg)
268300 }
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+ }
277302 }
278303 }
279304 }
0 commit comments