about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2020-02-17 16:03:07 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2020-02-17 16:08:13 +0100
commit0b1e08cb557768f168266c7bbcdcb93fcf372a66 (patch)
tree6e1f2aa851a0c8531e1562899b25aae4e097120c /src
parent75b98fbe77d472d85d1691bae5b25e7eefb3609c (diff)
downloadrust-0b1e08cb557768f168266c7bbcdcb93fcf372a66.tar.gz
rust-0b1e08cb557768f168266c7bbcdcb93fcf372a66.zip
parse: recover `mut (x @ y)` as `(mut x @ mut y)`.
Diffstat (limited to 'src')
-rw-r--r--src/librustc_parse/parser/pat.rs29
-rw-r--r--src/test/ui/parser/mut-patterns.rs2
-rw-r--r--src/test/ui/parser/mut-patterns.stderr30
3 files changed, 34 insertions, 27 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);
             }
diff --git a/src/test/ui/parser/mut-patterns.rs b/src/test/ui/parser/mut-patterns.rs
index 66fd5893af5..8b83d6ab2f8 100644
--- a/src/test/ui/parser/mut-patterns.rs
+++ b/src/test/ui/parser/mut-patterns.rs
@@ -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
diff --git a/src/test/ui/parser/mut-patterns.stderr b/src/test/ui/parser/mut-patterns.stderr
index 5f4c349d7d6..9a6af7394bf 100644
--- a/src/test/ui/parser/mut-patterns.stderr
+++ b/src/test/ui/parser/mut-patterns.stderr
@@ -14,14 +14,22 @@ 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 }`
@@ -29,7 +37,7 @@ LL |     let mut Foo { x: x } = Foo { x: 3 };
    = 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 }`
@@ -37,13 +45,13 @@ LL |     let mut Foo { x } = Foo { x: 3 };
    = 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
@@ -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
@@ -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
@@ -76,7 +84,7 @@ 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)`
@@ -84,7 +92,7 @@ LL |     let mut mut yield(become, await) = r#yield(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: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 }))))`
@@ -92,7 +100,7 @@ LL |     let mut W(mut a, W(b, W(ref c, W(d, B { box 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
@@ -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