about summary refs log tree commit diff
path: root/src/libsyntax/parse/parser.rs
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2014-06-13 19:09:12 -0700
committerPatrick Walton <pcwalton@mimiga.net>2014-06-23 15:39:29 -0700
commit654d6444feafaa7bae17057d8b98823c7556ea14 (patch)
tree423bbab4e54f324b269942c6af7b1c01a1eeaa36 /src/libsyntax/parse/parser.rs
parent575710f6cee318e2806b4563eb2887c1f03aaa18 (diff)
downloadrust-654d6444feafaa7bae17057d8b98823c7556ea14.tar.gz
rust-654d6444feafaa7bae17057d8b98823c7556ea14.zip
libsyntax: Disallow struct literals after `if`, `while`, `match`, and
`for...in`.

Closes #14803.

If you used a structure literal after one of these keywords, surround it
in parentheses.

[breaking-change]
Diffstat (limited to 'src/libsyntax/parse/parser.rs')
-rw-r--r--src/libsyntax/parse/parser.rs30
1 files changed, 16 insertions, 14 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 4a75473ac11..e3a028ed4d6 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -88,6 +88,7 @@ pub enum restriction {
     RESTRICT_STMT_EXPR,
     RESTRICT_NO_BAR_OP,
     RESTRICT_NO_BAR_OR_DOUBLEBAR_OP,
+    RESTRICT_NO_STRUCT_LITERAL,
 }
 
 type ItemInfo = (Ident, Item_, Option<Vec<Attribute> >);
@@ -2024,8 +2025,9 @@ impl<'a> Parser<'a> {
 
                 return self.mk_mac_expr(lo, hi, MacInvocTT(pth, tts, EMPTY_CTXT));
             } else if self.token == token::LBRACE {
-                // This might be a struct literal.
-                if self.looking_at_struct_literal() {
+                // This is a struct literal, unless we're prohibited from
+                // parsing struct literals here.
+                if self.restriction != RESTRICT_NO_STRUCT_LITERAL {
                     // It's a struct literal.
                     self.bump();
                     let mut fields = Vec::new();
@@ -2042,6 +2044,14 @@ impl<'a> Parser<'a> {
                                          &[token::COMMA], &[token::RBRACE]);
                     }
 
+                    if fields.len() == 0 && base.is_none() {
+                        let last_span = self.last_span;
+                        self.span_err(last_span,
+                                      "structure literal must either have at \
+                                       least one field or use functional \
+                                       structure update syntax");
+                    }
+
                     hi = self.span.hi;
                     self.expect(&token::RBRACE);
                     ex = ExprStruct(pth, fields, base);
@@ -2548,7 +2558,7 @@ impl<'a> Parser<'a> {
     // parse an 'if' expression ('if' token already eaten)
     pub fn parse_if_expr(&mut self) -> Gc<Expr> {
         let lo = self.last_span.lo;
-        let cond = self.parse_expr();
+        let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
         let thn = self.parse_block();
         let mut els: Option<Gc<Expr>> = None;
         let mut hi = thn.span.hi;
@@ -2633,7 +2643,7 @@ impl<'a> Parser<'a> {
         let lo = self.last_span.lo;
         let pat = self.parse_pat();
         self.expect_keyword(keywords::In);
-        let expr = self.parse_expr();
+        let expr = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
         let loop_block = self.parse_block();
         let hi = self.span.hi;
 
@@ -2642,7 +2652,7 @@ impl<'a> Parser<'a> {
 
     pub fn parse_while_expr(&mut self) -> Gc<Expr> {
         let lo = self.last_span.lo;
-        let cond = self.parse_expr();
+        let cond = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
         let body = self.parse_block();
         let hi = body.span.hi;
         return self.mk_expr(lo, hi, ExprWhile(cond, body));
@@ -2655,17 +2665,9 @@ impl<'a> Parser<'a> {
         self.mk_expr(lo, hi, ExprLoop(body, opt_ident))
     }
 
-    // For distinguishing between struct literals and blocks
-    fn looking_at_struct_literal(&mut self) -> bool {
-        self.token == token::LBRACE &&
-        ((self.look_ahead(1, |t| token::is_plain_ident(t)) &&
-          self.look_ahead(2, |t| *t == token::COLON))
-         || self.look_ahead(1, |t| *t == token::DOTDOT))
-    }
-
     fn parse_match_expr(&mut self) -> Gc<Expr> {
         let lo = self.last_span.lo;
-        let discriminant = self.parse_expr();
+        let discriminant = self.parse_expr_res(RESTRICT_NO_STRUCT_LITERAL);
         self.commit_expr_expecting(discriminant, token::LBRACE);
         let mut arms: Vec<Arm> = Vec::new();
         while self.token != token::RBRACE {