Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit c1ed1f1

Browse files
authoredOct 16, 2024
Rollup merge of #131381 - Nadrieril:min-match-ergonomics, r=pnkfelix
Implement edition 2024 match ergonomics restrictions This implements the minimalest version of [match ergonomics for edition 2024](https://rust-lang.github.io/rfcs/3627-match-ergonomics-2024.html). This minimal version makes it an error to ever reset the default binding mode. The implemented proposal is described precisely [here](https://hackmd.io/zUqs2ISNQ0Wrnxsa9nhD0Q#RFC-3627-nano), where it is called "RFC 3627-nano". Rules: - Rule 1C: When the DBM (default binding mode) is not `move` (whether or not behind a reference), writing `mut`, `ref`, or `ref mut` on a binding is an error. - Rule 2C: Reference patterns can only match against references in the scrutinee when the DBM is `move`. This minimal version is forward-compatible with the main proposals for match ergonomics 2024: [RFC3627](https://rust-lang.github.io/rfcs/3627-match-ergonomics-2024.html) itself, the alternative [rule 4-early variant](https://rust-lang.github.io/rfcs/3627-match-ergonomics-2024.html), and [others](https://hackmd.io/zUqs2ISNQ0Wrnxsa9nhD0Q). The idea is to give us more time to iron out a final proposal. This includes a migration lint that desugars any offending pattern into one that doesn't make use of match ergonomics. Such patterns have identical meaning across editions. This PR insta-stabilizes the proposed behavior onto edition 2024. r? `@ghost` Tracking: - #123076
2 parents 1817de6 + 2ef0a8f commit c1ed1f1

File tree

17 files changed

+757
-242
lines changed

17 files changed

+757
-242
lines changed
 

‎compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -690,16 +690,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
690690

691691
BindingMode(def_br, Mutability::Mut)
692692
} else {
693-
// `mut` resets binding mode on edition <= 2021
694-
self.typeck_results
693+
// `mut` resets the binding mode on edition <= 2021
694+
*self
695+
.typeck_results
695696
.borrow_mut()
696697
.rust_2024_migration_desugared_pats_mut()
697-
.insert(pat_info.top_info.hir_id);
698+
.entry(pat_info.top_info.hir_id)
699+
.or_default() |= pat.span.at_least_rust_2024();
698700
BindingMode(ByRef::No, Mutability::Mut)
699701
}
700702
}
701703
BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
702-
BindingMode(ByRef::Yes(_), _) => user_bind_annot,
704+
BindingMode(ByRef::Yes(_), _) => {
705+
if matches!(def_br, ByRef::Yes(_)) {
706+
// `ref`/`ref mut` overrides the binding mode on edition <= 2021
707+
*self
708+
.typeck_results
709+
.borrow_mut()
710+
.rust_2024_migration_desugared_pats_mut()
711+
.entry(pat_info.top_info.hir_id)
712+
.or_default() |= pat.span.at_least_rust_2024();
713+
}
714+
user_bind_annot
715+
}
703716
};
704717

705718
if bm.0 == ByRef::Yes(Mutability::Mut)
@@ -2204,14 +2217,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22042217
}
22052218
} else {
22062219
// Reset binding mode on old editions
2207-
22082220
if pat_info.binding_mode != ByRef::No {
22092221
pat_info.binding_mode = ByRef::No;
2210-
2211-
self.typeck_results
2222+
*self
2223+
.typeck_results
22122224
.borrow_mut()
22132225
.rust_2024_migration_desugared_pats_mut()
2214-
.insert(pat_info.top_info.hir_id);
2226+
.entry(pat_info.top_info.hir_id)
2227+
.or_default() |= pat.span.at_least_rust_2024();
22152228
}
22162229
}
22172230

@@ -2262,6 +2275,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
22622275
(err, err)
22632276
}
22642277
};
2278+
22652279
self.check_pat(inner, inner_ty, pat_info);
22662280
ref_ty
22672281
}

‎compiler/rustc_hir_typeck/src/writeback.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
635635

636636
#[instrument(skip(self), level = "debug")]
637637
fn visit_rust_2024_migration_desugared_pats(&mut self, hir_id: hir::HirId) {
638-
if self
638+
if let Some(is_hard_error) = self
639639
.fcx
640640
.typeck_results
641641
.borrow_mut()
@@ -645,7 +645,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
645645
debug!(
646646
"node is a pat whose match ergonomics are desugared by the Rust 2024 migration lint"
647647
);
648-
self.typeck_results.rust_2024_migration_desugared_pats_mut().insert(hir_id);
648+
self.typeck_results
649+
.rust_2024_migration_desugared_pats_mut()
650+
.insert(hir_id, is_hard_error);
649651
}
650652
}
651653

