diff options
| author | Patrick Walton <pcwalton@mimiga.net> | 2014-06-13 19:09:12 -0700 |
|---|---|---|
| committer | Patrick Walton <pcwalton@mimiga.net> | 2014-06-23 15:39:29 -0700 |
| commit | 654d6444feafaa7bae17057d8b98823c7556ea14 (patch) | |
| tree | 423bbab4e54f324b269942c6af7b1c01a1eeaa36 /src/libsyntax/parse/parser.rs | |
| parent | 575710f6cee318e2806b4563eb2887c1f03aaa18 (diff) | |
| download | rust-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.rs | 30 |
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 { |
