Skip to content

Commit 0b1e08c

Browse files
committed
parse: recover mut (x @ y) as (mut x @ mut y).
1 parent 75b98fb commit 0b1e08c

File tree

3 files changed

+34
-27
lines changed

3 files changed

+34
-27
lines changed

src/librustc_parse/parser/pat.rs

+13-16
Original file line numberDiff line numberDiff line change
@@ -503,17 +503,18 @@ impl<'a> Parser<'a> {
503503
// Parse the pattern we hope to be an identifier.
504504
let mut pat = self.parse_pat(Some("identifier"))?;
505505

506-
// Add `mut` to any binding in the parsed pattern.
507-
let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat);
508-
509-
// Unwrap; If we don't have `mut $ident`, error.
510-
let pat = pat.into_inner();
511-
match &pat.kind {
512-
PatKind::Ident(..) => {}
513-
_ => self.ban_mut_general_pat(mut_span, &pat, changed_any_binding),
506+
// If we don't have `mut $ident (@ pat)?`, error.
507+
if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind {
508+
// Don't recurse into the subpattern.
509+
// `mut` on the outer binding doesn't affect the inner bindings.
510+
*m = Mutability::Mut;
511+
} else {
512+
// Add `mut` to any binding in the parsed pattern.
513+
let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat);
514+
self.ban_mut_general_pat(mut_span, &pat, changed_any_binding);
514515
}
515516

516-
Ok(pat.kind)
517+
Ok(pat.into_inner().kind)
517518
}
518519

519520
/// Recover on `mut ref? ident @ pat` and suggest
@@ -542,14 +543,10 @@ impl<'a> Parser<'a> {
542543
}
543544

544545
fn visit_pat(&mut self, pat: &mut P<Pat>) {
545-
if let PatKind::Ident(ref mut bm, ..) = pat.kind {
546-
if let BindingMode::ByValue(ref mut m @ Mutability::Not) = bm {
547-
*m = Mutability::Mut;
548-
}
546+
if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind
547+
{
549548
self.0 = true;
550-
// Don't recurse into the subpattern, mut on the outer
551-
// binding doesn't affect the inner bindings.
552-
return;
549+
*m = Mutability::Mut;
553550
}
554551
noop_visit_pat(pat, self);
555552
}

src/test/ui/parser/mut-patterns.rs

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ pub fn main() {
99
let mut _ = 0; //~ ERROR `mut` must be followed by a named binding
1010
let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding
1111

12+
let mut (x @ y) = 0; //~ ERROR `mut` must be attached to each individual binding
13+
1214
let mut mut x = 0;
1315
//~^ ERROR `mut` on a binding may not be repeated
1416
//~| remove the additional `mut`s

src/test/ui/parser/mut-patterns.stderr

+19-11
Original file line numberDiff line numberDiff line change
@@ -14,36 +14,44 @@ LL | let mut (_, _) = (0, 0);
1414
|
1515
= note: `mut` may be followed by `variable` and `variable @ pattern`
1616

17+
error: `mut` must be attached to each individual binding
18+
--> $DIR/mut-patterns.rs:12:9
19+
|
20+
LL | let mut (x @ y) = 0;
21+
| ^^^^^^^^^^^ help: add `mut` to each binding: `(mut x @ mut y)`
22+
|
23+
= note: `mut` may be followed by `variable` and `variable @ pattern`
24+
1725
error: `mut` on a binding may not be repeated
18-
--> $DIR/mut-patterns.rs:12:13
26+
--> $DIR/mut-patterns.rs:14:13
1927
|
2028
LL | let mut mut x = 0;
2129
| ^^^ help: remove the additional `mut`s
2230

2331
error: `mut` must be attached to each individual binding
24-
--> $DIR/mut-patterns.rs:17:9
32+
--> $DIR/mut-patterns.rs:19:9
2533
|
2634
LL | let mut Foo { x: x } = Foo { x: 3 };
2735
| ^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { x: mut x }`
2836
|
2937
= note: `mut` may be followed by `variable` and `variable @ pattern`
3038

3139
error: `mut` must be attached to each individual binding
32-
--> $DIR/mut-patterns.rs:21:9
40+
--> $DIR/mut-patterns.rs:23:9
3341
|
3442
LL | let mut Foo { x } = Foo { x: 3 };
3543
| ^^^^^^^^^^^^^ help: add `mut` to each binding: `Foo { mut x }`
3644
|
3745
= note: `mut` may be followed by `variable` and `variable @ pattern`
3846

3947
error: `mut` on a binding may not be repeated
40-
--> $DIR/mut-patterns.rs:26:13
48+
--> $DIR/mut-patterns.rs:28:13
4149
|
4250
LL | let mut mut yield(become, await) = r#yield(0, 0);
4351
| ^^^ help: remove the additional `mut`s
4452

4553
error: expected identifier, found reserved keyword `yield`
46-
--> $DIR/mut-patterns.rs:26:17
54+
--> $DIR/mut-patterns.rs:28:17
4755
|
4856
LL | let mut mut yield(become, await) = r#yield(0, 0);
4957
| ^^^^^ expected identifier, found reserved keyword
@@ -54,7 +62,7 @@ LL | let mut mut r#yield(become, await) = r#yield(0, 0);
5462
| ^^^^^^^
5563

5664
error: expected identifier, found reserved keyword `become`
57-
--> $DIR/mut-patterns.rs:26:23
65+
--> $DIR/mut-patterns.rs:28:23
5866
|
5967
LL | let mut mut yield(become, await) = r#yield(0, 0);
6068
| ^^^^^^ expected identifier, found reserved keyword
@@ -65,7 +73,7 @@ LL | let mut mut yield(r#become, await) = r#yield(0, 0);
6573
| ^^^^^^^^
6674

6775
error: expected identifier, found keyword `await`
68-
--> $DIR/mut-patterns.rs:26:31
76+
--> $DIR/mut-patterns.rs:28:31
6977
|
7078
LL | let mut mut yield(become, await) = r#yield(0, 0);
7179
| ^^^^^ expected identifier, found keyword
@@ -76,23 +84,23 @@ LL | let mut mut yield(become, r#await) = r#yield(0, 0);
7684
| ^^^^^^^
7785

7886
error: `mut` must be attached to each individual binding
79-
--> $DIR/mut-patterns.rs:26:9
87+
--> $DIR/mut-patterns.rs:28:9
8088
|
8189
LL | let mut mut yield(become, await) = r#yield(0, 0);
8290
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `r#yield(mut r#become, mut r#await)`
8391
|
8492
= note: `mut` may be followed by `variable` and `variable @ pattern`
8593

8694
error: `mut` must be attached to each individual binding
87-
--> $DIR/mut-patterns.rs:35:9
95+
--> $DIR/mut-patterns.rs:37:9
8896
|
8997
LL | let mut W(mut a, W(b, W(ref c, W(d, B { box f }))))
9098
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: add `mut` to each binding: `W(mut a, W(mut b, W(ref c, W(mut d, B { box mut f }))))`
9199
|
92100
= note: `mut` may be followed by `variable` and `variable @ pattern`
93101

94102
error: expected identifier, found `x`
95-
--> $DIR/mut-patterns.rs:42:21
103+
--> $DIR/mut-patterns.rs:44:21
96104
|
97105
LL | let mut $p = 0;
98106
| ^^ expected identifier
@@ -102,5 +110,5 @@ LL | foo!(x);
102110
|
103111
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
104112

105-
error: aborting due to 12 previous errors
113+
error: aborting due to 13 previous errors
106114

0 commit comments

Comments
 (0)