Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit ef1d084

Browse files
Match ergonomics 2024: mut doesn't reset binding mode
1 parent 63f70b3 commit ef1d084

File tree

8 files changed

+121
-4
lines changed

8 files changed

+121
-4
lines changed

compiler/rustc_feature/src/unstable.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,8 @@ declare_features! (
533533
(unstable, more_qualified_paths, "1.54.0", Some(86935)),
534534
/// Allows the `#[must_not_suspend]` attribute.
535535
(unstable, must_not_suspend, "1.57.0", Some(83310)),
536+
/// Make `mut` not reset the binding mode on edition >= 2024.
537+
(unstable, mut_dont_reset_binding_mode_2024, "CURRENT_RUSTC_VERSION", Some(123076)),
536538
/// Allows `mut ref` and `mut ref mut` identifier patterns.
537539
(incomplete, mut_ref, "CURRENT_RUSTC_VERSION", Some(123076)),
538540
/// Allows using `#[naked]` on functions.

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -629,12 +629,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
629629
expected: Ty<'tcx>,
630630
pat_info: PatInfo<'tcx, '_>,
631631
) -> Ty<'tcx> {
632-
let PatInfo { binding_mode: def_bm, top_info: ti, .. } = pat_info;
632+
let PatInfo { binding_mode: BindingAnnotation(def_br, _), top_info: ti, .. } = pat_info;
633633

634634
// Determine the binding mode...
635635
let bm = match ba {
636-
BindingAnnotation(ByRef::No, Mutability::Not) => def_bm,
637-
_ => ba,
636+
BindingAnnotation(ByRef::No, Mutability::Mut)
637+
if !(pat.span.at_least_rust_2024()
638+
&& self.tcx.features().mut_dont_reset_binding_mode_2024)
639+
&& matches!(def_br, ByRef::Yes(_)) =>
640+
{
641+
// `mut x` resets the binding mode in edition <= 2021.
642+
BindingAnnotation(ByRef::No, Mutability::Mut)
643+
}
644+
BindingAnnotation(ByRef::No, mutbl) => BindingAnnotation(def_br, mutbl),
645+
BindingAnnotation(ByRef::Yes(_), _) => ba,
638646
};
639647
// ...and store it in a side table:
640648
self.typeck_results.borrow_mut().pat_binding_modes_mut().insert(pat.hir_id, bm);
@@ -743,7 +751,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
743751
}
744752
}
745753

746-
// Precondition: pat is a Ref(_) pattern
754+
/// Precondition: pat is a `Ref(_)` pattern
747755
fn borrow_pat_suggestion(&self, err: &mut Diag<'_>, pat: &Pat<'_>) {
748756
let tcx = self.tcx;
749757
if let PatKind::Ref(inner, mutbl) = pat.kind

compiler/rustc_span/src/symbol.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1194,6 +1194,7 @@ symbols! {
11941194
multiple_supertrait_upcastable,
11951195
must_not_suspend,
11961196
must_use,
1197+
mut_dont_reset_binding_mode_2024,
11971198
mut_ref,
11981199
naked,
11991200
naked_functions,
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
4+
struct Foo(u8);
5+
6+
fn main() {
7+
let Foo(mut a) = &Foo(0);
8+
a = &42;
9+
//~^ ERROR: mismatched types
10+
11+
let Foo(mut a) = &mut Foo(0);
12+
a = &mut 42;
13+
//~^ ERROR: mismatched types
14+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/feature-gate-mut_dont_reset_binding_mode_2024.rs:8:9
3+
|
4+
LL | let Foo(mut a) = &Foo(0);
5+
| ----- expected due to the type of this binding
6+
LL | a = &42;
7+
| ^^^ expected `u8`, found `&{integer}`
8+
|
9+
help: consider removing the borrow
10+
|
11+
LL - a = &42;
12+
LL + a = 42;
13+
|
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/feature-gate-mut_dont_reset_binding_mode_2024.rs:12:9
17+
|
18+
LL | let Foo(mut a) = &mut Foo(0);
19+
| ----- expected due to the type of this binding
20+
LL | a = &mut 42;
21+
| ^^^^^^^ expected `u8`, found `&mut {integer}`
22+
|
23+
help: consider removing the borrow
24+
|
25+
LL - a = &mut 42;
26+
LL + a = 42;
27+
|
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ edition: 2021
2+
//@ compile-flags: -Zunstable-options
3+
#![feature(mut_dont_reset_binding_mode_2024)]
4+
5+
struct Foo(u8);
6+
7+
fn main() {
8+
let Foo(mut a) = &Foo(0);
9+
a = &42;
10+
//~^ ERROR: mismatched types
11+
12+
let Foo(mut a) = &mut Foo(0);
13+
a = &mut 42;
14+
//~^ ERROR: mismatched types
15+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/mut_dont_reset_binding_mode_2021.rs:9:9
3+
|
4+
LL | let Foo(mut a) = &Foo(0);
5+
| ----- expected due to the type of this binding
6+
LL | a = &42;
7+
| ^^^ expected `u8`, found `&{integer}`
8+
|
9+
help: consider removing the borrow
10+
|
11+
LL - a = &42;
12+
LL + a = 42;
13+
|
14+
15+
error[E0308]: mismatched types
16+
--> $DIR/mut_dont_reset_binding_mode_2021.rs:13:9
17+
|
18+
LL | let Foo(mut a) = &mut Foo(0);
19+
| ----- expected due to the type of this binding
20+
LL | a = &mut 42;
21+
| ^^^^^^^ expected `u8`, found `&mut {integer}`
22+
|
23+
help: consider removing the borrow
24+
|
25+
LL - a = &mut 42;
26+
LL + a = 42;
27+
|
28+
29+
error: aborting due to 2 previous errors
30+
31+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ run-pass
2+
//@ edition: 2024
3+
//@ compile-flags: -Zunstable-options
4+
#![feature(mut_dont_reset_binding_mode_2024)]
5+
#![allow(unused)]
6+
7+
struct Foo(u8);
8+
9+
fn main() {
10+
let Foo(mut a) = &Foo(0);
11+
a = &42;
12+
13+
let Foo(mut a) = &mut Foo(0);
14+
a = &mut 42;
15+
}

0 commit comments

Comments
 (0)