Skip to content

Commit f57b970

Browse files
Comments and fixes
1 parent 91bbbaa commit f57b970

6 files changed

+132
-55
lines changed

compiler/rustc_hir_typeck/src/pat.rs

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -137,8 +137,8 @@ enum AdjustMode {
137137
/// with mutability matching the pattern,
138138
/// mark the pattern as having consumed this reference.
139139
///
140-
/// `Span` is that of the `&` or `&mut` itself
141-
ResetAndConsumeRef(Mutability, Span),
140+
/// `Span` is that of the `&` or `&mut` itself.
141+
ResetAndConsumeRef(Mutability, Option<Span>),
142142
/// Pass on the input binding mode and expected type.
143143
Pass,
144144
}
@@ -154,15 +154,23 @@ enum AdjustMode {
154154
/// this last case, so we need to throw an error ourselves.
155155
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
156156
enum MutblCap {
157-
/// Mutability restricted to immutable;
158-
/// contained span, if present, should be shown in diagnostics as the reason.
159-
Not(Option<Span>),
157+
/// Mutability restricted to immutable.
158+
///
159+
/// The contained span, if present, points to an `&` pattern
160+
/// that is the reason for the restriction,
161+
/// and which will be reported in a diagnostic.
162+
/// (Said diagnostic is shown only if
163+
/// replacing the `&` pattern with `&mut` would allow the code to compile.)
164+
///
165+
/// (Outer [`Option`] is for whether to show the diagnostic,
166+
/// inner [`Option`] is for whether we have a span we can report)
167+
Not(Option<Option<Span>>),
160168
/// No restriction on mutability
161169
Mut,
162170
}
163171

164172
impl MutblCap {
165-
fn cap_mutbl_to_not(self, span: Option<Span>) -> Self {
173+
fn cap_mutbl_to_not(self, span: Option<Option<Span>>) -> Self {
166174
if let Some(s) = span
167175
&& self != MutblCap::Not(None)
168176
{
@@ -434,7 +442,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
434442
// ```
435443
//
436444
// See issue #46688.
437-
PatKind::Ref(inner, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl, pat.span.until(inner.span.find_ancestor_inside(pat.span).unwrap())),
445+
PatKind::Ref(inner, mutbl) => AdjustMode::ResetAndConsumeRef(*mutbl, inner.span.find_ancestor_inside(pat.span).map(|end| pat.span.until(end))),
438446
// A `_` pattern works with any expected type, so there's no need to do anything.
439447
PatKind::Wild
440448
// A malformed pattern doesn't have an expected type, so let's just accept any type.
@@ -752,12 +760,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
752760
E0596,
753761
"cannot borrow as mutable inside an `&` pattern"
754762
);
755-
err.span_suggestion(
756-
and_pat_span,
757-
"replace this `&` with `&mut`",
758-
"&mut ",
759-
Applicability::MachineApplicable,
760-
);
763+
764+
if let Some(span) = and_pat_span {
765+
err.span_suggestion(
766+
span,
767+
"replace this `&` with `&mut`",
768+
"&mut ",
769+
Applicability::MachineApplicable,
770+
);
771+
}
761772
err.emit();
762773
}
763774

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.rs

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,6 @@ pub fn main() {
2323
if let Some(&mut Some(x)) = &Some(Some(0)) {
2424
//~^ ERROR: mismatched types
2525
}
26-
if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
27-
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
28-
}
29-
if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
30-
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
31-
}
3226
if let Some(&mut Some(x)) = &Some(Some(0)) {
3327
//~^ ERROR: mismatched types
3428
}
@@ -38,10 +32,4 @@ pub fn main() {
3832

3933
let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
4034
//~^ 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
4735
}

tests/ui/match/ref_pat_eat_one_layer_2024/ref_pat_eat_one_layer_2024_fail.stderr

Lines changed: 5 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -64,24 +64,8 @@ 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 borrow as mutable inside an `&` pattern
68-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:31
69-
|
70-
LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
71-
| - ^
72-
| |
73-
| help: replace this `&` with `&mut`: `&mut`
74-
75-
error[E0596]: cannot borrow as mutable inside an `&` pattern
76-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:29:31
77-
|
78-
LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
79-
| - ^
80-
| |
81-
| help: replace this `&` with `&mut`: `&mut`
82-
8367
error[E0308]: mismatched types
84-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:32:17
68+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:26:17
8569
|
8670
LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
8771
| ^^^^^^^^^^^^ -------------- this expression has type `&Option<Option<{integer}>>`
@@ -92,7 +76,7 @@ LL | if let Some(&mut Some(x)) = &Some(Some(0)) {
9276
found mutable reference `&mut _`
9377

9478
error[E0308]: mismatched types
95-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:36:9
79+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:30:9
9680
|
9781
LL | let &mut _ = &&0;
9882
| ^^^^^^ --- this expression has type `&&{integer}`
@@ -103,7 +87,7 @@ LL | let &mut _ = &&0;
10387
found mutable reference `&mut _`
10488

10589
error[E0308]: mismatched types
106-
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:39:9
90+
--> $DIR/ref_pat_eat_one_layer_2024_fail.rs:33:9
10791
|
10892
LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
10993
| ^^^^^^ ----------------------------- this expression has type `&&&&&&&&&&&&&&&&&&&&&&&&&&&&{integer}`
@@ -113,15 +97,6 @@ LL | let &mut _ = &&&&&&&&&&&&&&&&&&&&&&&&&&&&0;
11397
= note: expected type `{integer}`
11498
found mutable reference `&mut _`
11599

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 | let &pat!(x) = &mut 0;
120-
| - ^
121-
| |
122-
| help: replace this `&` with `&mut`: `&mut`
123-
124-
error: aborting due to 12 previous errors
100+
error: aborting due to 9 previous errors
125101

126-
Some errors have detailed explanations: E0308, E0596.
127-
For more information about an error, try `rustc --explain E0308`.
102+
For more information about this error, try `rustc --explain E0308`.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
//@ run-rustfix
4+
#![allow(incomplete_features)]
5+
#![feature(ref_pat_eat_one_layer_2024)]
6+
7+
pub fn main() {
8+
if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
9+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
10+
let _: &mut u8 = x;
11+
}
12+
13+
if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
14+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
15+
let _: &mut u8 = x;
16+
}
17+
18+
macro_rules! pat {
19+
($var:ident) => { ref mut $var };
20+
}
21+
let &mut pat!(x) = &mut 0;
22+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
23+
let _: &mut u8 = x;
24+
25+
let &mut (ref mut a, ref mut b) = &mut (true, false);
26+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
27+
//~| ERROR: cannot borrow as mutable inside an `&` pattern
28+
let _: &mut bool = a;
29+
let _: &mut bool = b;
30+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
//@ run-rustfix
4+
#![allow(incomplete_features)]
5+
#![feature(ref_pat_eat_one_layer_2024)]
6+
7+
pub fn main() {
8+
if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
9+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
10+
let _: &mut u8 = x;
11+
}
12+
13+
if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
14+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
15+
let _: &mut u8 = x;
16+
}
17+
18+
macro_rules! pat {
19+
($var:ident) => { ref mut $var };
20+
}
21+
let &pat!(x) = &mut 0;
22+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
23+
let _: &mut u8 = x;
24+
25+
let &(ref mut a, ref mut b) = &mut (true, false);
26+
//~^ ERROR: cannot borrow as mutable inside an `&` pattern
27+
//~| ERROR: cannot borrow as mutable inside an `&` pattern
28+
let _: &mut bool = a;
29+
let _: &mut bool = b;
30+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
error[E0596]: cannot borrow as mutable inside an `&` pattern
2+
--> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:8:31
3+
|
4+
LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
5+
| - ^
6+
| |
7+
| help: replace this `&` with `&mut`: `&mut`
8+
9+
error[E0596]: cannot borrow as mutable inside an `&` pattern
10+
--> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:13:31
11+
|
12+
LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
13+
| - ^
14+
| |
15+
| help: replace this `&` with `&mut`: `&mut`
16+
17+
error[E0596]: cannot borrow as mutable inside an `&` pattern
18+
--> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:21:15
19+
|
20+
LL | let &pat!(x) = &mut 0;
21+
| - ^
22+
| |
23+
| help: replace this `&` with `&mut`: `&mut`
24+
25+
error[E0596]: cannot borrow as mutable inside an `&` pattern
26+
--> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:25:19
27+
|
28+
LL | let &(ref mut a, ref mut b) = &mut (true, false);
29+
| - ^
30+
| |
31+
| help: replace this `&` with `&mut`: `&mut`
32+
33+
error[E0596]: cannot borrow as mutable inside an `&` pattern
34+
--> $DIR/ref_pat_eat_one_layer_2024_ref_mut_inside_and.rs:25:30
35+
|
36+
LL | let &(ref mut a, ref mut b) = &mut (true, false);
37+
| - ^
38+
| |
39+
| help: replace this `&` with `&mut`: `&mut`
40+
41+
error: aborting due to 5 previous errors
42+
43+
For more information about this error, try `rustc --explain E0596`.

0 commit comments

Comments
 (0)