Skip to content

Commit 5b26c10

Browse files
committed
Suggest ref mut for pattern matching assignment
1 parent 757b8ef commit 5b26c10

File tree

8 files changed

+155
-39
lines changed

8 files changed

+155
-39
lines changed

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -3020,7 +3020,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
30203020
/// assignment to `x.f`).
30213021
pub(crate) fn report_illegal_reassignment(
30223022
&mut self,
3023-
_location: Location,
30243023
(place, span): (Place<'tcx>, Span),
30253024
assigned_span: Span,
30263025
err_place: Place<'tcx>,
@@ -3053,7 +3052,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
30533052
| None => (self.describe_any_place(place.as_ref()), assigned_span),
30543053
Some(decl) => (self.describe_any_place(err_place.as_ref()), decl.source_info.span),
30553054
};
3056-
30573055
let mut err = self.cannot_reassign_immutable(span, &place_description, from_arg);
30583056
let msg = if from_arg {
30593057
"cannot assign to immutable argument"
@@ -3073,6 +3071,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
30733071
format!("mut {name}"),
30743072
Applicability::MachineApplicable,
30753073
);
3074+
if !from_arg
3075+
&& matches!(
3076+
decl.local_info(),
3077+
LocalInfo::User(BindingForm::Var(VarBindingForm {
3078+
opt_match_place: Some((Some(_), _)),
3079+
..
3080+
}))
3081+
)
3082+
{
3083+
err.span_suggestion(
3084+
decl.source_info.span,
3085+
"to modify the original value, take a borrow instead",
3086+
format!("ref mut {name}"),
3087+
Applicability::MaybeIncorrect,
3088+
);
3089+
}
30763090
}
30773091
err.span_label(span, msg);
30783092
self.buffer_error(err);

compiler/rustc_borrowck/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2174,7 +2174,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
21742174
// report the error as an illegal reassignment
21752175
let init = &self.move_data.inits[init_index];
21762176
let assigned_span = init.span(self.body);
2177-
self.report_illegal_reassignment(location, (place, span), assigned_span, place);
2177+
self.report_illegal_reassignment((place, span), assigned_span, place);
21782178
} else {
21792179
self.report_mutability_error(place, span, the_place_err, error_access, location)
21802180
}

tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr

+50-20
Original file line numberDiff line numberDiff line change
@@ -2,56 +2,86 @@ error[E0384]: cannot assign twice to immutable variable `x`
22
--> $DIR/borrowck-match-binding-is-assignment.rs:14:13
33
|
44
LL | x => {
5-
| -
6-
| |
7-
| first assignment to `x`
8-
| help: consider making this binding mutable: `mut x`
5+
| - first assignment to `x`
96
LL | x += 1;
107
| ^^^^^^ cannot assign twice to immutable variable
8+
|
9+
help: consider making this binding mutable
10+
|
11+
LL | mut x => {
12+
| ~~~~~
13+
help: to modify the original value, take a borrow instead
14+
|
15+
LL | ref mut x => {
16+
| ~~~~~~~~~
1117

1218
error[E0384]: cannot assign twice to immutable variable `x`
1319
--> $DIR/borrowck-match-binding-is-assignment.rs:20:13
1420
|
1521
LL | E::Foo(x) => {
16-
| -
17-
| |
18-
| first assignment to `x`
19-
| help: consider making this binding mutable: `mut x`
22+
| - first assignment to `x`
2023
LL | x += 1;
2124
| ^^^^^^ cannot assign twice to immutable variable
25+
|
26+
help: consider making this binding mutable
27+
|
28+
LL | E::Foo(mut x) => {
29+
| ~~~~~
30+
help: to modify the original value, take a borrow instead
31+
|
32+
LL | E::Foo(ref mut x) => {
33+
| ~~~~~~~~~
2234

2335
error[E0384]: cannot assign twice to immutable variable `x`
2436
--> $DIR/borrowck-match-binding-is-assignment.rs:26:13
2537
|
2638
LL | S { bar: x } => {
27-
| -
28-
| |
29-
| first assignment to `x`
30-
| help: consider making this binding mutable: `mut x`
39+
| - first assignment to `x`
3140
LL | x += 1;
3241
| ^^^^^^ cannot assign twice to immutable variable
42+
|
43+
help: consider making this binding mutable
44+
|
45+
LL | S { bar: mut x } => {
46+
| ~~~~~
47+
help: to modify the original value, take a borrow instead
48+
|
49+
LL | S { bar: ref mut x } => {
50+
| ~~~~~~~~~
3351

3452
error[E0384]: cannot assign twice to immutable variable `x`
3553
--> $DIR/borrowck-match-binding-is-assignment.rs:32:13
3654
|
3755
LL | (x,) => {
38-
| -
39-
| |
40-
| first assignment to `x`
41-
| help: consider making this binding mutable: `mut x`
56+
| - first assignment to `x`
4257
LL | x += 1;
4358
| ^^^^^^ cannot assign twice to immutable variable
59+
|
60+
help: consider making this binding mutable
61+
|
62+
LL | (mut x,) => {
63+
| ~~~~~
64+
help: to modify the original value, take a borrow instead
65+
|
66+
LL | (ref mut x,) => {
67+
| ~~~~~~~~~
4468

4569
error[E0384]: cannot assign twice to immutable variable `x`
4670
--> $DIR/borrowck-match-binding-is-assignment.rs:38:13
4771
|
4872
LL | [x,_,_] => {
49-
| -
50-
| |
51-
| first assignment to `x`
52-
| help: consider making this binding mutable: `mut x`
73+
| - first assignment to `x`
5374
LL | x += 1;
5475
| ^^^^^^ cannot assign twice to immutable variable
76+
|
77+
help: consider making this binding mutable
78+
|
79+
LL | [mut x,_,_] => {
80+
| ~~~~~
81+
help: to modify the original value, take a borrow instead
82+
|
83+
LL | [ref mut x,_,_] => {
84+
| ~~~~~~~~~
5585

5686
error: aborting due to 5 previous errors
5787

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
fn main() {
2+
let y = Some(0);
3+
if let Some(x) = y {
4+
x = 2; //~ ERROR cannot assign twice to immutable variable `x`
5+
}
6+
7+
let mut arr = [1, 2, 3];
8+
let [x, ref xs_hold @ ..] = arr;
9+
x = 0; //~ ERROR cannot assign twice to immutable variable `x`
10+
eprintln!("{:?}", arr);
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0384]: cannot assign twice to immutable variable `x`
2+
--> $DIR/issue-118596-suggest-ref-mut.rs:4:9
3+
|
4+
LL | if let Some(x) = y {
5+
| - first assignment to `x`
6+
LL | x = 2;
7+
| ^^^^^ cannot assign twice to immutable variable
8+
|
9+
help: consider making this binding mutable
10+
|
11+
LL | if let Some(mut x) = y {
12+
| ~~~~~
13+
help: to modify the original value, take a borrow instead
14+
|
15+
LL | if let Some(ref mut x) = y {
16+
| ~~~~~~~~~
17+
18+
error[E0384]: cannot assign twice to immutable variable `x`
19+
--> $DIR/issue-118596-suggest-ref-mut.rs:9:5
20+
|
21+
LL | let [x, ref xs_hold @ ..] = arr;
22+
| - first assignment to `x`
23+
LL | x = 0;
24+
| ^^^^^ cannot assign twice to immutable variable
25+
|
26+
help: consider making this binding mutable
27+
|
28+
LL | let [mut x, ref xs_hold @ ..] = arr;
29+
| ~~~~~
30+
help: to modify the original value, take a borrow instead
31+
|
32+
LL | let [ref mut x, ref xs_hold @ ..] = arr;
33+
| ~~~~~~~~~
34+
35+
error: aborting due to 2 previous errors
36+
37+
For more information about this error, try `rustc --explain E0384`.

tests/ui/mut/mut-pattern-internal-mutability.stderr

+10-4
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,18 @@ error[E0384]: cannot assign twice to immutable variable `x`
22
--> $DIR/mut-pattern-internal-mutability.rs:5:5
33
|
44
LL | let &mut x = foo;
5-
| -
6-
| |
7-
| first assignment to `x`
8-
| help: consider making this binding mutable: `mut x`
5+
| - first assignment to `x`
96
LL | x += 1;
107
| ^^^^^^ cannot assign twice to immutable variable
8+
|
9+
help: consider making this binding mutable
10+
|
11+
LL | let &mut mut x = foo;
12+
| ~~~~~
13+
help: to modify the original value, take a borrow instead
14+
|
15+
LL | let &mut ref mut x = foo;
16+
| ~~~~~~~~~
1117

1218
error[E0506]: cannot assign to `*foo` because it is borrowed
1319
--> $DIR/mut-pattern-internal-mutability.rs:13:5

tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr

+10-4
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,19 @@ error[E0384]: cannot assign twice to immutable variable `a`
7070
--> $DIR/pat-at-same-name-both.rs:13:15
7171
|
7272
LL | Ok(a @ b @ a)
73-
| -
74-
| |
75-
| first assignment to `a`
76-
| help: consider making this binding mutable: `mut a`
73+
| - first assignment to `a`
7774
LL |
7875
LL | | Err(a @ b @ a)
7976
| ^ cannot assign twice to immutable variable
77+
|
78+
help: consider making this binding mutable
79+
|
80+
LL | Ok(a @ b @ mut a)
81+
| ~~~~~
82+
help: to modify the original value, take a borrow instead
83+
|
84+
LL | Ok(a @ b @ ref mut a)
85+
| ~~~~~~~~~
8086

8187
error: aborting due to 12 previous errors
8288

tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr

+20-8
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ error[E0384]: cannot assign twice to immutable variable `_x1`
1515
--> $DIR/borrowck-move-ref-pattern.rs:9:5
1616
|
1717
LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr;
18-
| ---
19-
| |
20-
| first assignment to `_x1`
21-
| help: consider making this binding mutable: `mut _x1`
18+
| --- first assignment to `_x1`
2219
LL | _x1 = U;
2320
| ^^^^^^^ cannot assign twice to immutable variable
21+
|
22+
help: consider making this binding mutable
23+
|
24+
LL | let [ref _x0_hold, mut _x1, ref xs_hold @ ..] = arr;
25+
| ~~~~~~~
26+
help: to modify the original value, take a borrow instead
27+
|
28+
LL | let [ref _x0_hold, ref mut _x1, ref xs_hold @ ..] = arr;
29+
| ~~~~~~~~~~~
2430

2531
error[E0505]: cannot move out of `arr[..]` because it is borrowed
2632
--> $DIR/borrowck-move-ref-pattern.rs:11:10
@@ -73,12 +79,18 @@ error[E0384]: cannot assign twice to immutable variable `_x1`
7379
--> $DIR/borrowck-move-ref-pattern.rs:23:5
7480
|
7581
LL | let (ref _x0, _x1, ref _x2, ..) = tup;
76-
| ---
77-
| |
78-
| first assignment to `_x1`
79-
| help: consider making this binding mutable: `mut _x1`
82+
| --- first assignment to `_x1`
8083
LL | _x1 = U;
8184
| ^^^^^^^ cannot assign twice to immutable variable
85+
|
86+
help: consider making this binding mutable
87+
|
88+
LL | let (ref _x0, mut _x1, ref _x2, ..) = tup;
89+
| ~~~~~~~
90+
help: to modify the original value, take a borrow instead
91+
|
92+
LL | let (ref _x0, ref mut _x1, ref _x2, ..) = tup;
93+
| ~~~~~~~~~~~
8294

8395
error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable
8496
--> $DIR/borrowck-move-ref-pattern.rs:24:20

0 commit comments

Comments
 (0)