diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 4878da530b0..0e33a78cffb 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -3706,7 +3706,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { | None => (self.describe_any_place(place.as_ref()), assigned_span), Some(decl) => (self.describe_any_place(err_place.as_ref()), decl.source_info.span), }; - let mut err = self.cannot_reassign_immutable(span, &place_description, from_arg); let msg = if from_arg { "cannot assign to immutable argument" @@ -3726,6 +3725,22 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { format!("mut {name}"), Applicability::MachineApplicable, ); + if !from_arg + && matches!( + decl.local_info(), + LocalInfo::User(BindingForm::Var(VarBindingForm { + opt_match_place: Some((Some(_), _)), + .. + })) + ) + { + err.span_suggestion( + decl.source_info.span, + "to modify the original value, take a borrow instead", + format!("ref mut {name}"), + Applicability::MaybeIncorrect, + ); + } } err.span_label(span, msg); self.buffer_error(err); diff --git a/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr b/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr index dd22d7e2e2e..98ffa7f6ffa 100644 --- a/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr +++ b/tests/ui/borrowck/borrowck-match-binding-is-assignment.stderr @@ -2,56 +2,86 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/borrowck-match-binding-is-assignment.rs:14:13 | LL | x => { - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | mut x => { + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | ref mut x => { + | ~~~~~~~~~ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/borrowck-match-binding-is-assignment.rs:20:13 | LL | E::Foo(x) => { - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | E::Foo(mut x) => { + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | E::Foo(ref mut x) => { + | ~~~~~~~~~ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/borrowck-match-binding-is-assignment.rs:26:13 | LL | S { bar: x } => { - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | S { bar: mut x } => { + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | S { bar: ref mut x } => { + | ~~~~~~~~~ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/borrowck-match-binding-is-assignment.rs:32:13 | LL | (x,) => { - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | (mut x,) => { + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | (ref mut x,) => { + | ~~~~~~~~~ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/borrowck-match-binding-is-assignment.rs:38:13 | LL | [x,_,_] => { - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | [mut x,_,_] => { + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | [ref mut x,_,_] => { + | ~~~~~~~~~ error: aborting due to 5 previous errors diff --git a/tests/ui/borrowck/suggest-ref-mut-issue-118596.rs b/tests/ui/borrowck/suggest-ref-mut-issue-118596.rs new file mode 100644 index 00000000000..fb894623e78 --- /dev/null +++ b/tests/ui/borrowck/suggest-ref-mut-issue-118596.rs @@ -0,0 +1,11 @@ +fn main() { + let y = Some(0); + if let Some(x) = y { + x = 2; //~ ERROR cannot assign twice to immutable variable `x` + } + + let mut arr = [1, 2, 3]; + let [x, ref xs_hold @ ..] = arr; + x = 0; //~ ERROR cannot assign twice to immutable variable `x` + eprintln!("{:?}", arr); +} diff --git a/tests/ui/borrowck/suggest-ref-mut-issue-118596.stderr b/tests/ui/borrowck/suggest-ref-mut-issue-118596.stderr new file mode 100644 index 00000000000..fd2a775a099 --- /dev/null +++ b/tests/ui/borrowck/suggest-ref-mut-issue-118596.stderr @@ -0,0 +1,37 @@ +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/suggest-ref-mut-issue-118596.rs:4:9 + | +LL | if let Some(x) = y { + | - first assignment to `x` +LL | x = 2; + | ^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | if let Some(mut x) = y { + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | if let Some(ref mut x) = y { + | ~~~~~~~~~ + +error[E0384]: cannot assign twice to immutable variable `x` + --> $DIR/suggest-ref-mut-issue-118596.rs:9:5 + | +LL | let [x, ref xs_hold @ ..] = arr; + | - first assignment to `x` +LL | x = 0; + | ^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | let [mut x, ref xs_hold @ ..] = arr; + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | let [ref mut x, ref xs_hold @ ..] = arr; + | ~~~~~~~~~ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0384`. diff --git a/tests/ui/mut/mut-pattern-internal-mutability.stderr b/tests/ui/mut/mut-pattern-internal-mutability.stderr index 5f2074edb12..ab80af17a08 100644 --- a/tests/ui/mut/mut-pattern-internal-mutability.stderr +++ b/tests/ui/mut/mut-pattern-internal-mutability.stderr @@ -2,12 +2,18 @@ error[E0384]: cannot assign twice to immutable variable `x` --> $DIR/mut-pattern-internal-mutability.rs:5:5 | LL | let &mut x = foo; - | - - | | - | first assignment to `x` - | help: consider making this binding mutable: `mut x` + | - first assignment to `x` LL | x += 1; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | let &mut mut x = foo; + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | let &mut ref mut x = foo; + | ~~~~~~~~~ error[E0506]: cannot assign to `*foo` because it is borrowed --> $DIR/mut-pattern-internal-mutability.rs:13:5 diff --git a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr index e25c30cd492..41d1b79d97d 100644 --- a/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr +++ b/tests/ui/pattern/bindings-after-at/pat-at-same-name-both.stderr @@ -70,13 +70,19 @@ error[E0384]: cannot assign twice to immutable variable `a` --> $DIR/pat-at-same-name-both.rs:13:15 | LL | Ok(a @ b @ a) - | - - | | - | first assignment to `a` - | help: consider making this binding mutable: `mut a` + | - first assignment to `a` LL | LL | | Err(a @ b @ a) | ^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | Ok(a @ b @ mut a) + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | Ok(a @ b @ ref mut a) + | ~~~~~~~~~ error: aborting due to 12 previous errors diff --git a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr index a033cc0655e..1e7b990b67c 100644 --- a/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr +++ b/tests/ui/pattern/move-ref-patterns/borrowck-move-ref-pattern.stderr @@ -15,12 +15,18 @@ error[E0384]: cannot assign twice to immutable variable `_x1` --> $DIR/borrowck-move-ref-pattern.rs:9:5 | LL | let [ref _x0_hold, _x1, ref xs_hold @ ..] = arr; - | --- - | | - | first assignment to `_x1` - | help: consider making this binding mutable: `mut _x1` + | --- first assignment to `_x1` LL | _x1 = U; | ^^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | let [ref _x0_hold, mut _x1, ref xs_hold @ ..] = arr; + | ~~~~~~~ +help: to modify the original value, take a borrow instead + | +LL | let [ref _x0_hold, ref mut _x1, ref xs_hold @ ..] = arr; + | ~~~~~~~~~~~ error[E0505]: cannot move out of `arr[..]` because it is borrowed --> $DIR/borrowck-move-ref-pattern.rs:11:10 @@ -73,12 +79,18 @@ error[E0384]: cannot assign twice to immutable variable `_x1` --> $DIR/borrowck-move-ref-pattern.rs:23:5 | LL | let (ref _x0, _x1, ref _x2, ..) = tup; - | --- - | | - | first assignment to `_x1` - | help: consider making this binding mutable: `mut _x1` + | --- first assignment to `_x1` LL | _x1 = U; | ^^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | let (ref _x0, mut _x1, ref _x2, ..) = tup; + | ~~~~~~~ +help: to modify the original value, take a borrow instead + | +LL | let (ref _x0, ref mut _x1, ref _x2, ..) = tup; + | ~~~~~~~~~~~ error[E0502]: cannot borrow `tup.0` as mutable because it is also borrowed as immutable --> $DIR/borrowck-move-ref-pattern.rs:24:20 diff --git a/tests/ui/pattern/mut-ref-mut-2021.stderr b/tests/ui/pattern/mut-ref-mut-2021.stderr index eb31ffa0e30..ebf7979edb6 100644 --- a/tests/ui/pattern/mut-ref-mut-2021.stderr +++ b/tests/ui/pattern/mut-ref-mut-2021.stderr @@ -2,12 +2,18 @@ error[E0384]: cannot assign twice to immutable variable `a` --> $DIR/mut-ref-mut-2021.rs:9:5 | LL | let Foo(a) = Foo(0); - | - - | | - | first assignment to `a` - | help: consider making this binding mutable: `mut a` + | - first assignment to `a` LL | a = 42; | ^^^^^^ cannot assign twice to immutable variable + | +help: consider making this binding mutable + | +LL | let Foo(mut a) = Foo(0); + | ~~~~~ +help: to modify the original value, take a borrow instead + | +LL | let Foo(ref mut a) = Foo(0); + | ~~~~~~~~~ error[E0384]: cannot assign twice to immutable variable `a` --> $DIR/mut-ref-mut-2021.rs:15:5