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 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 -For more information about this error, try `rustc --explain E0308`. +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 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 + +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);