Skip to content

Commit

Permalink
Rollup merge of rust-lang#136397 - Shunpoco:issue-136223-ICE-pattern-…
Browse files Browse the repository at this point in the history
…mutability-cap-violated, r=Nadrieril

Add a comment pointing to ICE-136223

Fixes rust-lang#136223

## Steps how the ICE happen
This explanation is based on the test case `&Some(Some(x)) = &Some(&mut Some(0))`.
The case should fail with E0596 error, but it catches the debug assertion instead.

1. For the first `&`: In check_pat_ref(), the value max_ref_mutbl becomes MutblCap::Not ([here](https://github.com/rust-lang/rust/blob/fdd1a3b02687817cea41f6bacae3d5fbed2b2cd0/compiler/rustc_hir_typeck/src/pat.rs#L2394-L2396)). Once max_ref_mutbl becomes Not, it will never be back to MutblCap::Mut.
2. For `&mut`: In peel_off_references(), because Some(x) doesn't have `&` nor `&mut`, `&mut` in `&mut Some(0)` is not consumed then default_binding_mode (def_br) becomes `ByRef::Yes(Mutability::Mut)` (around [here](https://github.com/rust-lang/rust/blob/fdd1a3b02687817cea41f6bacae3d5fbed2b2cd0/compiler/rustc_hir_typeck/src/pat.rs#L519-L536)). This will be inherited to the next step. So this pattern has the mismatch between `def_br=Yes(Mut)` and `max_ref_mutbl=Not` now.
3. For the value `0`: Because of the step 2, the default_binding_mode is `Yes(Mut)`, but max_ref_mutbl is `Not` from the step 1. It causes the assertion error [here](https://github.com/rust-lang/rust/blob/fdd1a3b02687817cea41f6bacae3d5fbed2b2cd0/compiler/rustc_hir_typeck/src/pat.rs#L427-L430).

## What this PR fixes
Step 1 has happened from [this commit](rust-lang@e2f3ce9) by deleting `no_ref_mut_behind_and` from the if block. In my understanding, after RFC3627 is released, step 1 should happen not only 2024 edition but also other editions to track MutblCap value. But for now, it should not happen for non-2024 edition. So I put it back.

NOTE: I think there is another solution - We should return an E0596 error in calc_default_binding_mode() instead of the debug assertion. Since the assertion is caused by the mismatch between `def_br = Yes(Mut)` and `max_ref_mutbl = Not`, but in my understanding this violation is the same as E0596. check_pat_ident() does returns E0596 by a similar reason [here](https://github.com/rust-lang/rust/blob/fdd1a3b02687817cea41f6bacae3d5fbed2b2cd0/compiler/rustc_hir_typeck/src/pat.rs#L837-L856).
  • Loading branch information
workingjubilee authored Feb 8, 2025
2 parents 048a7b0 + ba12489 commit e4de450
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -48,19 +48,19 @@ LL | let &ref mut x = &0;
| ^^^^^^^^^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-errors.rs:35:23
--> $DIR/borrowck-errors.rs:37:23
|
LL | if let &Some(Some(x)) = &Some(&mut Some(0)) {
| ^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-errors.rs:40:11
--> $DIR/borrowck-errors.rs:42:11
|
LL | let &[x] = &&mut [0];
| ^ cannot borrow as mutable

error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
--> $DIR/borrowck-errors.rs:44:20
--> $DIR/borrowck-errors.rs:46:20
|
LL | let [&mut x] = &mut [&mut 0];
| - ^^^^^^^^^^^^^ cannot move out of here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ pub fn main() {
let &ref mut x = &0;
//~^ cannot borrow data in a `&` reference as mutable [E0596]

// For 2021 edition, this is also a regression test for #136223
// since the maximum mutability is downgraded during the pattern check process.
if let &Some(Some(x)) = &Some(&mut Some(0)) {
//[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
let _: &u32 = x;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ LL | let &ref mut x = &0;
| ^^^^^^^^^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-errors.rs:35:23
--> $DIR/borrowck-errors.rs:37:23
|
LL | if let &Some(Some(x)) = &Some(&mut Some(0)) {
| ^ cannot borrow as mutable

error[E0596]: cannot borrow data in a `&` reference as mutable
--> $DIR/borrowck-errors.rs:40:11
--> $DIR/borrowck-errors.rs:42:11
|
LL | let &[x] = &&mut [0];
| ^ cannot borrow as mutable
Expand Down

0 comments on commit e4de450

Please sign in to comment.