@@ -1202,36 +1202,42 @@ fn suggest_ampmut<'tcx>(
1202
1202
opt_assignment_rhs_span : Option < Span > ,
1203
1203
opt_ty_info : Option < Span > ,
1204
1204
) -> ( bool , Span , String ) {
1205
+ // if there is a RHS and it starts with a `&` from it, then check if it is
1206
+ // mutable, and if not, put suggest putting `mut ` to make it mutable.
1207
+ // we don't have to worry about lifetime annotations here because they are
1208
+ // not valid when taking a reference. For example, the following is not valid Rust:
1209
+ //
1210
+ // let x: &i32 = &'a 5;
1211
+ // ^^ lifetime annotation not allowed
1212
+ //
1205
1213
if let Some ( assignment_rhs_span) = opt_assignment_rhs_span
1206
1214
&& let Ok ( src) = tcx. sess . source_map ( ) . span_to_snippet ( assignment_rhs_span)
1215
+ && let Some ( stripped) = src. strip_prefix ( '&' )
1207
1216
{
1208
- let is_mutbl = |ty : & str | -> bool {
1209
- if let Some ( rest) = ty. strip_prefix ( "mut" ) {
1210
- match rest. chars ( ) . next ( ) {
1211
- // e.g. `&mut x`
1212
- Some ( c) if c. is_whitespace ( ) => true ,
1213
- // e.g. `&mut(x)`
1214
- Some ( '(' ) => true ,
1215
- // e.g. `&mut{x}`
1216
- Some ( '{' ) => true ,
1217
- // e.g. `&mutablevar`
1218
- _ => false ,
1219
- }
1220
- } else {
1221
- false
1217
+ let is_mut = if let Some ( rest) = stripped. trim_start ( ) . strip_prefix ( "mut" ) {
1218
+ match rest. chars ( ) . next ( ) {
1219
+ // e.g. `&mut x`
1220
+ Some ( c) if c. is_whitespace ( ) => true ,
1221
+ // e.g. `&mut(x)`
1222
+ Some ( '(' ) => true ,
1223
+ // e.g. `&mut{x}`
1224
+ Some ( '{' ) => true ,
1225
+ // e.g. `&mutablevar`
1226
+ _ => false ,
1222
1227
}
1228
+ } else {
1229
+ false
1223
1230
} ;
1224
- if let ( true , Some ( ws_pos) ) = ( src. starts_with ( "&'" ) , src. find ( char:: is_whitespace) ) {
1225
- let lt_name = & src[ 1 ..ws_pos] ;
1226
- let ty = src[ ws_pos..] . trim_start ( ) ;
1227
- if !is_mutbl ( ty) {
1228
- return ( true , assignment_rhs_span, format ! ( "&{lt_name} mut {ty}" ) ) ;
1229
- }
1230
- } else if let Some ( stripped) = src. strip_prefix ( '&' ) {
1231
- let stripped = stripped. trim_start ( ) ;
1232
- if !is_mutbl ( stripped) {
1233
- return ( true , assignment_rhs_span, format ! ( "&mut {stripped}" ) ) ;
1234
- }
1231
+ // if the reference is already mutable then there is nothing we can do
1232
+ // here.
1233
+ if !is_mut {
1234
+ let span = assignment_rhs_span;
1235
+ // shrink the span to just after the `&` in `&variable`
1236
+ let span = span. with_lo ( span. lo ( ) + BytePos ( 1 ) ) . shrink_to_lo ( ) ;
1237
+
1238
+ // FIXME(Ezrashaw): returning is bad because we still might want to
1239
+ // update the annotated type, see #106857.
1240
+ return ( true , span, "mut " . to_owned ( ) ) ;
1235
1241
}
1236
1242
}
1237
1243
0 commit comments