about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJules Bertholet <julesbertholet@quoi.xyz>2024-05-15 16:55:54 -0400
committerJules Bertholet <julesbertholet@quoi.xyz>2024-05-15 16:55:54 -0400
commit0746577fa27f2a322f3ab5f4e85c6eeb51c6fc6c (patch)
tree4f1999548a347cc6067d7c95677a09779e882038
parenteb91f3b0513acf34701d8598c1312875c6e489a5 (diff)
downloadrust-0746577fa27f2a322f3ab5f4e85c6eeb51c6fc6c.tar.gz
rust-0746577fa27f2a322f3ab5f4e85c6eeb51c6fc6c.zip
Gate implicit mutable by-reference bindings behind `mut ref`
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs34
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs10
-rw-r--r--tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr25
-rw-r--r--tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs14
-rw-r--r--tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr31
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.fixed2
-rw-r--r--tests/ui/pattern/match_ergonomics_2024.rs2
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2021.rs2
-rw-r--r--tests/ui/pattern/mut_preserve_binding_mode_2024.rs2
11 files changed, 61 insertions, 65 deletions
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index f1afde31803..aea447b2aff 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -128,6 +128,8 @@ declare_features! (
     /// Allows the use of type alias impl trait in function return positions
     (removed, min_type_alias_impl_trait, "1.56.0", Some(63063),
      Some("removed in favor of full type_alias_impl_trait")),
+    /// Make `mut` not reset the binding mode on edition >= 2024.
+    (removed, mut_preserve_binding_mode_2024, "1.79.0", Some(123076), Some("superseded by `ref_pat_eat_one_layer_2024`")),
     (removed, needs_allocator, "1.4.0", Some(27389),
      Some("subsumed by `#![feature(allocator_internals)]`")),
     /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 1a058a121f3..a4ccb0f1412 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -527,8 +527,6 @@ 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.
-    (incomplete, mut_preserve_binding_mode_2024, "1.79.0", Some(123076)),
     /// Allows `mut ref` and `mut ref mut` identifier patterns.
     (incomplete, mut_ref, "1.79.0", 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 6cd74961cc7..8e3b19f79a5 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -12,7 +12,7 @@ use rustc_infer::infer;
 use rustc_middle::mir::interpret::ErrorHandled;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt};
 use rustc_middle::{bug, span_bug};
-use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
+use rustc_session::{lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS, parse::feature_err};
 use rustc_span::edit_distance::find_best_match_for_name;
 use rustc_span::hygiene::DesugaringKind;
 use rustc_span::source_map::Spanned;
@@ -669,17 +669,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Determine the binding mode...
         let bm = match user_bind_annot {
-            // `mut` resets binding mode on edition <= 2021
-            BindingMode(ByRef::No, Mutability::Mut)
-                if !(pat.span.at_least_rust_2024()
-                    && self.tcx.features().mut_preserve_binding_mode_2024)
-                    && matches!(def_br, ByRef::Yes(_)) =>
-            {
-                self.typeck_results
-                    .borrow_mut()
-                    .rust_2024_migration_desugared_pats_mut()
-                    .insert(pat_info.top_info.hir_id);
-                BindingMode(ByRef::No, Mutability::Mut)
+            BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => {
+                if pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024 {
+                    if !self.tcx.features().mut_ref {
+                        feature_err(
+                            &self.tcx.sess,
+                            sym::mut_ref,
+                            pat.span.until(ident.span),
+                            "binding cannot be both mutable and by-reference",
+                        )
+                        .emit();
+                    }
+
+                    BindingMode(def_br, Mutability::Mut)
+                } else {
+                    // `mut` resets binding mode on edition <= 2021
+                    self.typeck_results
+                        .borrow_mut()
+                        .rust_2024_migration_desugared_pats_mut()
+                        .insert(pat_info.top_info.hir_id);
+                    BindingMode(ByRef::No, Mutability::Mut)
+                }
             }
             BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
             BindingMode(ByRef::Yes(_), _) => user_bind_annot,
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
index a2a0c73b53b..40e8293e241 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs
@@ -49,4 +49,14 @@ pub fn main() {
 
     let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
     //~^ ERROR: mismatched types
+
+    struct Foo(u8);
+
+    let Foo(mut a) = &Foo(0);
+    //~^ ERROR: binding cannot be both mutable and by-reference
+    a = &42;
+
+    let Foo(mut a) = &mut Foo(0);
+    //~^ ERROR: binding cannot be both mutable and by-reference
+    a = &mut 42;
 }
diff --git a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
index cad67b4f8d6..26317e43d02 100644
--- a/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
+++ b/tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr
@@ -152,6 +152,27 @@ LL |     let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
    = note:      expected reference `&&&&mut &&&mut &mut {integer}`
            found mutable reference `&mut _`
 
-error: aborting due to 14 previous errors
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:55:13
+   |
+LL |     let Foo(mut a) = &Foo(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[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/ref_pat_eat_one_layer_2024_fail.rs:59:13
+   |
+LL |     let Foo(mut a) = &mut Foo(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: aborting due to 16 previous errors
 
-For more information about this error, try `rustc --explain E0308`.
+Some errors have detailed explanations: E0308, E0658.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs
deleted file mode 100644
index 15c542e6bf1..00000000000
--- a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-//@ 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_preserve_binding_mode_2024.stderr b/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr
deleted file mode 100644
index 6d0a034be21..00000000000
--- a/tests/ui/pattern/feature-gate-mut_preserve_binding_mode_2024.stderr
+++ /dev/null
@@ -1,31 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/feature-gate-mut_preserve_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_preserve_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/match_ergonomics_2024.fixed b/tests/ui/pattern/match_ergonomics_2024.fixed
index d8dbcb217c0..1ec2b5a214b 100644
--- a/tests/ui/pattern/match_ergonomics_2024.fixed
+++ b/tests/ui/pattern/match_ergonomics_2024.fixed
@@ -2,7 +2,7 @@
 //@ run-rustfix
 //@ rustfix-only-machine-applicable
 //@ aux-build:match_ergonomics_2024_macros.rs
-#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)]
+#![feature(mut_ref, ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features, unused)]
 #![deny(rust_2024_incompatible_pat)]
 
diff --git a/tests/ui/pattern/match_ergonomics_2024.rs b/tests/ui/pattern/match_ergonomics_2024.rs
index 38dc0c8bebb..c9f992c12d4 100644
--- a/tests/ui/pattern/match_ergonomics_2024.rs
+++ b/tests/ui/pattern/match_ergonomics_2024.rs
@@ -2,7 +2,7 @@
 //@ run-rustfix
 //@ rustfix-only-machine-applicable
 //@ aux-build:match_ergonomics_2024_macros.rs
-#![feature(mut_preserve_binding_mode_2024, ref_pat_eat_one_layer_2024)]
+#![feature(mut_ref, ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features, unused)]
 #![deny(rust_2024_incompatible_pat)]
 
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
index befa49fdc24..282e0ef95d2 100644
--- a/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2021.rs
@@ -1,6 +1,6 @@
 //@ edition: 2021
 //@ compile-flags: -Zunstable-options
-#![feature(mut_preserve_binding_mode_2024)]
+#![feature(ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features)]
 
 struct Foo(u8);
diff --git a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
index 5454962e16c..19aa73573b4 100644
--- a/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
+++ b/tests/ui/pattern/mut_preserve_binding_mode_2024.rs
@@ -1,7 +1,7 @@
 //@ run-pass
 //@ edition: 2024
 //@ compile-flags: -Zunstable-options
-#![feature(mut_preserve_binding_mode_2024)]
+#![feature(mut_ref, ref_pat_eat_one_layer_2024)]
 #![allow(incomplete_features, unused)]
 
 struct Foo(u8);