Skip to content

Commit 980451e

Browse files
authored
Unrolled build for rust-lang#136093
Rollup merge of rust-lang#136093 - dianne:match-2024-for-edition-2021, r=Nadrieril Match Ergonomics 2024: update old-edition behavior of feature gates This updates the behavior of the feature gates `ref_pat_eat_one_layer_2024_structural` and `ref_pat_eat_one_layer_2024` in Editions 2021 and earlier to correspond to the left and right typing rules compared [here](https://nadrieril.github.io/typing-rust-patterns/?opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&style=UserVisible&compare=true&opts2=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules), respectively. Compared to the `stable_rust` rules: - they both allow reference patterns to match a lone inherited ref, - they both allow `&` patterns to eat `&mut` reference types (and lone `&mut` inherited refs) as if they're shared, - they both allow `&mut` patterns to eat `&` reference types when there's a `&mut` inherited reference to also eat, - and the left ruleset has RFC 3627's Rule 3: after encountering a shared reference type in the scrutinee, the default binding mode will be treated as by-shared-ref when it would otherwise be by-mutable-ref. I think there's already tests for all of those typing rules, so I've added revisions to use the existing tests with the new rulesets. Additionally, I've added a few tests to make sure we handle mixed-edition patterns appropriately, and I've added references to the unstable book. Relevant tracking issue: rust-lang#123076 r? ``@ghost``
2 parents f280acf + 0a15bfb commit 980451e

File tree

45 files changed

+1866
-523
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+1866
-523
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+60-7
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,19 @@ enum InheritedRefMatchRule {
230230
/// underlying type is not a reference type, the inherited reference will be consumed.
231231
EatInner,
232232
/// When the underlying type is a reference type, reference patterns consume both layers of
233-
/// reference, i.e. they both reset the binding mode and consume the reference type. Reference
234-
/// patterns are not permitted when there is no underlying reference type, i.e. they can't eat
235-
/// only an inherited reference. This is the current stable Rust behavior.
236-
EatBoth,
233+
/// reference, i.e. they both reset the binding mode and consume the reference type.
234+
EatBoth {
235+
/// If `true`, an inherited reference will be considered when determining whether a reference
236+
/// pattern matches a given type:
237+
/// - If the underlying type is not a reference, a reference pattern may eat the inherited reference;
238+
/// - If the underlying type is a reference, a reference pattern matches if it can eat either one
239+
/// of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
240+
/// underlying type is `&mut` or the inherited reference is `&mut`.
241+
/// If `false`, a reference pattern is only matched against the underlying type.
242+
/// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and
243+
/// `ref_pat_eat_one_layer_2024_structural` feature gates.
244+
consider_inherited_ref: bool,
245+
},
237246
}
238247

239248
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -259,10 +268,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259268
} else {
260269
// Currently, matching against an inherited ref on edition 2024 is an error.
261270
// Use `EatBoth` as a fallback to be similar to stable Rust.
262-
InheritedRefMatchRule::EatBoth
271+
InheritedRefMatchRule::EatBoth { consider_inherited_ref: false }
263272
}
264273
} else {
265-
InheritedRefMatchRule::EatBoth
274+
InheritedRefMatchRule::EatBoth {
275+
consider_inherited_ref: self.tcx.features().ref_pat_eat_one_layer_2024()
276+
|| self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
277+
}
266278
}
267279
}
268280

