@@ -19,6 +19,7 @@ use rustc_trait_selection::traits::ObligationCause;
1919
2020use super :: method:: probe;
2121
22+ use std:: cmp:: min;
2223use std:: iter;
2324
2425impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
@@ -937,51 +938,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
937938 && let Ok ( src) = sm. span_to_snippet ( sp)
938939 {
939940 let derefs = "*" . repeat ( steps) ;
940- if let Some ( ( span, src, applicability) ) = match mutbl_b {
941- hir:: Mutability :: Mut => {
942- let new_prefix = "&mut " . to_owned ( ) + & derefs;
943- match mutbl_a {
944- hir:: Mutability :: Mut => {
945- replace_prefix ( & src, "&mut " , & new_prefix) . map ( |_| {
946- let pos = sp. lo ( ) + BytePos ( 5 ) ;
947- let sp = sp. with_lo ( pos) . with_hi ( pos) ;
948- ( sp, derefs, Applicability :: MachineApplicable )
949- } )
950- }
951- hir:: Mutability :: Not => {
952- replace_prefix ( & src, "&" , & new_prefix) . map ( |_| {
953- let pos = sp. lo ( ) + BytePos ( 1 ) ;
954- let sp = sp. with_lo ( pos) . with_hi ( pos) ;
955- (
956- sp,
957- format ! ( "mut {derefs}" ) ,
958- Applicability :: Unspecified ,
959- )
960- } )
961- }
962- }
963- }
964- hir:: Mutability :: Not => {
965- let new_prefix = "&" . to_owned ( ) + & derefs;
966- match mutbl_a {
967- hir:: Mutability :: Mut => {
968- replace_prefix ( & src, "&mut " , & new_prefix) . map ( |_| {
969- let lo = sp. lo ( ) + BytePos ( 1 ) ;
970- let hi = sp. lo ( ) + BytePos ( 5 ) ;
971- let sp = sp. with_lo ( lo) . with_hi ( hi) ;
972- ( sp, derefs, Applicability :: MachineApplicable )
973- } )
974- }
975- hir:: Mutability :: Not => {
976- replace_prefix ( & src, "&" , & new_prefix) . map ( |_| {
977- let pos = sp. lo ( ) + BytePos ( 1 ) ;
978- let sp = sp. with_lo ( pos) . with_hi ( pos) ;
979- ( sp, derefs, Applicability :: MachineApplicable )
980- } )
981- }
982- }
983- }
984- } {
941+ let old_prefix = mutbl_a. ref_prefix_str ( ) ;
942+ let new_prefix = mutbl_b. ref_prefix_str ( ) . to_owned ( ) + & derefs;
943+
944+ let suggestion = replace_prefix ( & src, old_prefix, & new_prefix) . map ( |_| {
945+ // skip `&` or `&mut ` if both mutabilities are mutable
946+ let lo = sp. lo ( ) + BytePos ( min ( old_prefix. len ( ) , mutbl_b. ref_prefix_str ( ) . len ( ) ) as _ ) ;
947+ // skip `&` or `&mut `
948+ let hi = sp. lo ( ) + BytePos ( old_prefix. len ( ) as _ ) ;
949+ let sp = sp. with_lo ( lo) . with_hi ( hi) ;
950+
951+ (
952+ sp,
953+ format ! ( "{}{derefs}" , if mutbl_a != mutbl_b { mutbl_b. prefix_str( ) } else { "" } ) ,
954+ if mutbl_b <= mutbl_a { Applicability :: MachineApplicable } else { Applicability :: MaybeIncorrect }
955+ )
956+ } ) ;
957+
958+ if let Some ( ( span, src, applicability) ) = suggestion {
985959 return Some ( (
986960 span,
987961 "consider dereferencing" . to_string ( ) ,
@@ -1005,10 +979,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1005979 // If the expression has `&`, removing it would fix the error
1006980 prefix_span = prefix_span. with_hi ( inner. span . lo ( ) ) ;
1007981 expr = inner;
1008- remove += match mutbl {
1009- hir:: Mutability :: Not => "&" ,
1010- hir:: Mutability :: Mut => "&mut " ,
1011- } ;
982+ remove. push_str ( mutbl. ref_prefix_str ( ) ) ;
1012983 steps -= 1 ;
1013984 } else {
1014985 break ;
0 commit comments