Skip to content

Commit 1ba119c

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

18 files changed

+195
-521
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 32 additions & 7 deletions
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

@@ -2381,9 +2386,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
23812386
return expected;
23822387
}
23832388
}
2384-
InheritedRefMatchRule::EatBoth => {
2389+
InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: true } => {
23852390
// Reset binding mode on old editions
23862391
pat_info.binding_mode = ByRef::No;
2392+
2393+
if let ty::Ref(_, _, _) = *expected.kind() {
2394+
// Consume both the inherited and inner references.
2395+
} else {
2396+
// The expected type isn't a reference type, so only match against the
2397+
// inherited reference.
2398+
if pat_mutbl > inh_mut {
2399+
// We can't match a lone inherited shared reference with `&mut`.
2400+
self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
2401+
}
2402+
2403+
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
2404+
self.check_pat(inner, expected, pat_info);
2405+
return expected;
2406+
}
2407+
}
2408+
InheritedRefMatchRule::EatBoth { eat_inherited_ref_alone: false } => {
2409+
// Reset binding mode on stable Rust. This will be a type error below if
2410+
// `expected` is not a reference type.
2411+
pat_info.binding_mode = ByRef::No;
23872412
self.add_rust_2024_migration_desugared_pat(
23882413
pat_info.top_info.hir_id,
23892414
pat,

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

Lines changed: 16 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -58,155 +58,20 @@ LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
5858
found mutable reference `&mut _`
5959

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

20873
error[E0308]: mismatched types
209-
--> $DIR/pattern-errors.rs:122:11
74+
--> $DIR/pattern-errors.rs:114:11
21075
|
21176
LL | let [&&mut x] = &[&mut 0];
21277
| ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -222,7 +87,7 @@ LL + let [&x] = &[&mut 0];
22287
|
22388

22489
error[E0308]: mismatched types
225-
--> $DIR/pattern-errors.rs:129:11
90+
--> $DIR/pattern-errors.rs:121:11
22691
|
22792
LL | let [&&mut x] = &mut [&mut 0];
22893
| ^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -238,7 +103,7 @@ LL + let [&x] = &mut [&mut 0];
238103
|
239104

240105
error[E0308]: mismatched types
241-
--> $DIR/pattern-errors.rs:136:11
106+
--> $DIR/pattern-errors.rs:128:11
242107
|
243108
LL | let [&&mut ref x] = &[&mut 0];
244109
| ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -254,7 +119,7 @@ LL + let [&ref x] = &[&mut 0];
254119
|
255120

256121
error[E0308]: mismatched types
257-
--> $DIR/pattern-errors.rs:143:11
122+
--> $DIR/pattern-errors.rs:135:11
258123
|
259124
LL | let [&&mut ref x] = &mut [&mut 0];
260125
| ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -270,7 +135,7 @@ LL + let [&ref x] = &mut [&mut 0];
270135
|
271136

272137
error[E0308]: mismatched types
273-
--> $DIR/pattern-errors.rs:150:11
138+
--> $DIR/pattern-errors.rs:142:11
274139
|
275140
LL | let [&&mut mut x] = &[&mut 0];
276141
| ^^^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -286,7 +151,7 @@ LL + let [&mut x] = &[&mut 0];
286151
|
287152

288153
error[E0308]: mismatched types
289-
--> $DIR/pattern-errors.rs:157:11
154+
--> $DIR/pattern-errors.rs:149:11
290155
|
291156
LL | let [&&mut mut x] = &mut [&mut 0];
292157
| ^^^^^^^^^^ ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -302,7 +167,7 @@ LL + let [&mut x] = &mut [&mut 0];
302167
|
303168

304169
error[E0308]: mismatched types
305-
--> $DIR/pattern-errors.rs:172:15
170+
--> $DIR/pattern-errors.rs:164:15
306171
|
307172
LL | let [&mut &x] = &[&mut 0];
308173
| ^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -318,7 +183,7 @@ LL + let [&mut x] = &[&mut 0];
318183
|
319184

320185
error[E0308]: mismatched types
321-
--> $DIR/pattern-errors.rs:178:15
186+
--> $DIR/pattern-errors.rs:170:15
322187
|
323188
LL | let [&mut &ref x] = &[&mut 0];
324189
| ^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -334,7 +199,7 @@ LL + let [&mut ref x] = &[&mut 0];
334199
|
335200

336201
error[E0308]: mismatched types
337-
--> $DIR/pattern-errors.rs:184:15
202+
--> $DIR/pattern-errors.rs:176:15
338203
|
339204
LL | let [&mut &(mut x)] = &[&mut 0];
340205
| ^^^^^^^^ --------- this expression has type `&[&mut {integer}; 1]`
@@ -349,6 +214,6 @@ LL - let [&mut &(mut x)] = &[&mut 0];
349214
LL + let [&mut mut x)] = &[&mut 0];
350215
|
351216

352-
error: aborting due to 21 previous errors
217+
error: aborting due to 14 previous errors
353218

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

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

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ LL + if let Some(&Some(&_)) = &mut Some(&Some(0)) {
6464
|
6565

6666
error[E0308]: mismatched types
67-
--> $DIR/pattern-errors.rs:57:17
67+
--> $DIR/pattern-errors.rs:56:17
6868
|
6969
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
7070
| ^^^^^
@@ -77,7 +77,7 @@ LL + if let Some(&Some(x)) = &Some(Some(0)) {
7777
|
7878

7979
error[E0308]: mismatched types
80-
--> $DIR/pattern-errors.rs:166:10
80+
--> $DIR/pattern-errors.rs:158:10
8181
|
8282
LL | let [&mut x] = &[&mut 0];
8383
| ^^^^^
@@ -90,7 +90,7 @@ LL + let [&x] = &[&mut 0];
9090
|
9191

9292
error[E0308]: mismatched types
93-
--> $DIR/pattern-errors.rs:172:10
93+
--> $DIR/pattern-errors.rs:164:10
9494
|
9595
LL | let [&mut &x] = &[&mut 0];
9696
| ^^^^^
@@ -103,7 +103,7 @@ LL + let [&&x] = &[&mut 0];
103103
|
104104

105105
error[E0308]: mismatched types
106-
--> $DIR/pattern-errors.rs:178:10
106+
--> $DIR/pattern-errors.rs:170:10
107107
|
108108
LL | let [&mut &ref x] = &[&mut 0];
109109
| ^^^^^
@@ -116,7 +116,7 @@ LL + let [&&ref x] = &[&mut 0];
116116
|
117117

118118
error[E0308]: mismatched types
119-
--> $DIR/pattern-errors.rs:184:10
119+
--> $DIR/pattern-errors.rs:176:10
120120
|
121121
LL | let [&mut &(mut x)] = &[&mut 0];
122122
| ^^^^^

0 commit comments

Comments
 (0)