Skip to content

Commit ed96c65

Browse files
Various fixes:
- Only show error when move-check would not be triggered - Add structured suggestion
1 parent 4f76f10 commit ed96c65

File tree

5 files changed

+71
-38
lines changed

5 files changed

+71
-38
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,13 @@ enum MutblCap {
163163

164164
impl MutblCap {
165165
fn cap_mutbl_to_not(self, span: Option<Span>) -> Self {
166-
if self == MutblCap::Mut { MutblCap::Not(span) } else { self }
166+
if let Some(s) = span
167+
&& self != MutblCap::Not(None)
168+
{
169+
MutblCap::Not(Some(s))
170+
} else {
171+
MutblCap::Not(None)
172+
}
167173
}
168174

169175
fn as_mutbl(self) -> Mutability {
@@ -744,9 +750,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
744750
self.tcx.dcx(),
745751
ident.span,
746752
E0596,
747-
"cannot bind with `ref mut` behind an `&` pattern"
753+
"cannot borrow as mutable inside an `&` pattern"
754+
);
755+
err.span_suggestion(
756+
and_pat_span,
757+
"replace this `&` with `&mut`",
758+
"&mut ",
759+
Applicability::MachineApplicable,
748760
);
749-
err.span_help(and_pat_span, "change this `&` pattern to an `&mut`");
750761
err.emit();
751762
}
752763

@@ -2187,7 +2198,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21872198
// the bad interactions of the given hack detailed in (note_1).
21882199
debug!("check_pat_ref: expected={:?}", expected);
21892200
match *expected.kind() {
2190-
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => (expected, r_ty, pat_info),
2201+
ty::Ref(_, r_ty, r_mutbl) if r_mutbl == mutbl => {
2202+
let pat_info = if r_mutbl == Mutability::Not
2203+
&& ((pat.span.at_least_rust_2024()
2204+
&& self.tcx.features().ref_pat_eat_one_layer_2024)
2205+
|| self.tcx.features().ref_pat_everywhere)
2206+
{
2207+
PatInfo {
2208+
max_ref_mutbl: pat_info.max_ref_mutbl.cap_mutbl_to_not(None),
2209+
..pat_info
2210+
}
2211+
} else {
2212+
pat_info
2213+
};
2214+
(expected, r_ty, pat_info)
2215+
}
21912216

21922217
// `&` pattern eats `&mut` reference
21932218
ty::Ref(_, r_ty, Mutability::Mut)
@@ -2196,16 +2221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
21962221
&& self.tcx.features().ref_pat_eat_one_layer_2024)
21972222
|| self.tcx.features().ref_pat_everywhere) =>
21982223
{
2199-
(
2200-
expected,
2201-
r_ty,
2202-
PatInfo {
2203-
max_ref_mutbl: pat_info
2204-
.max_ref_mutbl
2205-
.cap_mutbl_to_not(Some(pat.span.until(inner.span))),
2206-
..pat_info
2207-
},
2208-
)
2224+
(expected, r_ty, pat_info)
22092225
}
22102226

22112227
_ if consumed_inherited_ref && self.tcx.features().ref_pat_everywhere => {

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,24 @@ pub fn main() {
2424
//~^ ERROR: mismatched types
2525
}
2626
if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
27-
//~^ ERROR: cannot bind with `ref mut` behind an `&` pattern
27+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
2828
}
2929
if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
30-
//~^ ERROR: cannot bind with `ref mut` behind an `&` pattern
30+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
3131
}
3232
if let Some(&mut Some(x)) = &Some(Some(0)) {
3333
//~^ ERROR: mismatched types
3434
}
3535

36-
let &mut _= &&0;
36+
let &mut _ = &&0;
3737
//~^ ERROR: mismatched types
3838

3939
let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
4040
//~^ ERROR: mismatched types
41+
42+
macro_rules! pat {
43+
($var:ident) => { ref mut $var };
44+
}
45+
let &pat!(x) = &mut 0;
46+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
4147
}

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,29 +64,21 @@ LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
6464
= note: expected enum `Option<{integer}>`
6565
found mutable reference `&mut _`
6666

67-
error[E0596]: cannot bind with `ref mut` behind an `&` pattern
67+
error[E0596]: cannot borrow as mutable inside an `&` pattern
6868
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:31
6969
|
7070
LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
71-
| ^
72-
|
73-
help: change this `&` pattern to an `&mut`
74-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17
75-
|
76-
LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
77-
| ^
71+
| - ^
72+
| |
73+
| help: replace this `&` with `&mut`: `&mut`
7874

79-
error[E0596]: cannot bind with `ref mut` behind an `&` pattern
75+
error[E0596]: cannot borrow as mutable inside an `&` pattern
8076
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:29:31
8177
|
8278
LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
83-
| ^
84-
|
85-
help: change this `&` pattern to an `&mut`
86-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:29:12
87-
|
88-
LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
89-
| ^
79+
| - ^
80+
| |
81+
| help: replace this `&` with `&mut`: `&mut`
9082

9183
error[E0308]: mismatched types
9284
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:17
@@ -102,8 +94,8 @@ LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
10294
error[E0308]: mismatched types
10395
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:9
10496
|
105-
LL | let &mut _= &&0;
106-
| ^^^^^^ --- this expression has type `&&{integer}`
97+
LL | let &mut _ = &&0;
98+
| ^^^^^^ --- this expression has type `&&{integer}`
10799
| |
108100
| expected integer, found `&mut _`
109101
|
@@ -121,7 +113,16 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
121113
= note: expected type `{integer}`
122114
found mutable reference `&mut _`
123115

124-
error: aborting due to 11 previous errors
116+
error[E0596]: cannot borrow as mutable inside an `&` pattern
117+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:45:15
118+
|
119+
LL | ($var:ident) => { ref mut $var };
120+
| ------------ help: replace this `&` with `&mut`: `&mut`
121+
LL | }
122+
LL | let &pat!(x) = &mut 0;
123+
| ^
124+
125+
error: aborting due to 12 previous errors
125126

126127
Some errors have detailed explanations: E0308, E0596.
127128
For more information about an error, try `rustc --explain E0308`.

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,7 @@ pub fn main() {
88
//~^ ERROR: cannot move out of a shared reference [E0507]
99
let _: &u32 = x;
1010
}
11+
12+
let &ref mut x = &0;
13+
//~^ cannot borrow data in a `&` reference as mutable [E0596]
1114
}

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail2.stderr

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,13 @@ help: consider borrowing the pattern binding
1212
LL | if let Some(&Some(ref x)) = Some(&Some(&mut 0)) {
1313
| +++
1414

15-
error: aborting due to 1 previous error
15+
error[E0596]: cannot borrow data in a `&` reference as mutable
16+
--> $DIR/ref_pat_eat_one_layer_2024_fail2.rs:12:10
17+
|
18+
LL | let &ref mut x = &0;
19+
| ^^^^^^^^^ cannot borrow as mutable
20+
21+
error: aborting due to 2 previous errors
1622

17-
For more information about this error, try `rustc --explain E0507`.
23+
Some errors have detailed explanations: E0507, E0596.
24+
For more information about an error, try `rustc --explain E0507`.

0 commit comments

Comments
 (0)