‎compiler/rustc_lint_defs/src/builtin.rs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,7 +1651,6 @@ declare_lint! {
16511651
/// ### Example
16521652
///
16531653
/// ```rust,edition2021
1654-
/// #![feature(ref_pat_eat_one_layer_2024)]
16551654
/// #![warn(rust_2024_incompatible_pat)]
16561655
///
16571656
/// if let Some(&a) = &Some(&0u8) {
@@ -1672,12 +1671,10 @@ declare_lint! {
16721671
pub RUST_2024_INCOMPATIBLE_PAT,
16731672
Allow,
16741673
"detects patterns whose meaning will change in Rust 2024",
1675-
@feature_gate = ref_pat_eat_one_layer_2024;
1676-
// FIXME uncomment below upon stabilization
1677-
/*@future_incompatible = FutureIncompatibleInfo {
1674+
@future_incompatible = FutureIncompatibleInfo {
16781675
reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
16791676
reference: "123076",
1680-
};*/
1677+
};
16811678
}
16821679

16831680
declare_lint! {

‎compiler/rustc_middle/src/ty/typeck_results.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ pub struct TypeckResults<'tcx> {
7373
/// Stores the actual binding mode for all instances of [`BindingMode`].
7474
pat_binding_modes: ItemLocalMap<BindingMode>,
7575

76-
/// Top-level patterns whose match ergonomics need to be desugared
77-
/// by the Rust 2021 -> 2024 migration lint.
78-
rust_2024_migration_desugared_pats: ItemLocalSet,
76+
/// Top-level patterns whose match ergonomics need to be desugared by the Rust 2021 -> 2024
77+
/// migration lint. The boolean indicates whether the emitted diagnostic should be a hard error
78+
/// (if any of the incompatible pattern elements are in edition 2024).
79+
rust_2024_migration_desugared_pats: ItemLocalMap<bool>,
7980

8081
/// Stores the types which were implicitly dereferenced in pattern binding modes
8182
/// for later usage in THIR lowering. For example,
@@ -418,15 +419,15 @@ impl<'tcx> TypeckResults<'tcx> {
418419
LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments }
419420
}
420421

421-
pub fn rust_2024_migration_desugared_pats(&self) -> LocalSetInContext<'_> {
422-
LocalSetInContext {
422+
pub fn rust_2024_migration_desugared_pats(&self) -> LocalTableInContext<'_, bool> {
423+
LocalTableInContext {
423424
hir_owner: self.hir_owner,
424425
data: &self.rust_2024_migration_desugared_pats,
425426
}
426427
}
427428

