about summary refs log tree commit diff
diff options
context:
space:
mode:
authordianne <diannes.gm@gmail.com>2025-01-04 22:01:01 -0800
committerdianne <diannes.gm@gmail.com>2025-01-20 16:03:37 -0800
commitc03769524bc52b0761385cab4b0a5c5e8fd96bd7 (patch)
tree5774875144b6f5e4e0438dc1cd9546d7649cb154
parentc57708a58dbb7fbf3605dcc33d03d4e1d33747e3 (diff)
downloadrust-c03769524bc52b0761385cab4b0a5c5e8fd96bd7.tar.gz
rust-c03769524bc52b0761385cab4b0a5c5e8fd96bd7.zip
"structural" ruleset: account for dbm mutability cap in Deref(EatInner) rules
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs7
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr2
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs4
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr8
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr98
6 files changed, 112 insertions, 13 deletions
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index cf9921312d5..1cbeb6d1fd0 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -2344,7 +2344,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 InheritedRefMatchRule::EatInner => {
                     if let ty::Ref(_, _, r_mutbl) = *expected.kind() {
                         // Match against the reference type; don't consume the inherited ref.
-                        pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(r_mutbl);
+                        // NB: For RFC 3627's Rule 3, we limit the default binding mode's ref
+                        // mutability to `pat_info.max_ref_mutbl`. If we implement a pattern typing
+                        // ruleset with Rule 4 but not Rule 3, we'll need to check that here.
+                        debug_assert!(self.downgrade_mut_inside_shared());
+                        let mutbl_cap = cmp::min(r_mutbl, pat_info.max_ref_mutbl.as_mutbl());
+                        pat_info.binding_mode = pat_info.binding_mode.cap_ref_mutability(mutbl_cap);
                     } else {
                         // The expected type isn't a reference, so match against the inherited ref.
                         if pat_mutbl > inh_mut {
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr
index 65b03f7a610..d72539eeeb2 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic.stderr
@@ -46,7 +46,7 @@ LL |     let [&ref x] = &[&mut 0];
    |           +++
 
 error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:31:16
+  --> $DIR/borrowck-errors.rs:30:16
    |
 LL |     let [&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 7645c145b65..60f3a1dc18c 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
@@ -27,8 +27,8 @@ pub fn main() {
     //[classic]~^ ERROR: cannot move out of type
     let _: &u32 = x;
 
-    #[cfg(classic)] // TODO: this should pass on `structural` but doesn't
-    let [&x] = &mut [&mut 0]; //[classic]~ ERROR: cannot move out of type
+    let [&x] = &mut [&mut 0];
+    //[classic]~^ ERROR: cannot move out of type
     let _: &u32 = x;
 
     let [&mut x] = &mut [&mut 0];
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr
index fbb9a35443a..939eb4ea430 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic.stderr
@@ -83,7 +83,7 @@ LL |     if let Some(&Some(x)) = &Some(Some(0)) {
    |                 ~
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:119:10
+  --> $DIR/pattern-errors.rs:125:10
    |
 LL |     let [&mut x] = &[&mut 0];
    |          ^^^^^
@@ -95,7 +95,7 @@ LL |     let [&x] = &[&mut 0];
    |          ~
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:124:10
+  --> $DIR/pattern-errors.rs:130:10
    |
 LL |     let [&mut &x] = &[&mut 0];
    |          ^^^^^
@@ -107,7 +107,7 @@ LL |     let [&&x] = &[&mut 0];
    |          ~
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:129:10
+  --> $DIR/pattern-errors.rs:135:10
    |
 LL |     let [&mut &ref x] = &[&mut 0];
    |          ^^^^^
@@ -119,7 +119,7 @@ LL |     let [&&ref x] = &[&mut 0];
    |          ~
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:134:10
+  --> $DIR/pattern-errors.rs:140:10
    |
 LL |     let [&mut &(mut x)] = &[&mut 0];
    |          ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
index b5e8bd112aa..90f77df871d 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
@@ -96,13 +96,16 @@ fn structural_errors_2() {
     //[structural]~^ ERROR: mismatched types
 
     let [&&mut x] = &mut [&mut 0];
+    //[structural]~^ ERROR: mismatched types
     let _: u32 = x;
+    //[structural]~^ ERROR: mismatched types
 
     let [&&mut ref x] = &[&mut 0];
     //[structural]~^ ERROR: mismatched types
     let _: &u32 = x;
 
     let [&&mut ref x] = &mut [&mut 0];
+    //[structural]~^ ERROR: mismatched types
     let _: &u32 = x;
 
     let [&&mut mut x] = &[&mut 0];
@@ -112,7 +115,10 @@ fn structural_errors_2() {
     //[structural]~^ ERROR: mismatched types
 
     let [&&mut mut x] = &mut [&mut 0];
+    //[structural]~^ ERROR: binding cannot be both mutable and by-reference
+    //[structural]~| ERROR: mismatched types
     let _: u32 = x;
+    //[structural]~^ ERROR: mismatched types
 }
 
 fn classic_errors_0() {
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr
index 4eabb8b1b0a..ed7e09c937a 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural.stderr
@@ -342,7 +342,38 @@ LL |     let _: u32 = *x;
    |                  +
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:101:11
+  --> $DIR/pattern-errors.rs:98:11
+   |
+LL |     let [&&mut x] = &mut [&mut 0];
+   |           ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &mut [&mut 0];
+LL +     let [&x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:100:18
+   |
+LL |     let _: u32 = x;
+   |            ---   ^ expected `u32`, found `&_`
+   |            |
+   |            expected due to this
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider dereferencing the borrow
+   |
+LL |     let _: u32 = *x;
+   |                  +
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:103:11
    |
 LL |     let [&&mut ref x] = &[&mut 0];
    |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -358,7 +389,23 @@ LL +     let [&ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:108:11
+  --> $DIR/pattern-errors.rs:107:11
+   |
+LL |     let [&&mut ref x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &mut [&mut 0];
+LL +     let [&ref x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:111:11
    |
 LL |     let [&&mut mut x] = &[&mut 0];
    |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -374,7 +421,7 @@ LL +     let [&mut x] = &[&mut 0];
    |
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/pattern-errors.rs:108:16
+  --> $DIR/pattern-errors.rs:111:16
    |
 LL |     let [&&mut mut x] = &[&mut 0];
    |                ^^^^
@@ -384,7 +431,48 @@ LL |     let [&&mut mut x] = &[&mut 0];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:111:18
+  --> $DIR/pattern-errors.rs:114:18
+   |
+LL |     let _: u32 = x;
+   |            ---   ^ expected `u32`, found `&_`
+   |            |
+   |            expected due to this
+   |
+   = note:   expected type `u32`
+           found reference `&_`
+help: consider dereferencing the borrow
+   |
+LL |     let _: u32 = *x;
+   |                  +
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:117:11
+   |
+LL |     let [&&mut mut x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &mut [&mut 0];
+LL +     let [&mut x] = &mut [&mut 0];
+   |
+
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/pattern-errors.rs:117:16
+   |
+LL |     let [&&mut mut x] = &mut [&mut 0];
+   |                ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:120:18
    |
 LL |     let _: u32 = x;
    |            ---   ^ expected `u32`, found `&_`
@@ -398,7 +486,7 @@ help: consider dereferencing the borrow
 LL |     let _: u32 = *x;
    |                  +
 
-error: aborting due to 27 previous errors
+error: aborting due to 33 previous errors
 
 Some errors have detailed explanations: E0308, E0658.
 For more information about an error, try `rustc --explain E0308`.