Skip to content

Commit 2c89cb1

Browse files
Jules-Bertholetlcnr
authored andcommitted
&mut no longer peels off &
1 parent 45aa3f5 commit 2c89cb1

File tree

4 files changed

+147
-88
lines changed

4 files changed

+147
-88
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -335,9 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
335335
match adjust_mode {
336336
AdjustMode::Pass => (expected, def_br, max_ref_mutbl),
337337
AdjustMode::Reset => (expected, ByRef::No, MutblCap::Mut),
338-
AdjustMode::Peel => {
339-
self.peel_off_references(pat, expected, def_br, Mutability::Mut, max_ref_mutbl)
340-
}
338+
AdjustMode::Peel => self.peel_off_references(pat, expected, def_br, max_ref_mutbl),
341339
}
342340
}
343341

@@ -408,7 +406,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
408406
pat: &'tcx Pat<'tcx>,
409407
expected: Ty<'tcx>,
410408
mut def_br: ByRef,
411-
max_peelable_mutability: Mutability,
412409
mut max_ref_mutability: MutblCap,
413410
) -> (Ty<'tcx>, ByRef, MutblCap) {
414411
let mut expected = self.try_structurally_resolve_type(pat.span, expected);
@@ -421,9 +418,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
421418
//
422419
// See the examples in `ui/match-defbm*.rs`.
423420
let mut pat_adjustments = vec![];
424-
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind()
425-
&& inner_mutability <= max_peelable_mutability
426-
{
421+
while let ty::Ref(_, inner_ty, inner_mutability) = *expected.kind() {
427422
debug!("inspecting {:?}", expected);
428423

429424
debug!("current discriminant is Ref, inserting implicit deref");
@@ -2130,32 +2125,39 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21302125
pat.span.at_least_rust_2024() && self.tcx.features().ref_pat_eat_one_layer_2024;
21312126

21322127
if new_match_ergonomics {
2128+
let pat_prefix_span =
2129+
inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end));
2130+
21332131
if pat_mutbl == Mutability::Not {
21342132
// Prevent the inner pattern from binding with `ref mut`.
2135-
pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(
2136-
inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end)),
2137-
);
2138-
}
2133+
pat_info.max_ref_mutbl = pat_info.max_ref_mutbl.cap_to_weakly_not(pat_prefix_span);
2134+
}
2135+
2136+
if let ByRef::Yes(inh_mut) = pat_info.binding_mode {
2137+
// ref pattern consumes inherited reference
2138+
2139+
if pat_mutbl > inh_mut {
2140+
// Tried to match inherited `ref` with `&mut`, which is an error
2141+
let err_msg = "cannot match inherited `&` with `&mut` pattern";
2142+
let err = if let Some(span) = pat_prefix_span {
2143+
let mut err = self.dcx().struct_span_err(span, err_msg);
2144+
err.span_suggestion_verbose(
2145+
span,
2146+
"replace this `&mut` pattern with `&`",
2147+
"&",
2148+
Applicability::MachineApplicable,
2149+
);
2150+
err
2151+
} else {
2152+
self.dcx().struct_span_err(pat.span, err_msg)
2153+
};
2154+
err.emit();
2155+
}
21392156

2140-
if let ByRef::Yes(inh_mut) = pat_info.binding_mode
2141-
&& pat_mutbl <= inh_mut
2142-
{
21432157
pat_info.binding_mode = ByRef::No;
21442158
self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
21452159
self.check_pat(inner, expected, pat_info);
21462160
return expected;
2147-
} else if pat_mutbl == Mutability::Mut {
2148-
// `&mut` patterns pell off `&` references
2149-
let (new_expected, new_bm, max_ref_mutbl) = self.peel_off_references(
2150-
pat,
2151-
expected,
2152-
pat_info.binding_mode,
2153-
Mutability::Not,
2154-
pat_info.max_ref_mutbl,
2155-
);
2156-
expected = new_expected;
2157-
pat_info.binding_mode = new_bm;
2158-
pat_info.max_ref_mutbl = max_ref_mutbl;
21592161
}
21602162
} else {
21612163
// Reset binding mode on old editions

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024.rs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ pub fn main() {
2323
if let Some(Some(&x)) = &Some(&Some(0)) {
2424
let _: u32 = x;
2525
}
26-
if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
27-
let _: u32 = x;
28-
}
2926
if let Some(&Some(&x)) = &mut Some(&Some(0)) {
3027
let _: u32 = x;
3128
}
@@ -35,9 +32,6 @@ pub fn main() {
3532
if let Some(&Some(&mut ref x)) = Some(&Some(&mut 0)) {
3633
let _: &u32 = x;
3734
}
38-
if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
39-
let _: &u32 = x;
40-
}
4135
if let &Some(Some(x)) = &Some(&mut Some(0)) {
4236
let _: &u32 = x;
4337
}
@@ -59,13 +53,4 @@ pub fn main() {
5953
if let Some(&Some(x)) = &mut Some(Some(0)) {
6054
let _: u32 = x;
6155
}
62-
63-
let &mut x = &&mut 0;
64-
let _: &u32 = x;
65-
66-
let &mut x = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
67-
let _: &u32 = x;
68-
69-
let &mut &mut &mut &mut x = &mut &&&&mut &&&mut &mut 0;
70-
let _: &u32 = x;
7156
}

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,31 +5,48 @@
55

66
pub fn main() {
77
if let Some(&mut Some(&_)) = &Some(&Some(0)) {
8-
//~^ ERROR: mismatched types
8+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
99
}
1010
if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
11-
//~^ ERROR: mismatched types
11+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
1212
}
1313
if let Some(&Some(x)) = &mut Some(&Some(0)) {
1414
let _: &mut u32 = x;
1515
//~^ ERROR: mismatched types
1616
}
1717
if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
18-
//~^ ERROR: mismatched types
18+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
1919
}
2020
if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
21-
//~^ ERROR: mismatched types
21+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
2222
}
2323
if let Some(&mut Some(x)) = &Some(Some(0)) {
24-
//~^ ERROR: mismatched types
24+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
2525
}
2626
if let Some(&mut Some(x)) = &Some(Some(0)) {
27-
//~^ ERROR: mismatched types
27+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
2828
}
2929

