about summary refs log tree commit diff
path: root/src/librustc_parse/parser
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-02-18 22:16:31 +0100
committerGitHub <noreply@github.com>2020-02-18 22:16:31 +0100
commit6c6d45c6e7ca1e7685e2556d9f58b6f3109c13bf (patch)
tree39649c075dab42df78c94de2fafa81466fc7694d /src/librustc_parse/parser
parentc499570b5d287f10adfeb63580c8c92a1d5329c5 (diff)
parent0b1e08cb557768f168266c7bbcdcb93fcf372a66 (diff)
downloadrust-6c6d45c6e7ca1e7685e2556d9f58b6f3109c13bf.tar.gz
rust-6c6d45c6e7ca1e7685e2556d9f58b6f3109c13bf.zip
Rollup merge of #69236 - Centril:mut-parens-at-recovery, r=estebank
parse: recover `mut (x @ y)` as `(mut x @ mut y)`.

Follow up to https://github.com/rust-lang/rust/pull/68992#discussion_r376829749 and https://github.com/rust-lang/rust/pull/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
Diffstat (limited to 'src/librustc_parse/parser')
-rw-r--r--src/librustc_parse/parser/pat.rs29
1 files changed, 13 insertions, 16 deletions
diff --git a/src/librustc_parse/parser/pat.rs b/src/librustc_parse/parser/pat.rs
index ec6d4db6102..520d325f16b 100644
--- a/src/librustc_parse/parser/pat.rs
+++ b/src/librustc_parse/parser/pat.rs
@@ -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
@@ -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);
             }