428-
pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalSetInContextMut<'_> {
429-
LocalSetInContextMut {
429+
pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalTableInContextMut<'_, bool> {
430+
LocalTableInContextMut {
430431
hir_owner: self.hir_owner,
431432
data: &mut self.rust_2024_migration_desugared_pats,
432433
}

‎compiler/rustc_mir_build/messages.ftl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,7 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from
265265
266266
mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
267267
268-
mir_build_rust_2024_incompatible_pat = the semantics of this pattern will change in edition 2024
268+
mir_build_rust_2024_incompatible_pat = patterns are not allowed to reset the default binding mode in edition 2024
269269
270270
mir_build_rustc_box_attribute_error = `#[rustc_box]` attribute used incorrectly
271271
.attributes = no other attributes may be applied

‎compiler/rustc_mir_build/src/errors.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,8 @@ pub(crate) struct Rust2024IncompatiblePat {
983983

984984
pub(crate) struct Rust2024IncompatiblePatSugg {
985985
pub(crate) suggestion: Vec<(Span, String)>,
986+
/// Whether the incompatibility is a hard error because a relevant span is in edition 2024.
987+
pub(crate) is_hard_error: bool,
986988
}
987989

988990
impl Subdiagnostic for Rust2024IncompatiblePatSugg {

‎compiler/rustc_mir_build/src/thir/pattern/mod.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use tracing::{debug, instrument};
2525

2626
pub(crate) use self::check_match::check_match;
2727
use crate::errors::*;
28+
use crate::fluent_generated as fluent;
2829
use crate::thir::util::UserAnnotatedTyHelpers;
2930

3031
struct PatCtxt<'a, 'tcx> {
@@ -48,18 +49,28 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
4849
typeck_results,
4950
rust_2024_migration_suggestion: typeck_results
5051
.rust_2024_migration_desugared_pats()
51-
.contains(pat.hir_id)
52-
.then_some(Rust2024IncompatiblePatSugg { suggestion: Vec::new() }),
52+
.get(pat.hir_id)
53+
.map(|&is_hard_error| Rust2024IncompatiblePatSugg {
54+
suggestion: Vec::new(),
55+
is_hard_error,
56+
}),
5357
};
5458
let result = pcx.lower_pattern(pat);
5559
debug!("pat_from_hir({:?}) = {:?}", pat, result);
5660
if let Some(sugg) = pcx.rust_2024_migration_suggestion {
57-
tcx.emit_node_span_lint(
58-
lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
59-
pat.hir_id,
60-
pat.span,
61-
Rust2024IncompatiblePat { sugg },
62-
);
61+
if sugg.is_hard_error {
62+
let mut err =
63+
tcx.dcx().struct_span_err(pat.span, fluent::mir_build_rust_2024_incompatible_pat);
64+
err.subdiagnostic(sugg);
65+
err.emit();
66+
} else {
67+
tcx.emit_node_span_lint(
68+
lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
69+
pat.hir_id,
70+
pat.span,
71+
Rust2024IncompatiblePat { sugg },
72+
);
73+
}
6374
}
6475
result
6576
}

‎tests/ui/pattern/match_ergonomics_2024.fixed

Lines changed: 0 additions & 57 deletions
This file was deleted.

‎tests/ui/pattern/match_ergonomics_2024.rs

Lines changed: 0 additions & 57 deletions
This file was deleted.

‎tests/ui/pattern/match_ergonomics_2024.stderr

Lines changed: 0 additions & 97 deletions
This file was deleted.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//@ edition: 2021
2+
//@ run-rustfix
3+
//@ rustfix-only-machine-applicable
4+
//@ aux-build:migration_lint_macros.rs
5+
#![feature(mut_ref)]
6+
#![allow(incomplete_features, unused)]
7+
#![deny(rust_2024_incompatible_pat)]
8+
9+
extern crate migration_lint_macros;
10+
11+
struct Foo<T>(T);
12+
13+
// Tests type equality in a way that avoids coercing `&&T` to `&T`.
14+
trait Eq<T> {}
15+
impl<T> Eq<T> for T {}
16+
fn assert_type_eq<T, U: Eq<T>>(_: T, _: U) {}
17+
18+
fn main() {
19+
let Foo(x) = &Foo(0);
20+
assert_type_eq(x, &0u8);
21+
22+
let Foo(x) = &mut Foo(0);
23+
assert_type_eq(x, &mut 0u8);
24+
25+
let &Foo(mut x) = &Foo(0);
26+
//~^ ERROR: patterns are not allowed to reset the default binding mode
27+
//~| WARN: this changes meaning in Rust 2024
28+
assert_type_eq(x, 0u8);
29+
30+
let &mut Foo(mut x) = &mut Foo(0);
31+
//~^ ERROR: patterns are not allowed to reset the default binding mode
32+
//~| WARN: this changes meaning in Rust 2024
33+
assert_type_eq(x, 0u8);
34+
35+
let &Foo(ref x) = &Foo(0);
36+
//~^ ERROR: patterns are not allowed to reset the default binding mode
37+
//~| WARN: this changes meaning in Rust 2024
38+
assert_type_eq(x, &0u8);
39+
40+
let &mut Foo(ref x) = &mut Foo(0);
41+
//~^ ERROR: patterns are not allowed to reset the default binding mode
42+
//~| WARN: this changes meaning in Rust 2024
43+
assert_type_eq(x, &0u8);
44+
45+
let &Foo(x) = &Foo(0);
46+
assert_type_eq(x, 0u8);
47+
48+
let &mut Foo(x) = &mut Foo(0);
49+
assert_type_eq(x, 0u8);
50+
51+
let &Foo(x) = &Foo(&0);
52+
assert_type_eq(x, &0u8);
53+
54+
let &mut Foo(x) = &mut Foo(&0);
55+
assert_type_eq(x, &0u8);
56+
57+
let &Foo(&x) = &Foo(&0);
58+
//~^ ERROR: patterns are not allowed to reset the default binding mode
59+
//~| WARN: this changes meaning in Rust 2024
60+
assert_type_eq(x, 0u8);
61+
62+
let &Foo(&mut x) = &Foo(&mut 0);
63+
//~^ ERROR: patterns are not allowed to reset the default binding mode
64+
//~| WARN: this changes meaning in Rust 2024
65+
assert_type_eq(x, 0u8);
66+
67+
let &mut Foo(&x) = &mut Foo(&0);
68+
//~^ ERROR: patterns are not allowed to reset the default binding mode
69+
//~| WARN: this changes meaning in Rust 2024
70+
assert_type_eq(x, 0u8);
71+
72+
let &mut Foo(&mut x) = &mut Foo(&mut 0);
73+
//~^ ERROR: patterns are not allowed to reset the default binding mode
74+
//~| WARN: this changes meaning in Rust 2024
75+
assert_type_eq(x, 0u8);
76+
77+
if let Some(x) = &&&&&Some(&0u8) {
78+
assert_type_eq(x, &&0u8);
79+
}
80+
81+
if let &&&&&Some(&x) = &&&&&Some(&0u8) {
82+
//~^ ERROR: patterns are not allowed to reset the default binding mode
83+
//~| WARN: this changes meaning in Rust 2024
84+
assert_type_eq(x, 0u8);
85+
}
86+
87+
if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) {
88+
//~^ ERROR: patterns are not allowed to reset the default binding mode
89+
//~| WARN: this changes meaning in Rust 2024
90+
assert_type_eq(x, 0u8);
91+
}
92+
93+
if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) {
94+
//~^ ERROR: patterns are not allowed to reset the default binding mode
95+
//~| WARN: this changes meaning in Rust 2024
96+
assert_type_eq(x, 0u8);
97+
}
98+
99+
if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) {
100+
//~^ ERROR: patterns are not allowed to reset the default binding mode
101+
//~| WARN: this changes meaning in Rust 2024
102+
assert_type_eq(x, &mut 0u8);
103+
}
104+
105+
struct Struct<A, B, C> {
106+
a: A,
107+
b: B,
108+
c: C,
109+
}
110+
111+
let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 };
112+
//~^ ERROR: patterns are not allowed to reset the default binding mode
113+
//~| WARN: this changes meaning in Rust 2024
114+
assert_type_eq(a, &0u32);
115+
assert_type_eq(b, 0u32);
116+
117+
let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 };
118+
//~^ ERROR: patterns are not allowed to reset the default binding mode
119+
//~| WARN: this changes meaning in Rust 2024
120+
assert_type_eq(a, 0u32);
121+
assert_type_eq(b, &&0u32);
122+
assert_type_eq(c, &&0u32);
123+
124+
if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } =
125+
//~^ ERROR: patterns are not allowed to reset the default binding mode
126+
//~| WARN: this changes meaning in Rust 2024
127+
&(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) })
128+
{
129+
assert_type_eq(a, &0u32);
130+
assert_type_eq(b, 0u32);
131+
assert_type_eq(c, &&0u32);
132+
}
133+
134+
match &(Some(0), Some(0)) {
135+
// The two patterns are the same syntactically, but because they're defined in different
136+
// editions they don't mean the same thing.
137+
&(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
138+
//~^ ERROR: patterns are not allowed to reset the default binding mode
139+
assert_type_eq(x, 0u32);
140+
assert_type_eq(y, 0u32);
141+
}
142+
_ => {}
143+
}
144+
}
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
//@ edition: 2021
2+
//@ run-rustfix
3+
//@ rustfix-only-machine-applicable
4+
//@ aux-build:migration_lint_macros.rs
5+
#![feature(mut_ref)]
6+
#![allow(incomplete_features, unused)]
7+
#![deny(rust_2024_incompatible_pat)]
8+
9+
extern crate migration_lint_macros;
10+
11+
struct Foo<T>(T);
12+
13+
// Tests type equality in a way that avoids coercing `&&T` to `&T`.
14+
trait Eq<T> {}
15+
impl<T> Eq<T> for T {}
16+
fn assert_type_eq<T, U: Eq<T>>(_: T, _: U) {}
17+
18+
fn main() {
19+
let Foo(x) = &Foo(0);
20+
assert_type_eq(x, &0u8);
21+
22+
let Foo(x) = &mut Foo(0);
23+
assert_type_eq(x, &mut 0u8);
24+
25+
let Foo(mut x) = &Foo(0);
26+
//~^ ERROR: patterns are not allowed to reset the default binding mode
27+
//~| WARN: this changes meaning in Rust 2024
28+
assert_type_eq(x, 0u8);
29+
30+
let Foo(mut x) = &mut Foo(0);
31+
//~^ ERROR: patterns are not allowed to reset the default binding mode
32+
//~| WARN: this changes meaning in Rust 2024
33+
assert_type_eq(x, 0u8);
34+
35+
let Foo(ref x) = &Foo(0);
36+
//~^ ERROR: patterns are not allowed to reset the default binding mode
37+
//~| WARN: this changes meaning in Rust 2024
38+
assert_type_eq(x, &0u8);
39+
40+
let Foo(ref x) = &mut Foo(0);
41+
//~^ ERROR: patterns are not allowed to reset the default binding mode
42+
//~| WARN: this changes meaning in Rust 2024
43+
assert_type_eq(x, &0u8);
44+
45+
let &Foo(x) = &Foo(0);
46+
assert_type_eq(x, 0u8);
47+
48+
let &mut Foo(x) = &mut Foo(0);
49+
assert_type_eq(x, 0u8);
50+
51+
let &Foo(x) = &Foo(&0);
52+
assert_type_eq(x, &0u8);
53+
54+
let &mut Foo(x) = &mut Foo(&0);
55+
assert_type_eq(x, &0u8);
56+
57+
let Foo(&x) = &Foo(&0);
58+
//~^ ERROR: patterns are not allowed to reset the default binding mode
59+
//~| WARN: this changes meaning in Rust 2024
60+
assert_type_eq(x, 0u8);
61+
62+
let Foo(&mut x) = &Foo(&mut 0);
63+
//~^ ERROR: patterns are not allowed to reset the default binding mode
64+
//~| WARN: this changes meaning in Rust 2024
65+
assert_type_eq(x, 0u8);
66+
67+
let Foo(&x) = &mut Foo(&0);
68+
//~^ ERROR: patterns are not allowed to reset the default binding mode
69+
//~| WARN: this changes meaning in Rust 2024
70+
assert_type_eq(x, 0u8);
71+
72+
let Foo(&mut x) = &mut Foo(&mut 0);
73+
//~^ ERROR: patterns are not allowed to reset the default binding mode
74+
//~| WARN: this changes meaning in Rust 2024
75+
assert_type_eq(x, 0u8);
76+
77+
if let Some(x) = &&&&&Some(&0u8) {
78+
assert_type_eq(x, &&0u8);
79+
}
80+
81+
if let Some(&x) = &&&&&Some(&0u8) {
82+
//~^ ERROR: patterns are not allowed to reset the default binding mode
83+
//~| WARN: this changes meaning in Rust 2024
84+
assert_type_eq(x, 0u8);
85+
}
86+
87+
if let Some(&mut x) = &&&&&Some(&mut 0u8) {
88+
//~^ ERROR: patterns are not allowed to reset the default binding mode
89+
//~| WARN: this changes meaning in Rust 2024
90+
assert_type_eq(x, 0u8);
91+
}
92+
93+
if let Some(&x) = &&&&&mut Some(&0u8) {
94+
//~^ ERROR: patterns are not allowed to reset the default binding mode
95+
//~| WARN: this changes meaning in Rust 2024
96+
assert_type_eq(x, 0u8);
97+
}
98+
99+
if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
100+
//~^ ERROR: patterns are not allowed to reset the default binding mode
101+
//~| WARN: this changes meaning in Rust 2024
102+
assert_type_eq(x, &mut 0u8);
103+
}
104+
105+
struct Struct<A, B, C> {
106+
a: A,
107+
b: B,
108+
c: C,
109+
}
110+
111+
let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
112+
//~^ ERROR: patterns are not allowed to reset the default binding mode
113+
//~| WARN: this changes meaning in Rust 2024
114+
assert_type_eq(a, &0u32);
115+
assert_type_eq(b, 0u32);
116+
117+
let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
118+
//~^ ERROR: patterns are not allowed to reset the default binding mode
119+
//~| WARN: this changes meaning in Rust 2024
120+
assert_type_eq(a, 0u32);
121+
assert_type_eq(b, &&0u32);
122+
assert_type_eq(c, &&0u32);
123+
124+
if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
125+
//~^ ERROR: patterns are not allowed to reset the default binding mode
126+
//~| WARN: this changes meaning in Rust 2024
127+
&(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) })
128+
{
129+
assert_type_eq(a, &0u32);
130+
assert_type_eq(b, 0u32);
131+
assert_type_eq(c, &&0u32);
132+
}
133+
134+
match &(Some(0), Some(0)) {
135+
// The two patterns are the same syntactically, but because they're defined in different
136+
// editions they don't mean the same thing.
137+
(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
138+
//~^ ERROR: patterns are not allowed to reset the default binding mode
139+
assert_type_eq(x, 0u32);
140+
assert_type_eq(y, 0u32);
141+
}
142+
_ => {}
143+
}
144+
}
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
error: patterns are not allowed to reset the default binding mode in edition 2024
2+
--> $DIR/migration_lint.rs:25:9
3+
|
4+
LL | let Foo(mut x) = &Foo(0);
5+
| -^^^^^^^^^
6+
| |
7+
| help: desugar the match ergonomics: `&`
8+
|
9+
= warning: this changes meaning in Rust 2024
10+
= note: for more information, see 123076
11+
note: the lint level is defined here
12+
--> $DIR/migration_lint.rs:7:9
13+
|
14+
LL | #![deny(rust_2024_incompatible_pat)]
15+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
16+
17+
error: patterns are not allowed to reset the default binding mode in edition 2024
18+
--> $DIR/migration_lint.rs:30:9
19+
|
20+
LL | let Foo(mut x) = &mut Foo(0);
21+
| -^^^^^^^^^
22+
| |
23+
| help: desugar the match ergonomics: `&mut`
24+
|
25+
= warning: this changes meaning in Rust 2024
26+
= note: for more information, see 123076
27+
28+
error: patterns are not allowed to reset the default binding mode in edition 2024
29+
--> $DIR/migration_lint.rs:35:9
30+
|
31+
LL | let Foo(ref x) = &Foo(0);
32+
| -^^^^^^^^^
33+
| |
34+
| help: desugar the match ergonomics: `&`
35+
|
36+
= warning: this changes meaning in Rust 2024
37+
= note: for more information, see 123076
38+
39+
error: patterns are not allowed to reset the default binding mode in edition 2024
40+
--> $DIR/migration_lint.rs:40:9
41+
|
42+
LL | let Foo(ref x) = &mut Foo(0);
43+
| -^^^^^^^^^
44+
| |
45+
| help: desugar the match ergonomics: `&mut`
46+
|
47+
= warning: this changes meaning in Rust 2024
48+
= note: for more information, see 123076
49+
50+
error: patterns are not allowed to reset the default binding mode in edition 2024
51+
--> $DIR/migration_lint.rs:57:9
52+
|
53+
LL | let Foo(&x) = &Foo(&0);
54+
| -^^^^^^
55+
| |
56+
| help: desugar the match ergonomics: `&`
57+
|
58+
= warning: this changes meaning in Rust 2024
59+
= note: for more information, see 123076
60+
61+
error: patterns are not allowed to reset the default binding mode in edition 2024
62+
--> $DIR/migration_lint.rs:62:9
63+
|
64+
LL | let Foo(&mut x) = &Foo(&mut 0);
65+
| -^^^^^^^^^^
66+
| |
67+
| help: desugar the match ergonomics: `&`
68+
|
69+
= warning: this changes meaning in Rust 2024
70+
= note: for more information, see 123076
71+
72+
error: patterns are not allowed to reset the default binding mode in edition 2024
73+
--> $DIR/migration_lint.rs:67:9
74+
|
75+
LL | let Foo(&x) = &mut Foo(&0);
76+
| -^^^^^^
77+
| |
78+
| help: desugar the match ergonomics: `&mut`
79+
|
80+
= warning: this changes meaning in Rust 2024
81+
= note: for more information, see 123076
82+
83+
error: patterns are not allowed to reset the default binding mode in edition 2024
84+
--> $DIR/migration_lint.rs:72:9
85+
|
86+
LL | let Foo(&mut x) = &mut Foo(&mut 0);
87+
| -^^^^^^^^^^
88+
| |
89+
| help: desugar the match ergonomics: `&mut`
90+
|
91+
= warning: this changes meaning in Rust 2024
92+
= note: for more information, see 123076
93+
94+
error: patterns are not allowed to reset the default binding mode in edition 2024
95+
--> $DIR/migration_lint.rs:81:12
96+
|
97+
LL | if let Some(&x) = &&&&&Some(&0u8) {
98+
| -^^^^^^^
99+
| |
100+
| help: desugar the match ergonomics: `&&&&&`
101+
|
102+
= warning: this changes meaning in Rust 2024
103+
= note: for more information, see 123076
104+
105+
error: patterns are not allowed to reset the default binding mode in edition 2024
106+
--> $DIR/migration_lint.rs:87:12
107+
|
108+
LL | if let Some(&mut x) = &&&&&Some(&mut 0u8) {
109+
| -^^^^^^^^^^^
110+
| |
111+
| help: desugar the match ergonomics: `&&&&&`
112+
|
113+
= warning: this changes meaning in Rust 2024
114+
= note: for more information, see 123076
115+
116+
error: patterns are not allowed to reset the default binding mode in edition 2024
117+
--> $DIR/migration_lint.rs:93:12
118+
|
119+
LL | if let Some(&x) = &&&&&mut Some(&0u8) {
120+
| -^^^^^^^
121+
| |
122+
| help: desugar the match ergonomics: `&&&&&mut`
123+
|
124+
= warning: this changes meaning in Rust 2024
125+
= note: for more information, see 123076
126+
127+
error: patterns are not allowed to reset the default binding mode in edition 2024
128+
--> $DIR/migration_lint.rs:99:12
129+
|
130+
LL | if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
131+
| ^^^^^^^^^^^^^^^^^^^^^^^^
132+
|
133+
= warning: this changes meaning in Rust 2024
134+
= note: for more information, see 123076
135+
help: desugar the match ergonomics
136+
|
137+
LL | if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) {
138+
| ++++ ++++ +++++++
139+
140+
error: patterns are not allowed to reset the default binding mode in edition 2024
141+
--> $DIR/migration_lint.rs:111:9
142+
|
143+
LL | let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
144+
| ^^^^^^^^^^^^^^^^^^^^^^
145+
|
146+
= warning: this changes meaning in Rust 2024
147+
= note: for more information, see 123076
148+
help: desugar the match ergonomics
149+
|
150+
LL | let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 };
151+
| + +++ +++
152+
153+
error: patterns are not allowed to reset the default binding mode in edition 2024
154+
--> $DIR/migration_lint.rs:117:9
155+
|
156+
LL | let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
157+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
158+
|
159+
= warning: this changes meaning in Rust 2024
160+
= note: for more information, see 123076
161+
help: desugar the match ergonomics
162+
|
163+
LL | let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 };
164+
| + +++
165+
166+
error: patterns are not allowed to reset the default binding mode in edition 2024
167+
--> $DIR/migration_lint.rs:124:12
168+
|
169+
LL | if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
170+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171+
|
172+
= warning: this changes meaning in Rust 2024
173+
= note: for more information, see 123076
174+
help: desugar the match ergonomics
175+
|
176+
LL | if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } =
177+
| + + + +++
178+
179+
error: patterns are not allowed to reset the default binding mode in edition 2024
180+
--> $DIR/migration_lint.rs:137:9
181+
|
182+
LL | (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
183+
| -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
184+
| |
185+
| help: desugar the match ergonomics: `&`
186+
187+
error: aborting due to 16 previous errors
188+
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//@ check-fail
2+
//@ edition: 2024
3+
//@ compile-flags: -Zunstable-options
4+
#![deny(rust_2024_incompatible_pat)]
5+
6+
fn main() {}
7+
8+
#[derive(Copy, Clone)]
9+
struct T;
10+
11+
struct Foo {
12+
f: &'static (u8,),
13+
}
14+
15+
macro_rules! test_pat_on_type {
16+
($($tt:tt)*) => {
17+
const _: () = {
18+
// Define a new function to ensure all cases are tested independently.
19+
fn foo($($tt)*) {}
20+
};
21+
};
22+
}
23+
24+
test_pat_on_type![(&x,): &(T,)]; //~ ERROR mismatched types
25+
test_pat_on_type![(&x,): &(&T,)]; //~ ERROR patterns are not allowed to reset the default binding mode
26+
test_pat_on_type![(&x,): &(&mut T,)]; //~ ERROR mismatched types
27+
test_pat_on_type![(&mut x,): &(&T,)]; //~ ERROR mismatched types
28+
test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR patterns are not allowed to reset the default binding mode
29+
test_pat_on_type![(&x,): &&mut &(T,)]; //~ ERROR mismatched types
30+
test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types
31+
test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types
32+
test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR patterns are not allowed to reset the default binding mode
33+
test_pat_on_type![(mut x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode
34+
test_pat_on_type![(ref x,): &(T,)]; //~ ERROR patterns are not allowed to reset the default binding mode
35+
test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR patterns are not allowed to reset the default binding mode
36+
37+
fn get<X>() -> X {
38+
unimplemented!()
39+
}
40+
41+
// Make sure this works even when the underlying type is inferred. This test passes on rust stable.
42+
fn infer<X: Copy>() -> X {
43+
match &get() {
44+
(&x,) => x, //~ ERROR patterns are not allowed to reset the default binding mode
45+
}
46+
}
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/min_match_ergonomics_fail.rs:24:20
3+
|
4+
LL | test_pat_on_type![(&x,): &(T,)];
5+
| ^^ ----- expected due to this
6+
| |
7+
| expected `T`, found `&_`
8+
|
9+
= note: expected struct `T`
10+
found reference `&_`
11+
help: consider removing `&` from the pattern
12+
|
13+
LL - test_pat_on_type![(&x,): &(T,)];
14+
LL + test_pat_on_type![(x,): &(T,)];
15+
|
16+
17+
error[E0308]: mismatched types
18+
--> $DIR/min_match_ergonomics_fail.rs:26:20
19+
|
20+
LL | test_pat_on_type![(&x,): &(&mut T,)];
21+
| ^^ ---------- expected due to this
22+
| |
23+
| types differ in mutability
24+
|
25+
= note: expected mutable reference `&mut T`
26+
found reference `&_`
27+
help: consider removing `&` from the pattern
28+
|
29+
LL - test_pat_on_type![(&x,): &(&mut T,)];
30+
LL + test_pat_on_type![(x,): &(&mut T,)];
31+
|
32+
33+
error[E0308]: mismatched types
34+
--> $DIR/min_match_ergonomics_fail.rs:27:20
35+
|
36+
LL | test_pat_on_type![(&mut x,): &(&T,)];
37+
| ^^^^^^ ------ expected due to this
38+
| |
39+
| types differ in mutability
40+
|
41+
= note: expected reference `&T`
42+
found mutable reference `&mut _`
43+
note: to declare a mutable binding use: `mut x`
44+
--> $DIR/min_match_ergonomics_fail.rs:27:20
45+
|
46+
LL | test_pat_on_type![(&mut x,): &(&T,)];
47+
| ^^^^^^
48+
help: consider removing `&mut` from the pattern
49+
|
50+
LL - test_pat_on_type![(&mut x,): &(&T,)];
51+
LL + test_pat_on_type![(x,): &(&T,)];
52+
|
53+
54+
error[E0308]: mismatched types
55+
--> $DIR/min_match_ergonomics_fail.rs:29:20
56+
|
57+
LL | test_pat_on_type![(&x,): &&mut &(T,)];
58+
| ^^ ----------- expected due to this
59+
| |
60+
| expected `T`, found `&_`
61+
|
62+
= note: expected struct `T`
63+
found reference `&_`
64+
help: consider removing `&` from the pattern
65+
|
66+
LL - test_pat_on_type![(&x,): &&mut &(T,)];
67+
LL + test_pat_on_type![(x,): &&mut &(T,)];
68+
|
69+
70+
error[E0308]: mismatched types
71+
--> $DIR/min_match_ergonomics_fail.rs:30:29
72+
|
73+
LL | test_pat_on_type![Foo { f: (&x,) }: Foo];
74+
| ^^ --- expected due to this
75+
| |
76+
| expected `u8`, found `&_`
77+
|
78+
= note: expected type `u8`
79+
found reference `&_`
80+
help: consider removing `&` from the pattern
81+
|
82+
LL - test_pat_on_type![Foo { f: (&x,) }: Foo];
83+
LL + test_pat_on_type![Foo { f: (x,) }: Foo];
84+
|
85+
86+
error[E0308]: mismatched types
87+
--> $DIR/min_match_ergonomics_fail.rs:31:29
88+
|
89+
LL | test_pat_on_type![Foo { f: (&x,) }: &mut Foo];
90+
| ^^ -------- expected due to this
91+
| |
92+
| expected `u8`, found `&_`
93+
|
94+
= note: expected type `u8`
95+
found reference `&_`
96+
help: consider removing `&` from the pattern
97+
|
98+
LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo];
99+
LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo];
100+
|
101+
102+
error: patterns are not allowed to reset the default binding mode in edition 2024
103+
--> $DIR/min_match_ergonomics_fail.rs:25:19
104+
|
105+
LL | test_pat_on_type![(&x,): &(&T,)];
106+
| -^^^^
107+
| |
108+
| help: desugar the match ergonomics: `&`
109+
110+
error: patterns are not allowed to reset the default binding mode in edition 2024
111+
--> $DIR/min_match_ergonomics_fail.rs:28:19
112+
|
113+
LL | test_pat_on_type![(&mut x,): &(&mut T,)];
114+
| -^^^^^^^^
115+
| |
116+
| help: desugar the match ergonomics: `&`
117+
118+
error: patterns are not allowed to reset the default binding mode in edition 2024
119+
--> $DIR/min_match_ergonomics_fail.rs:32:19
120+
|
121+
LL | test_pat_on_type![Foo { f: &(x,) }: &Foo];
122+
| -^^^^^^^^^^^^^^^
123+
| |
124+
| help: desugar the match ergonomics: `&`
125+
126+
error: patterns are not allowed to reset the default binding mode in edition 2024
127+
--> $DIR/min_match_ergonomics_fail.rs:33:19
128+
|
129+
LL | test_pat_on_type![(mut x,): &(T,)];
130+
| -^^^^^^^
131+
| |
132+
| help: desugar the match ergonomics: `&`
133+
134+
error: patterns are not allowed to reset the default binding mode in edition 2024
135+
--> $DIR/min_match_ergonomics_fail.rs:34:19
136+
|
137+
LL | test_pat_on_type![(ref x,): &(T,)];
138+
| -^^^^^^^
139+
| |
140+
| help: desugar the match ergonomics: `&`
141+
142+
error: patterns are not allowed to reset the default binding mode in edition 2024
143+
--> $DIR/min_match_ergonomics_fail.rs:35:19
144+
|
145+
LL | test_pat_on_type![(ref mut x,): &mut (T,)];
146+
| -^^^^^^^^^^^
147+
| |
148+
| help: desugar the match ergonomics: `&mut`
149+
150+
error: patterns are not allowed to reset the default binding mode in edition 2024
151+
--> $DIR/min_match_ergonomics_fail.rs:44:9
152+
|
153+
LL | (&x,) => x,
154+
| -^^^^
155+
| |
156+
| help: desugar the match ergonomics: `&`
157+
158+
error: aborting due to 13 previous errors
159+
160+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//@ check-pass
2+
#![allow(incomplete_features)]
3+
4+
fn main() {}
5+
6+
// Tests type equality in a way that avoids coercing `&&T` to `&T`.
7+
trait Eq<T> {}
8+
impl<T> Eq<T> for T {}
9+
fn assert_type_eq<T, U: Eq<T>>(_: T, _: U) {}
10+
11+
#[derive(Copy, Clone)]
12+
struct T;
13+
14+
fn test() {
15+
let (x,) = &(&T,);
16+
assert_type_eq(x, &&T);
17+
}

0 commit comments

Comments
 (0)
Please sign in to comment.