@@ -353,6 +353,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
353353 false
354354 }
355355
356+ fn replace_prefix < A , B , C > ( & self , s : A , old : B , new : C ) -> Option < String >
357+ where
358+ A : AsRef < str > ,
359+ B : AsRef < str > ,
360+ C : AsRef < str > ,
361+ {
362+ let s = s. as_ref ( ) ;
363+ let old = old. as_ref ( ) ;
364+ if s. starts_with ( old) { Some ( new. as_ref ( ) . to_owned ( ) + & s[ old. len ( ) ..] ) } else { None }
365+ }
366+
356367 /// This function is used to determine potential "simple" improvements or users' errors and
357368 /// provide them useful help. For example:
358369 ///
@@ -393,20 +404,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
393404 // `ExprKind::DropTemps` is semantically irrelevant for these suggestions.
394405 let expr = expr. peel_drop_temps ( ) ;
395406
396- let remove_prefix = |s : String , prefix : & str | {
397- if s. starts_with ( prefix) { Some ( s[ prefix. len ( ) ..] . to_string ( ) ) } else { None }
398- } ;
399-
400407 match ( & expr. kind , & expected. kind , & checked_ty. kind ) {
401408 ( _, & ty:: Ref ( _, exp, _) , & ty:: Ref ( _, check, _) ) => match ( & exp. kind , & check. kind ) {
402409 ( & ty:: Str , & ty:: Array ( arr, _) | & ty:: Slice ( arr) ) if arr == self . tcx . types . u8 => {
403410 if let hir:: ExprKind :: Lit ( _) = expr. kind {
404411 if let Ok ( src) = sm. span_to_snippet ( sp) {
405- if let Some ( src) = remove_prefix ( src, "b\" " ) {
412+ if let Some ( src) = self . replace_prefix ( src, "b\" " , " \" ") {
406413 return Some ( (
407414 sp,
408415 "consider removing the leading `b`" ,
409- format ! ( " \" {}" , src) ,
416+ src,
410417 Applicability :: MachineApplicable ,
411418 ) ) ;
412419 }
@@ -416,11 +423,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
416423 ( & ty:: Array ( arr, _) | & ty:: Slice ( arr) , & ty:: Str ) if arr == self . tcx . types . u8 => {
417424 if let hir:: ExprKind :: Lit ( _) = expr. kind {
418425 if let Ok ( src) = sm. span_to_snippet ( sp) {
419- if let Some ( src) = remove_prefix ( src, "\" " ) {
426+ if let Some ( src) = self . replace_prefix ( src, "\" " , "b \" ") {
420427 return Some ( (
421428 sp,
422429 "consider adding a leading `b`" ,
423- format ! ( "b \" {}" , src) ,
430+ src,
424431 Applicability :: MachineApplicable ,
425432 ) ) ;
426433 }
@@ -539,7 +546,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
539546 // we may want to suggest removing a `&`.
540547 if sm. is_imported ( expr. span ) {
541548 if let Ok ( src) = sm. span_to_snippet ( sp) {
542- if let Some ( src) = remove_prefix ( src, "&" ) {
549+ if let Some ( src) = self . replace_prefix ( src, "&" , " ") {
543550 return Some ( (
544551 sp,
545552 "consider removing the borrow" ,
@@ -569,52 +576,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
569576 if steps > 0 {
570577 // The pointer type implements `Copy` trait so the suggestion is always valid.
571578 if let Ok ( src) = sm. span_to_snippet ( sp) {
572- let derefs = "*" . repeat ( steps) ;
573- match mutbl_b {
574- hir:: Mutability :: Mut => match mutbl_a {
575- hir:: Mutability :: Mut => {
576- if let Some ( src) = remove_prefix ( src, "&mut " ) {
577- return Some ( (
578- sp,
579- "consider dereferencing" ,
580- format ! ( "&mut {}{}" , derefs, src) ,
581- Applicability :: MachineApplicable ,
582- ) ) ;
579+ let derefs = & "*" . repeat ( steps) ;
580+ if let Some ( ( src, applicability) ) = match mutbl_b {
581+ hir:: Mutability :: Mut => {
582+ let new_prefix = "&mut " . to_owned ( ) + derefs;
583+ match mutbl_a {
584+ hir:: Mutability :: Mut => {
585+ if let Some ( s) =
586+ self . replace_prefix ( src, "&mut " , new_prefix)
587+ {
588+ Some ( ( s, Applicability :: MachineApplicable ) )
589+ } else {
590+ None
591+ }
583592 }
584- }
585- hir:: Mutability :: Not => {
586- if let Some ( src) = remove_prefix ( src, "&" ) {
587- return Some ( (
588- sp,
589- "consider dereferencing" ,
590- format ! ( "&mut {}{}" , derefs, src) ,
591- Applicability :: Unspecified ,
592- ) ) ;
593+ hir:: Mutability :: Not => {
594+ if let Some ( s) =
595+ self . replace_prefix ( src, "&" , new_prefix)
596+ {
597+ Some ( ( s, Applicability :: Unspecified ) )
598+ } else {
599+ None
600+ }
593601 }
594602 }
595- } ,
596- hir:: Mutability :: Not => match mutbl_a {
597- hir:: Mutability :: Mut => {
598- if let Some ( src) = remove_prefix ( src, "&mut " ) {
599- return Some ( (
600- sp,
601- "consider dereferencing" ,
602- format ! ( "&{}{}" , derefs, src) ,
603- Applicability :: MachineApplicable ,
604- ) ) ;
603+ }
604+ hir:: Mutability :: Not => {
605+ let new_prefix = "&" . to_owned ( ) + derefs;
606+ match mutbl_a {
607+ hir:: Mutability :: Mut => {
608+ if let Some ( s) =
609+ self . replace_prefix ( src, "&mut " , new_prefix)
610+ {
611+ Some ( ( s, Applicability :: MachineApplicable ) )
612+ } else {
613+ None
614+ }
605615 }
606- }
607- hir:: Mutability :: Not => {
608- if let Some ( src) = remove_prefix ( src, "&" ) {
609- return Some ( (
610- sp,
611- "consider dereferencing" ,
612- format ! ( "&{}{}" , derefs, src) ,
613- Applicability :: MachineApplicable ,
614- ) ) ;
616+ hir:: Mutability :: Not => {
617+ if let Some ( s) =
618+ self . replace_prefix ( src, "&" , new_prefix)
619+ {
620+ Some ( ( s, Applicability :: MachineApplicable ) )
621+ } else {
622+ None
623+ }
615624 }
616625 }
617- } ,
626+ }
627+ } {
628+ return Some ( ( sp, "consider dereferencing" , src, applicability) ) ;
618629 }
619630 }
620631 }
0 commit comments