@@ -2371,6 +2383,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23712383
// NB: This assumes that `&` patterns can match against mutable
23722384
// references (RFC 3627, Rule 5). If we implement a pattern typing
23732385
// ruleset with Rule 4 but not Rule 5, we'll need to check that here.
2386+
// FIXME(ref_pat_eat_one_layer_2024_structural): If we already tried
2387+
// matching the real reference, the error message should explain that
2388+
// falling back to the inherited reference didn't work. This should be
2389+
// the same error as the old-Edition version below.
23742390
debug_assert!(ref_pat_matches_mut_ref);
23752391
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
23762392
}
@@ -2381,9 +2397,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23812397
return expected;
23822398
}
23832399
}
2384-
InheritedRefMatchRule::EatBoth => {
2400+
InheritedRefMatchRule::EatBoth { consider_inherited_ref: true } => {
23852401
// Reset binding mode on old editions
23862402
pat_info.binding_mode = ByRef::No;
2403+
2404+
if let ty::Ref(_, inner_ty, _) = *expected.kind() {
2405+
// Consume both the inherited and inner references.
2406+
if pat_mutbl.is_mut() && inh_mut.is_mut() {
2407+
// As a special case, a `&mut` reference pattern will be able to match
2408+
// against a reference type of any mutability if the inherited ref is
2409+
// mutable. Since this allows us to match against a shared reference
2410+
// type, we refer to this as "falling back" to matching the inherited
2411+
// reference, though we consume the real reference as well. We handle
2412+
// this here to avoid adding this case to the common logic below.
2413+
self.check_pat(inner, inner_ty, pat_info);
2414+
return expected;
2415+
} else {
2416+
// Otherwise, use the common logic below for matching the inner
2417+
// reference type.
2418+
// FIXME(ref_pat_eat_one_layer_2024_structural): If this results in a
2419+
// mutability mismatch, the error message should explain that falling
2420+
// back to the inherited reference didn't work. This should be the same
2421+
// error as the Edition 2024 version above.
2422+
}
2423+
} else {
2424+
// The expected type isn't a reference type, so only match against the
2425+
// inherited reference.
2426+
if pat_mutbl > inh_mut {
2427+
// We can't match a lone inherited shared reference with `&mut`.
2428+
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2429+
}
2430+
2431+
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2432+
self.check_pat(inner, expected, pat_info);
2433+
return expected;
2434+
}
2435+
}
2436+
InheritedRefMatchRule::EatBoth { consider_inherited_ref: false } => {
2437+
// Reset binding mode on stable Rust. This will be a type error below if
2438+
// `expected` is not a reference type.
2439+
pat_info.binding_mode = ByRef::No;
23872440
self.add_rust_2024_migration_desugared_pat(
23882441
pat_info.top_info.hir_id,
23892442
pat,

src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ This feature is incomplete and not yet intended for general use.
1010

1111
This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
1212
in Rust.
13-
For more information, see the corresponding typing rules for [Editions 2024 and later].
14-
On earlier Editions, the current behavior is unspecified.
13+
For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
14+
[Editions 2024 and later].
1515

1616
For alternative experimental match ergonomics, see the feature
1717
[`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md).
1818

19+
[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
1920
[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false

src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md

+3-2
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ This feature is incomplete and not yet intended for general use.
1010

1111
This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
1212
in Rust.
13-
For more information, see the corresponding typing rules for [Editions 2024 and later].
14-
On earlier Editions, the current behavior is unspecified.
13+
For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
14+
[Editions 2024 and later].
1515

1616
For alternative experimental match ergonomics, see the feature
1717
[`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md).
1818

19+
[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
1920
[Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
//@[classic2021] edition: 2024
2+
//@[structural2021] edition: 2024
3+
//@[classic2024] edition: 2021
4+
//@[structural2024] edition: 2021
5+
//! This contains macros in an edition *different* to the one used in `../mixed-editions.rs`, in
6+
//! order to test typing mixed-edition patterns.
7+
8+
#[macro_export]
9+
macro_rules! match_ctor {
10+
($p:pat) => {
11+
[$p]
12+
};
13+
}
14+
15+
#[macro_export]
16+
macro_rules! match_ref {
17+
($p:pat) => {
18+
&$p
19+
};
20+
}
21+
22+
#[macro_export]
23+
macro_rules! bind {
24+
($i:ident) => {
25+
$i
26+
}
27+
}
28+
29+
#[macro_export]
30+
macro_rules! bind_ref {
31+
($i:ident) => {
32+
ref $i
33+
}
34+
}
35+
36+
#[macro_export]
37+
macro_rules! bind_mut {
38+
($i:ident) => {
39+
mut $i
40+
}
41+
}
42+
43+
#[macro_export]
44+
macro_rules! bind_ref_mut {
45+
($i:ident) => {
46+
ref mut $i
47+
}
48+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
error[E0507]: cannot move out of a shared reference
2+
--> $DIR/borrowck-errors.rs:31:29
3+
|
4+
LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) {
5+
| - ^^^^^^^^^^^^^^^^^^^
6+
| |
7+
| data moved here
8+
| move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
9+
|
10+
help: consider removing the borrow
11+
|
12+
LL - if let Some(&Some(x)) = Some(&Some(&mut 0)) {
13+
LL + if let Some(Some(x)) = Some(&Some(&mut 0)) {
14+
|
15+
16+
error[E0596]: cannot borrow data in a `&` reference as mutable
17+
--> $DIR/borrowck-errors.rs:36:10
18+
|
19+
LL | let &ref mut x = &0;
20+
| ^^^^^^^^^ cannot borrow as mutable
21+
22+
error[E0596]: cannot borrow data in a `&` reference as mutable
23+
--> $DIR/borrowck-errors.rs:41:23
24+
|
25+
LL | if let &Some(Some(x)) = &Some(&mut Some(0)) {
26+
| ^ cannot borrow as mutable
27+
28+
error[E0596]: cannot borrow data in a `&` reference as mutable
29+
--> $DIR/borrowck-errors.rs:46:11
30+
|
31+
LL | let &[x] = &&mut [0];
32+
| ^ cannot borrow as mutable
33+
34+
error: aborting due to 4 previous errors
35+
36+
Some errors have detailed explanations: E0507, E0596.
37+
For more information about an error, try `rustc --explain E0507`.

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr

+11-11
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,33 @@
1-
error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
2-
--> $DIR/borrowck-errors.rs:13:16
1+
error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
2+
--> $DIR/borrowck-errors.rs:15:16
33
|
44
LL | let [&x] = &[&mut 0];
55
| - ^^^^^^^^^ cannot move out of here
66
| |
77
| data moved here
8-
| move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
8+
| move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
99
|
1010
help: consider borrowing the pattern binding
1111
|
1212
LL | let [&ref x] = &[&mut 0];
1313
| +++
1414

15-
error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
16-
--> $DIR/borrowck-errors.rs:19:16
15+
error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
16+
--> $DIR/borrowck-errors.rs:22:16
1717
|
1818
LL | let [&x] = &mut [&mut 0];
1919
| - ^^^^^^^^^^^^^ cannot move out of here
2020
| |
2121
| data moved here
22-
| move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
22+
| move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
2323
|
2424
help: consider borrowing the pattern binding
2525
|
2626
LL | let [&ref x] = &mut [&mut 0];
2727
| +++
2828

2929
error[E0507]: cannot move out of a shared reference
30-
--> $DIR/borrowck-errors.rs:27:29
30+
--> $DIR/borrowck-errors.rs:31:29
3131
|
3232
LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) {
3333
| - ^^^^^^^^^^^^^^^^^^^
@@ -42,25 +42,25 @@ LL + if let Some(Some(x)) = Some(&Some(&mut 0)) {
4242
|
4343

4444
error[E0596]: cannot borrow data in a `&` reference as mutable
45-
--> $DIR/borrowck-errors.rs:32:10
45+
--> $DIR/borrowck-errors.rs:36:10
4646
|
4747
LL | let &ref mut x = &0;
4848
| ^^^^^^^^^ cannot borrow as mutable
4949

5050
error[E0596]: cannot borrow data in a `&` reference as mutable
51-
--> $DIR/borrowck-errors.rs:37:23
51+
--> $DIR/borrowck-errors.rs:41:23
5252
|
5353
LL | if let &Some(Some(x)) = &Some(&mut Some(0)) {
5454
| ^ cannot borrow as mutable
5555

5656
error[E0596]: cannot borrow data in a `&` reference as mutable
57-
--> $DIR/borrowck-errors.rs:42:11
57+
--> $DIR/borrowck-errors.rs:46:11
5858
|
5959
LL | let &[x] = &&mut [0];
6060
| ^ cannot borrow as mutable
6161

6262
error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
63-
--> $DIR/borrowck-errors.rs:46:20
63+
--> $DIR/borrowck-errors.rs:50:20
6464
|
6565
LL | let [&mut x] = &mut [&mut 0];
6666
| - ^^^^^^^^^^^^^ cannot move out of here
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
1-
//@ revisions: stable2021 classic2024 structural2024
1+
//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
22
//@[stable2021] edition: 2021
3+
//@[classic2021] edition: 2021
4+
//@[structural2021] edition: 2021
35
//@[classic2024] edition: 2024
46
//@[structural2024] edition: 2024
57
//! Tests for pattern errors not handled by the pattern typing rules, but by borrowck.
68
#![allow(incomplete_features)]
7-
#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
8-
#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
9+
#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
10+
#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
911

1012
/// These patterns additionally use `&` to match a `&mut` reference type, which causes compilation
1113
/// to fail in HIR typeck on stable. As such, they need to be separate from the other tests.
@@ -14,13 +16,15 @@ fn errors_caught_in_hir_typeck_on_stable() {
1416
//[stable2021]~^ mismatched types
1517
//[stable2021]~| types differ in mutability
1618
//[classic2024]~^^^ ERROR: cannot move out of type
17-
let _: &u32 = x;
19+
#[cfg(any(classic2021, structural2021))] let _: u32 = x;
20+
#[cfg(structural2024)] let _: &u32 = x;
1821

1922
let [&x] = &mut [&mut 0];
2023
//[stable2021]~^ mismatched types
2124
//[stable2021]~| types differ in mutability
2225
//[classic2024]~^^^ ERROR: cannot move out of type
23-
let _: &u32 = x;
26+
#[cfg(any(classic2021, structural2021))] let _: u32 = x;
27+
#[cfg(structural2024)] let _: &u32 = x;
2428
}
2529

2630
pub fn main() {
@@ -35,16 +39,16 @@ pub fn main() {
3539
// For 2021 edition, this is also a regression test for #136223
3640
// since the maximum mutability is downgraded during the pattern check process.
3741
if let &Some(Some(x)) = &Some(&mut Some(0)) {
38-
//[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
39-
let _: &u32 = x;
42+
//[stable2021,classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
43+
#[cfg(any(structural2021, structural2024))] let _: &u32 = x;
4044
}
4145

4246
let &[x] = &&mut [0];
43-
//[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
44-
let _: &u32 = x;
47+
//[stable2021,classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
48+
#[cfg(any(structural2021, structural2024))] let _: &u32 = x;
4549

4650
let [&mut x] = &mut [&mut 0];
4751
//[classic2024]~^ ERROR: cannot move out of type
48-
#[cfg(stable2021)] let _: u32 = x;
52+
#[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
4953
#[cfg(structural2024)] let _: &mut u32 = x;
5054
}

tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/borrowck-errors.rs:13:10
2+
--> $DIR/borrowck-errors.rs:15:10
33
|
44
LL | let [&x] = &[&mut 0];
55
| ^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -15,7 +15,7 @@ LL + let [x] = &[&mut 0];
1515
|
1616

1717
error[E0308]: mismatched types
18-
--> $DIR/borrowck-errors.rs:19:10
18+
--> $DIR/borrowck-errors.rs:22:10
1919
|
2020
LL | let [&x] = &mut [&mut 0];
2121
| ^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -31,7 +31,7 @@ LL + let [x] = &mut [&mut 0];
3131
|
3232

3333
error[E0507]: cannot move out of a shared reference
34-
--> $DIR/borrowck-errors.rs:27:29
34+
--> $DIR/borrowck-errors.rs:31:29
3535
|
3636
LL | if let Some(&Some(x)) = Some(&Some(&mut 0)) {
3737
| - ^^^^^^^^^^^^^^^^^^^
@@ -46,19 +46,19 @@ LL + if let Some(Some(x)) = Some(&Some(&mut 0)) {
4646
|
4747

4848
error[E0596]: cannot borrow data in a `&` reference as mutable
49-
--> $DIR/borrowck-errors.rs:32:10
49+
--> $DIR/borrowck-errors.rs:36:10
5050
|
5151
LL | let &ref mut x = &0;
5252
| ^^^^^^^^^ cannot borrow as mutable
5353

5454
error[E0596]: cannot borrow data in a `&` reference as mutable
55-
--> $DIR/borrowck-errors.rs:37:23
55+
--> $DIR/borrowck-errors.rs:41:23
5656
|
5757
LL | if let &Some(Some(x)) = &Some(&mut Some(0)) {
5858
| ^ cannot borrow as mutable
5959

6060
error[E0596]: cannot borrow data in a `&` reference as mutable
61-
--> $DIR/borrowck-errors.rs:42:11
61+
--> $DIR/borrowck-errors.rs:46:11
6262
|
6363
LL | let &[x] = &&mut [0];
6464
| ^ cannot borrow as mutable

0 commit comments

Comments
 (0)