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; +}