about summary refs log tree commit diff
path: root/src/libsyntax/parse
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-09-06 15:23:55 -0700
committerPatrick Walton <pcwalton@mimiga.net>2014-09-08 16:12:13 -0700
commiteb678ff87f0cdbf523b26fe9255cff684b4091e5 (patch)
tree9fb3745051a57fd5f73d6d50aabf07ce9d2f6ea4 /src/libsyntax/parse
parent6f34760e4173dda94162502153fe4c5a2a96fc9d (diff)
downloadrust-eb678ff87f0cdbf523b26fe9255cff684b4091e5.tar.gz
rust-eb678ff87f0cdbf523b26fe9255cff684b4091e5.zip
librustc: Change the syntax of subslice matching to use postfix `..`
instead of prefix `..`.

This breaks code that looked like:

    match foo {
        [ first, ..middle, last ] => { ... }
    }

Change this code to:

    match foo {
        [ first, middle.., last ] => { ... }
    }

RFC #55.

Closes #16967.

[breaking-change]
Diffstat (limited to 'src/libsyntax/parse')
-rw-r--r--src/libsyntax/parse/obsolete.rs5
-rw-r--r--src/libsyntax/parse/parser.rs68
2 files changed, 42 insertions, 31 deletions
diff --git a/src/libsyntax/parse/obsolete.rs b/src/libsyntax/parse/obsolete.rs
index 5273addf4f5..ec6fd013d08 100644
--- a/src/libsyntax/parse/obsolete.rs
+++ b/src/libsyntax/parse/obsolete.rs
@@ -35,6 +35,7 @@ pub enum ObsoleteSyntax {
     ObsoleteManagedType,
     ObsoleteManagedExpr,
     ObsoleteImportRenaming,
+    ObsoleteSubsliceMatch,
 }
 
 pub trait ParserObsoleteMethods {
@@ -87,6 +88,10 @@ impl<'a> ParserObsoleteMethods for parser::Parser<'a> {
             ObsoleteImportRenaming => (
                 "`use foo = bar` syntax",
                 "write `use bar as foo` instead"
+            ),
+            ObsoleteSubsliceMatch => (
+                "subslice match syntax",
+                "instead of `..xs`, write `xs..` in a pattern"
             )
         };
 
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 936cabc54d1..6aff1152f7e 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -2858,43 +2858,42 @@ impl<'a> Parser<'a> {
         let mut before_slice = true;
 
         while self.token != token::RBRACKET {
-            if first { first = false; }
-            else { self.expect(&token::COMMA); }
+            if first {
+                first = false;
+            } else {
+                self.expect(&token::COMMA);
+            }
 
-            let mut is_slice = false;
             if before_slice {
                 if self.token == token::DOTDOT {
                     self.bump();
-                    is_slice = true;
-                    before_slice = false;
-                }
-            }
 
-            if is_slice {
-                if self.token == token::COMMA || self.token == token::RBRACKET {
-                    slice = Some(box(GC) ast::Pat {
-                        id: ast::DUMMY_NODE_ID,
-                        node: PatWild(PatWildMulti),
-                        span: self.span,
-                    })
-                } else {
-                    let subpat = self.parse_pat();
-                    match *subpat {
-                        ast::Pat { node: PatIdent(_, _, _), .. } => {
-                            slice = Some(subpat);
-                        }
-                        ast::Pat { span, .. } => self.span_fatal(
-                            span, "expected an identifier or nothing"
-                        )
+                    if self.token == token::COMMA ||
+                            self.token == token::RBRACKET {
+                        slice = Some(box(GC) ast::Pat {
+                            id: ast::DUMMY_NODE_ID,
+                            node: PatWild(PatWildMulti),
+                            span: self.span,
+                        });
+                        before_slice = false;
+                    } else {
+                        let _ = self.parse_pat();
+                        let span = self.span;
+                        self.obsolete(span, ObsoleteSubsliceMatch);
                     }
+                    continue
                 }
+            }
+
+            let subpat = self.parse_pat();
+            if before_slice && self.token == token::DOTDOT {
+                self.bump();
+                slice = Some(subpat);
+                before_slice = false;
+            } else if before_slice {
+                before.push(subpat);
             } else {
-                let subpat = self.parse_pat();
-                if before_slice {
-                    before.push(subpat);
-                } else {
-                    after.push(subpat);
-                }
+                after.push(subpat);
             }
         }
 
@@ -3065,7 +3064,11 @@ impl<'a> Parser<'a> {
             // These expressions are limited to literals (possibly
             // preceded by unary-minus) or identifiers.
             let val = self.parse_literal_maybe_minus();
-            if self.eat(&token::DOTDOT) {
+            if self.token == token::DOTDOT &&
+                    self.look_ahead(1, |t| {
+                        *t != token::COMMA && *t != token::RBRACKET
+                    }) {
+                self.bump();
                 let end = if is_ident_or_path(&self.token) {
                     let path = self.parse_path(LifetimeAndTypesWithColons)
                                    .path;
@@ -3106,7 +3109,10 @@ impl<'a> Parser<'a> {
                 }
             });
 
-            if self.look_ahead(1, |t| *t == token::DOTDOT) {
+            if self.look_ahead(1, |t| *t == token::DOTDOT) &&
+                    self.look_ahead(2, |t| {
+                        *t != token::COMMA && *t != token::RBRACKET
+                    }) {
                 let start = self.parse_expr_res(RESTRICT_NO_BAR_OP);
                 self.eat(&token::DOTDOT);
                 let end = self.parse_expr_res(RESTRICT_NO_BAR_OP);