about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJubilee <workingjubilee@gmail.com>2025-02-08 20:41:20 -0800
committerGitHub <noreply@github.com>2025-02-08 20:41:20 -0800
commitef22c14dfb0192ed779f9fc156604a1bec19a5d3 (patch)
tree7f377b9d4fb6f141611b4ecfde9e19e015b866c6
parent43ca9d18e333797f0aa3b525501a7cec8d61a96b (diff)
parentba124898c06d9d0ba562b6bb353d841b22a2571c (diff)
downloadrust-ef22c14dfb0192ed779f9fc156604a1bec19a5d3.tar.gz
rust-ef22c14dfb0192ed779f9fc156604a1bec19a5d3.zip
Rollup merge of #136397 - Shunpoco:issue-136223-ICE-pattern-mutability-cap-violated, r=Nadrieril
Add a comment pointing to ICE-136223

Fixes #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](https://github.com/rust-lang/rust/commit/e2f3ce956809dd98adf271afe0b024c7febdf47f) 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).
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs2
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr4
3 files changed, 7 insertions, 5 deletions
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
index 331b86736a0..1c446178308 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
@@ -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
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
index 3f5d9c8db5d..59cafc50d86 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
@@ -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;
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
index 65c98e2da9c..deefe21ca7d 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
@@ -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