about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJules Bertholet <julesbertholet@quoi.xyz>2024-04-05 23:27:29 -0400
committerJules Bertholet <julesbertholet@quoi.xyz>2024-04-15 23:26:22 -0400
commitef1d084c0b5b0ff7143bbca966442cd24151313b (patch)
tree15c2881af2d553bc9ada9f4f5159dca00d187143
parent63f70b3d104e20289a1a0df82747066c3d85b9a1 (diff)
downloadrust-ef1d084c0b5b0ff7143bbca966442cd24151313b.tar.gz
rust-ef1d084c0b5b0ff7143bbca966442cd24151313b.zip
Match ergonomics 2024: `mut` doesn't reset binding mode
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs16
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.rs14
-rw-r--r--tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.stderr31
-rw-r--r--tests/ui/pattern/mut_dont_reset_binding_mode_2021.rs15
-rw-r--r--tests/ui/pattern/mut_dont_reset_binding_mode_2021.stderr31
-rw-r--r--tests/ui/pattern/mut_dont_reset_binding_mode_2024.rs15
8 files changed, 121 insertions, 4 deletions
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e6b19817de3..2a753af9387 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -533,6 +533,8 @@ declare_features! (
     (unstable, more_qualified_paths, "1.54.0", Some(86935)),
     /// Allows the `#[must_not_suspend]` attribute.
     (unstable, must_not_suspend, "1.57.0", Some(83310)),
+    /// Make `mut` not reset the binding mode on edition >= 2024.
+    (unstable, mut_dont_reset_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows `mut ref` and `mut ref mut` identifier patterns.
     (incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
     /// Allows using `#[naked]` on functions.
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index db4bd132b7e..06f6a7f6bf2 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -629,12 +629,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         pat_info: PatInfo<'tcx, '_>,
     ) -> Ty<'tcx> {
-        let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
+        let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
 
         // Determine the binding mode...
         let bm = match ba {
-            BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
-            _ => ba,
+            BindingAnnotation(ByRef::No, Mutability::Mut)
+                if !(pat.span.at_least_rust_2024()
+                    && self.tcx.features().mut_dont_reset_binding_mode_2024)
+                    && matches!(def_br, ByRef::Yes(_)) =>
+            {
+                // `mut x` resets the binding mode in edition <= 2021.
+                BindingAnnotation(ByRef::No, Mutability::Mut)
+            }
+            BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
+            BindingAnnotation(ByRef::Yes(_), _) => ba,
         };
         // ...and store it in a side table:
         self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@@ -743,7 +751,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    // Precondition: pat is a Ref(_) pattern
+    /// Precondition: pat is a `Ref(_)` pattern
     fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
         let tcx = self.tcx;
         if let PatKind::Ref(inner, mutbl) = pat.kind
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index bfd0f77c237..02550fd655c 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1194,6 +1194,7 @@ symbols! {
         multiple_supertrait_upcastable,
         must_not_suspend,
         must_use,
+        mut_dont_reset_binding_mode_2024,
         mut_ref,
         naked,
         naked_functions,
diff --git a/tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.rs b/tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.rs
new file mode 100644
index 00000000000..15c542e6bf1
--- /dev/null
+++ b/tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.rs
@@ -0,0 +1,14 @@
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    a = &42;
+    //~^ ERROR: mismatched types
+
+    let Foo(mut a) = &mut Foo(0);
+    a = &mut 42;
+    //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.stderr b/tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.stderr
new file mode 100644
index 00000000000..1624883de60
--- /dev/null
+++ b/tests/ui/pattern/feature-gate-mut_dont_reset_binding_mode_2024.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-mut_dont_reset_binding_mode_2024.rs:8:9
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &42;
+   |         ^^^ expected `u8`, found `&{integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &42;
+LL +     a = 42;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/feature-gate-mut_dont_reset_binding_mode_2024.rs:12:9
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &mut 42;
+   |         ^^^^^^^ expected `u8`, found `&mut {integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &mut 42;
+LL +     a = 42;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/mut_dont_reset_binding_mode_2021.rs b/tests/ui/pattern/mut_dont_reset_binding_mode_2021.rs
new file mode 100644
index 00000000000..a9e12472734
--- /dev/null
+++ b/tests/ui/pattern/mut_dont_reset_binding_mode_2021.rs
@@ -0,0 +1,15 @@
+//@ edition: 2021
+//@ compile-flags: -Zunstable-options
+#![feature(mut_dont_reset_binding_mode_2024)]
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    a = &42;
+    //~^ ERROR: mismatched types
+
+    let Foo(mut a) = &mut Foo(0);
+    a = &mut 42;
+    //~^ ERROR: mismatched types
+}
diff --git a/tests/ui/pattern/mut_dont_reset_binding_mode_2021.stderr b/tests/ui/pattern/mut_dont_reset_binding_mode_2021.stderr
new file mode 100644
index 00000000000..16818c900b3
--- /dev/null
+++ b/tests/ui/pattern/mut_dont_reset_binding_mode_2021.stderr
@@ -0,0 +1,31 @@
+error[E0308]: mismatched types
+  --> $DIR/mut_dont_reset_binding_mode_2021.rs:9:9
+   |
+LL |     let Foo(mut a) = &Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &42;
+   |         ^^^ expected `u8`, found `&{integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &42;
+LL +     a = 42;
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/mut_dont_reset_binding_mode_2021.rs:13:9
+   |
+LL |     let Foo(mut a) = &mut Foo(0);
+   |             ----- expected due to the type of this binding
+LL |     a = &mut 42;
+   |         ^^^^^^^ expected `u8`, found `&mut {integer}`
+   |
+help: consider removing the borrow
+   |
+LL -     a = &mut 42;
+LL +     a = 42;
+   |
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/mut_dont_reset_binding_mode_2024.rs b/tests/ui/pattern/mut_dont_reset_binding_mode_2024.rs
new file mode 100644
index 00000000000..9ac5ec50c74
--- /dev/null
+++ b/tests/ui/pattern/mut_dont_reset_binding_mode_2024.rs
@@ -0,0 +1,15 @@
+//@ run-pass
+//@ edition: 2024
+//@ compile-flags: -Zunstable-options
+#![feature(mut_dont_reset_binding_mode_2024)]
+#![allow(unused)]
+
+struct Foo(u8);
+
+fn main() {
+    let Foo(mut a) = &Foo(0);
+    a = &42;
+
+    let Foo(mut a) = &mut Foo(0);
+    a = &mut 42;
+}