3030
let &mut _ = &&0;
3131
//~^ ERROR: mismatched types
3232

3333
let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
3434
//~^ ERROR: mismatched types
35+
36+
if let Some(&mut Some(&_)) = &Some(&mut Some(0)) {
37+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
38+
}
39+
40+
if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
41+
//~^ ERROR: cannot match inherited `&` with `&mut` pattern
42+
}
43+
44+
let &mut _ = &&mut 0;
45+
//~^ ERROR: mismatched types
46+
47+
let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
48+
//~^ ERROR: mismatched types
49+
50+
let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
51+
//~^ ERROR: mismatched types
3552
}
Lines changed: 96 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
1-
error[E0308]: mismatched types
1+
error: cannot match inherited `&` with `&mut` pattern
22
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:7:17
33
|
44
LL | if let Some(&mut Some(&_)) = &Some(&Some(0)) {
5-
| ^^^^^^^^^^^^^ --------------- this expression has type `&Option<&Option<{integer}>>`
6-
| |
7-
| expected `Option<{integer}>`, found `&mut _`
5+
| ^^^^^
86
|
9-
= note: expected enum `Option<{integer}>`
10-
found mutable reference `&mut _`
7+
help: replace this `&mut` pattern with `&`
8+
|
9+
LL | if let Some(&Some(&_)) = &Some(&Some(0)) {
10+
| ~
1111

12-
error[E0308]: mismatched types
12+
error: cannot match inherited `&` with `&mut` pattern
1313
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:10:23
1414
|
1515
LL | if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
16-
| ^^^^^^ ------------------- this expression has type `&Option<&mut Option<{integer}>>`
17-
| |
18-
| expected integer, found `&mut _`
16+
| ^^^^^
1917
|
20-
= note: expected type `{integer}`
21-
found mutable reference `&mut _`
18+
help: replace this `&mut` pattern with `&`
19+
|
20+
LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) {
21+
| ~
2222

2323
error[E0308]: mismatched types
2424
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:14:27
@@ -31,59 +31,59 @@ LL | let _: &mut u32 = x;
3131
= note: expected mutable reference `&mut u32`
3232
found reference `&{integer}`
3333

34-
error[E0308]: mismatched types
34+
error: cannot match inherited `&` with `&mut` pattern
3535
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:17:23
3636
|
3737
LL | if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
38-
| ^^^^^^ ------------------- this expression has type `&mut Option<&Option<{integer}>>`
39-
| |
40-
| expected integer, found `&mut _`
38+
| ^^^^^
4139
|
42-
= note: expected type `{integer}`
43-
found mutable reference `&mut _`
40+
help: replace this `&mut` pattern with `&`
41+
|
42+
LL | if let Some(&Some(&_)) = &mut Some(&Some(0)) {
43+
| ~
4444

45-
error[E0308]: mismatched types
45+
error: cannot match inherited `&` with `&mut` pattern
4646
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:20:29
4747
|
4848
LL | if let Some(&Some(Some((&mut _)))) = &Some(Some(&mut Some(0))) {
49-
| ^^^^^^ ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
50-
| |
51-
| expected integer, found `&mut _`
49+
| ^^^^^
5250
|
53-
= note: expected type `{integer}`
54-
found mutable reference `&mut _`
51+
help: replace this `&mut` pattern with `&`
52+
|
53+
LL | if let Some(&Some(Some((&_)))) = &Some(Some(&mut Some(0))) {
54+
| ~
5555

56-
error[E0308]: mismatched types
56+
error: cannot match inherited `&` with `&mut` pattern
5757
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:23:17
5858
|
5959
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
60-
| ^^^^^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
61-
| |
62-
| expected `Option<{integer}>`, found `&mut _`
60+
| ^^^^^
6361
|
64-
= note: expected enum `Option<{integer}>`
65-
found mutable reference `&mut _`
62+
help: replace this `&mut` pattern with `&`
63+
|
64+
LL | if let Some(&Some(x)) = &Some(Some(0)) {
65+
| ~
6666

67-
error[E0308]: mismatched types
67+
error: cannot match inherited `&` with `&mut` pattern
6868
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17
6969
|
7070
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
71-
| ^^^^^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
72-
| |
73-
| expected `Option<{integer}>`, found `&mut _`
71+
| ^^^^^
7472
|
75-
= note: expected enum `Option<{integer}>`
76-
found mutable reference `&mut _`
73+
help: replace this `&mut` pattern with `&`
74+
|
75+
LL | if let Some(&Some(x)) = &Some(Some(0)) {
76+
| ~
7777

7878
error[E0308]: mismatched types
7979
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9
8080
|
8181
LL | let &mut _ = &&0;
8282
| ^^^^^^ --- this expression has type `&&{integer}`
8383
| |
84-
| expected integer, found `&mut _`
84+
| types differ in mutability
8585
|
86-
= note: expected type `{integer}`
86+
= note: expected reference `&&{integer}`
8787
found mutable reference `&mut _`
8888

8989
error[E0308]: mismatched types
@@ -92,11 +92,66 @@ error[E0308]: mismatched types
9292
LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
9393
| ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
9494
| |
95-
| expected integer, found `&mut _`
95+
| types differ in mutability
96+
|
97+
= note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
98+
found mutable reference `&mut _`
99+
100+
error: cannot match inherited `&` with `&mut` pattern
101+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:17
102+
|
103+
LL | if let Some(&mut Some(&_)) = &Some(&mut Some(0)) {
104+
| ^^^^^
105+
|
106+
help: replace this `&mut` pattern with `&`
107+
|
108+
LL | if let Some(&Some(&_)) = &Some(&mut Some(0)) {
109+
| ~
110+
111+
error: cannot match inherited `&` with `&mut` pattern
112+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:40:22
113+
|
114+
LL | if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
115+
| ^^^^^
116+
|
117+
help: replace this `&mut` pattern with `&`
118+
|
119+
LL | if let Some(Some(&x)) = &Some(Some(&mut 0)) {
120+
| ~
121+
122+
error[E0308]: mismatched types
123+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:44:9
124+
|
125+
LL | let &mut _ = &&mut 0;
126+
| ^^^^^^ ------- this expression has type `&&mut {integer}`
127+
| |
128+
| types differ in mutability
129+
|
130+
= note: expected reference `&&mut {integer}`
131+
found mutable reference `&mut _`
132+
133+
error[E0308]: mismatched types
134+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:47:9
135+
|
136+
LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&mut 0;
137+
| ^^^^^^ --------------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}`
138+
| |
139+
| types differ in mutability
140+
|
141+
= note: expected reference `&&&&&&&&&&&&&&&&&&&&&&&&&&&&mut {integer}`
142+
found mutable reference `&mut _`
143+
144+
error[E0308]: mismatched types
145+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:50:14
146+
|
147+
LL | let &mut &mut &mut &mut _ = &mut &&&&mut &&&mut &mut 0;
148+
| ^^^^^^^^^^^^^^^^ -------------------------- this expression has type `&mut &&&&mut &&&mut &mut {integer}`
149+
| |
150+
| types differ in mutability
96151
|
97-
= note: expected type `{integer}`
152+
= note: expected reference `&&&&mut &&&mut &mut {integer}`
98153
found mutable reference `&mut _`
99154

100-
error: aborting due to 9 previous errors
155+
error: aborting due to 14 previous errors
101156

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

0 commit comments

Comments
 (0)