Skip to content

Commit ec8bf0f

Browse files
committed
"classic2021" and "structural2021" rulesets: add eat-inherited-ref-alone deref rules
1 parent 3f4d34f commit ec8bf0f

18 files changed

+199
-530
lines changed

compiler/rustc_hir_typeck/src/pat.rs

+32-7
Original file line numberDiff line numberDiff line change
@@ -230,10 +230,12 @@ 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+
/// Whether to allow reference patterns to consume only an inherited reference when matching
236+
/// against a non-reference type. This is `false` for stable Rust.
237+
eat_inherited_ref_alone: bool,
238+
},
237239
}
238240

239241
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -259,10 +261,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259261
} else {
260262
// Currently, matching against an inherited ref on edition 2024 is an error.
261263
// Use `EatBoth` as a fallback to be similar to stable Rust.
262-
InheritedRefMatchRule::EatBoth
264+
InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: false }
263265
}
264266
} else {
265-
InheritedRefMatchRule::EatBoth
267+
InheritedRefMatchRule::EatBoth {
268+
eat_inherited_ref_alone: self.tcx.features().ref_pat_eat_one_layer_2024()
269+
|| self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
270+
}
266271
}
267272
}
268273

@@ -2361,9 +2366,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23612366
return expected;
23622367
}
23632368
}
2364-
InheritedRefMatchRule::EatBoth => {
2369+
InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: true } => {
23652370
// Reset binding mode on old editions
23662371
pat_info.binding_mode = ByRef::No;
2372+
2373+
if let ty::Ref(_, _, _) = *expected.kind() {
2374+
// Consume both the inherited and inner references.
2375+
} else {
2376+
// The expected type isn't a reference type, so only match against the
2377+
// inherited reference.
2378+
if pat_mutbl > inh_mut {
2379+
// We can't match a lone inherited shared reference with `&mut`.
2380+
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2381+
}
2382+
2383+
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2384+
self.check_pat(inner, expected, pat_info);
2385+
return expected;
2386+
}
2387+
}
2388+
InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: false } => {
2389+
// Reset binding mode on stable Rust. This will be a type error below if
2390+
// `expected` is not a reference type.
2391+
pat_info.binding_mode = ByRef::No;
23672392
self.add_rust_2024_migration_desugared_pat(
23682393
pat_info.top_info.hir_id,
23692394
pat.span,

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

+16-152
Original file line numberDiff line numberDiff line change
@@ -56,155 +56,19 @@ LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
5656
found mutable reference `&mut _`
5757

5858
error[E0308]: mismatched types
59-
--> $DIR/pattern-errors.rs:50:17
60-
|
61-
LL | if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
62-
| ^^^^^^^^^^^^^^^^^^^ ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
63-
| |
64-
| expected `Option<&mut Option<{integer}>>`, found `&_`
65-
|
66-
= note: expected enum `Option<&mut Option<{integer}>>`
67-
found reference `&_`
68-
69-
error[E0308]: mismatched types
70-
--> $DIR/pattern-errors.rs:57:17
59+
--> $DIR/pattern-errors.rs:56:17
7160
|
7261
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
73-
| ^^^^^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
74-
| |
75-
| expected `Option<{integer}>`, found `&mut _`
76-
|
77-
= note: expected enum `Option<{integer}>`
78-
found mutable reference `&mut _`
79-
80-
error[E0308]: mismatched types
81-
--> $DIR/pattern-errors.rs:66:11
82-
|
83-
LL | let &[&mut x] = &&mut [0];
84-
| ^^^^^^ --------- this expression has type `&&mut [{integer}; 1]`
85-
| |
86-
| expected integer, found `&mut _`
87-
|
88-
= note: expected type `{integer}`
89-
found mutable reference `&mut _`
90-
note: to declare a mutable binding use: `mut x`
91-
--> $DIR/pattern-errors.rs:66:11
92-
|
93-
LL | let &[&mut x] = &&mut [0];
94-
| ^^^^^^
95-
help: consider removing `&mut` from the pattern
96-
|
97-
LL - let &[&mut x] = &&mut [0];
98-
LL + let &[x] = &&mut [0];
99-
|
100-
101-
error[E0308]: mismatched types
102-
--> $DIR/pattern-errors.rs:73:11
103-
|
104-
LL | let &[&mut x] = &mut &mut [0];
105-
| ^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]`
106-
| |
107-
| expected integer, found `&mut _`
108-
|
109-
= note: expected type `{integer}`
110-
found mutable reference `&mut _`
111-
note: to declare a mutable binding use: `mut x`
112-
--> $DIR/pattern-errors.rs:73:11
113-
|
114-
LL | let &[&mut x] = &mut &mut [0];
115-
| ^^^^^^
116-
help: consider removing `&mut` from the pattern
117-
|
118-
LL - let &[&mut x] = &mut &mut [0];
119-
LL + let &[x] = &mut &mut [0];
120-
|
121-
122-
error[E0308]: mismatched types
123-
--> $DIR/pattern-errors.rs:80:11
124-
|
125-
LL | let &[&mut ref x] = &&mut [0];
126-
| ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]`
127-
| |
128-
| expected integer, found `&mut _`
129-
|
130-
= note: expected type `{integer}`
131-
found mutable reference `&mut _`
132-
note: to declare a mutable binding use: `mut x`
133-
--> $DIR/pattern-errors.rs:80:11
134-
|
135-
LL | let &[&mut ref x] = &&mut [0];
136-
| ^^^^^^^^^^
137-
help: consider removing `&mut` from the pattern
138-
|
139-
LL - let &[&mut ref x] = &&mut [0];
140-
LL + let &[ref x] = &&mut [0];
141-
|
142-
143-
error[E0308]: mismatched types
144-
--> $DIR/pattern-errors.rs:87:11
145-
|
146-
LL | let &[&mut ref x] = &mut &mut [0];
147-
| ^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]`
148-
| |
149-
| expected integer, found `&mut _`
150-
|
151-
= note: expected type `{integer}`
152-
found mutable reference `&mut _`
153-
note: to declare a mutable binding use: `mut x`
154-
--> $DIR/pattern-errors.rs:87:11
155-
|
156-
LL | let &[&mut ref x] = &mut &mut [0];
157-
| ^^^^^^^^^^
158-
help: consider removing `&mut` from the pattern
159-
|
160-
LL - let &[&mut ref x] = &mut &mut [0];
161-
LL + let &[ref x] = &mut &mut [0];
162-
|
163-
164-
error[E0308]: mismatched types
165-
--> $DIR/pattern-errors.rs:94:11
166-
|
167-
LL | let &[&mut mut x] = &&mut [0];
168-
| ^^^^^^^^^^ --------- this expression has type `&&mut [{integer}; 1]`
169-
| |
170-
| expected integer, found `&mut _`
171-
|
172-
= note: expected type `{integer}`
173-
found mutable reference `&mut _`
174-
note: to declare a mutable binding use: `mut x`
175-
--> $DIR/pattern-errors.rs:94:11
176-
|
177-
LL | let &[&mut mut x] = &&mut [0];
178-
| ^^^^^^^^^^
179-
help: consider removing `&mut` from the pattern
180-
|
181-
LL - let &[&mut mut x] = &&mut [0];
182-
LL + let &[mut x] = &&mut [0];
183-
|
184-
185-
error[E0308]: mismatched types
186-
--> $DIR/pattern-errors.rs:101:11
187-
|
188-
LL | let &[&mut mut x] = &mut &mut [0];
189-
| ^^^^^^^^^^ ------------- this expression has type `&mut &mut [{integer}; 1]`
190-
| |
191-
| expected integer, found `&mut _`
192-
|
193-
= note: expected type `{integer}`
194-
found mutable reference `&mut _`
195-
note: to declare a mutable binding use: `mut x`
196-
--> $DIR/pattern-errors.rs:101:11
197-
|
198-
LL | let &[&mut mut x] = &mut &mut [0];
199-
| ^^^^^^^^^^
200-
help: consider removing `&mut` from the pattern
62+
| ^^^^^
20163
|
202-
LL - let &[&mut mut x] = &mut &mut [0];
203-
LL + let &[mut x] = &mut &mut [0];
64+
= note: cannot match inherited `&` with `&mut` pattern
65+
help: replace this `&mut` pattern with `&`
20466
|
67+
LL | if let Some(&Some(x)) = &Some(Some(0)) {
68+
| ~
20569

20670
error[E0308]: mismatched types
207-
--> $DIR/pattern-errors.rs:122:11
71+
--> $DIR/pattern-errors.rs:114:11
20872
|
20973
LL | let [&&mut x] = &[&mut 0];
21074
| ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -220,7 +84,7 @@ LL + let [&x] = &[&mut 0];
22084
|
22185

22286
error[E0308]: mismatched types
223-
--> $DIR/pattern-errors.rs:129:11
87+
--> $DIR/pattern-errors.rs:121:11
22488
|
22589
LL | let [&&mut x] = &mut [&mut 0];
22690
| ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -236,7 +100,7 @@ LL + let [&x] = &mut [&mut 0];
236100
|
237101

238102
error[E0308]: mismatched types
239-
--> $DIR/pattern-errors.rs:136:11
103+
--> $DIR/pattern-errors.rs:128:11
240104
|
241105
LL | let [&&mut ref x] = &[&mut 0];
242106
| ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -252,7 +116,7 @@ LL + let [&ref x] = &[&mut 0];
252116
|
253117

254118
error[E0308]: mismatched types
255-
--> $DIR/pattern-errors.rs:143:11
119+
--> $DIR/pattern-errors.rs:135:11
256120
|
257121
LL | let [&&mut ref x] = &mut [&mut 0];
258122
| ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -268,7 +132,7 @@ LL + let [&ref x] = &mut [&mut 0];
268132
|
269133

270134
error[E0308]: mismatched types
271-
--> $DIR/pattern-errors.rs:150:11
135+
--> $DIR/pattern-errors.rs:142:11
272136
|
273137
LL | let [&&mut mut x] = &[&mut 0];
274138
| ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -284,7 +148,7 @@ LL + let [&mut x] = &[&mut 0];
284148
|
285149

286150
error[E0308]: mismatched types
287-
--> $DIR/pattern-errors.rs:157:11
151+
--> $DIR/pattern-errors.rs:149:11
288152
|
289153
LL | let [&&mut mut x] = &mut [&mut 0];
290154
| ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -300,7 +164,7 @@ LL + let [&mut x] = &mut [&mut 0];
300164
|
301165

302166
error[E0308]: mismatched types
303-
--> $DIR/pattern-errors.rs:172:15
167+
--> $DIR/pattern-errors.rs:164:15
304168
|
305169
LL | let [&mut &x] = &[&mut 0];
306170
| ^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -316,7 +180,7 @@ LL + let [&mut x] = &[&mut 0];
316180
|
317181

318182
error[E0308]: mismatched types
319-
--> $DIR/pattern-errors.rs:178:15
183+
--> $DIR/pattern-errors.rs:170:15
320184
|
321185
LL | let [&mut &ref x] = &[&mut 0];
322186
| ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -332,7 +196,7 @@ LL + let [&mut ref x] = &[&mut 0];
332196
|
333197

334198
error[E0308]: mismatched types
335-
--> $DIR/pattern-errors.rs:184:15
199+
--> $DIR/pattern-errors.rs:176:15
336200
|
337201
LL | let [&mut &(mut x)] = &[&mut 0];
338202
| ^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -347,6 +211,6 @@ LL - let [&mut &(mut x)] = &[&mut 0];
347211
LL + let [&mut mut x)] = &[&mut 0];
348212
|
349213

350-
error: aborting due to 21 previous errors
214+
error: aborting due to 14 previous errors
351215

352216
For more information about this error, try `rustc --explain E0308`.

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) {
5959
| ~
6060

6161
error[E0308]: mismatched types
62-
--> $DIR/pattern-errors.rs:57:17
62+
--> $DIR/pattern-errors.rs:56:17
6363
|
6464
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
6565
| ^^^^^
@@ -71,7 +71,7 @@ LL | if let Some(&Some(x)) = &Some(Some(0)) {
7171
| ~
7272

7373
error[E0308]: mismatched types
74-
--> $DIR/pattern-errors.rs:166:10
74+
--> $DIR/pattern-errors.rs:158:10
7575
|
7676
LL | let [&mut x] = &[&mut 0];
7777
| ^^^^^
@@ -83,7 +83,7 @@ LL | let [&x] = &[&mut 0];
8383
| ~
8484

8585
error[E0308]: mismatched types
86-
--> $DIR/pattern-errors.rs:172:10
86+
--> $DIR/pattern-errors.rs:164:10
8787
|
8888
LL | let [&mut &x] = &[&mut 0];
8989
| ^^^^^
@@ -95,7 +95,7 @@ LL | let [&&x] = &[&mut 0];
9595
| ~
9696

9797
error[E0308]: mismatched types
98-
--> $DIR/pattern-errors.rs:178:10
98+
--> $DIR/pattern-errors.rs:170:10
9999
|
100100
LL | let [&mut &ref x] = &[&mut 0];
101101
| ^^^^^
@@ -107,7 +107,7 @@ LL | let [&&ref x] = &[&mut 0];
107107
| ~
108108

109109
error[E0308]: mismatched types
110-
--> $DIR/pattern-errors.rs:184:10
110+
--> $DIR/pattern-errors.rs:176:10
111111
|
112112
LL | let [&mut &(mut x)] = &[&mut 0];
113113
| ^^^^^

0 commit comments

Comments
 (0)