Skip to content

Commit

Permalink
Rollup merge of rust-lang#69236 - Centril:mut-parens-at-recovery, r=e…
Browse files Browse the repository at this point in the history
…stebank

parse: recover `mut (x @ y)` as `(mut x @ mut y)`.

Follow up to rust-lang#68992 (comment) and rust-lang#63945.

Specifically, when given `let mut (x @ y)` we recover with `let (mut x @ mut y)` as the suggestion:

```rust
error: `mut` must be attached to each individual binding
  --> $DIR/mut-patterns.rs:12:9
   |
LL |     let mut (x @ y) = 0;
   |         ^^^^^^^^^^^ help: add `mut` to each binding: `(mut x @ mut y)`
   |
   = note: `mut` may be followed by `variable` and `variable @ pattern`
```

r? @matthewjasper @estebank
  • Loading branch information
Centril committed Feb 18, 2020
2 parents c499570 + 0b1e08c commit 6c6d45c
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 27 deletions.
29 changes: 13 additions & 16 deletions src/librustc_parse/parser/pat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,17 +503,18 @@ impl<'a> Parser<'a> {
// Parse the pattern we hope to be an identifier.
let mut pat = self.parse_pat(Some("identifier"))?;

// Add `mut` to any binding in the parsed pattern.
let changed_any_binding = Self::make_all_value_bindings_mutable(&mut pat);

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

Ok(pat.kind)
Ok(pat.into_inner().kind)
}

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

fn visit_pat(&mut self, pat: &mut P<Pat>) {
if let PatKind::Ident(ref mut bm, ..) = pat.kind {
if let BindingMode::ByValue(ref mut m @ Mutability::Not) = bm {
*m = Mutability::Mut;
}
if let PatKind::Ident(BindingMode::ByValue(m @ Mutability::Not), ..) = &mut pat.kind
{
self.0 = true;
// Don't recurse into the subpattern, mut on the outer
// binding doesn't affect the inner bindings.
return;
*m = Mutability::Mut;
}
noop_visit_pat(pat, self);
}
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/parser/mut-patterns.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub fn main() {
let mut _ = 0; //~ ERROR `mut` must be followed by a named binding
let mut (_, _) = (0, 0); //~ ERROR `mut` must be followed by a named binding

let mut (x @ y) = 0; //~ ERROR `mut` must be attached to each individual binding

let mut mut x = 0;
//~^ ERROR `mut` on a binding may not be repeated
//~| remove the additional `mut`s
Expand Down
30 changes: 19 additions & 11 deletions src/test/ui/parser/mut-patterns.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -14,36 +14,44 @@ LL | let mut (_, _) = (0, 0);
|
= note: `mut` may be followed by `variable` and `variable @ pattern`

error: `mut` must be attached to each individual binding
--> $DIR/mut-patterns.rs:12:9
|
LL | let mut (x @ y) = 0;
| ^^^^^^^^^^^ help: add `mut` to each binding: `(mut x @ mut y)`
|
= note: `mut` may be followed by `variable` and `variable @ pattern`

error: `mut` on a binding may not be repeated
--> $DIR/mut-patterns.rs:12:13
--> $DIR/mut-patterns.rs:14:13
|
LL | let mut mut x = 0;
| ^^^ help: remove the additional `mut`s

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

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

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

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

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

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

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

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

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

error: aborting due to 12 previous errors
error: aborting due to 13 previous errors

0 comments on commit 6c6d45c

Please sign in to comment.