diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-04-18 11:35:11 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-04-19 10:13:45 -0700 |
| commit | 4c4ca60edd9775873e555dbb5928b000bd734403 (patch) | |
| tree | 36d0896b30261cfc9be79a761fc6c5a6fab55475 /src/libsyntax/parse | |
| parent | f1be8d16c55990fff8c265352328fd90555feabd (diff) | |
| download | rust-4c4ca60edd9775873e555dbb5928b000bd734403.tar.gz rust-4c4ca60edd9775873e555dbb5928b000bd734403.zip | |
remove duplicated code and simplify logic
Diffstat (limited to 'src/libsyntax/parse')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 61 |
1 files changed, 31 insertions, 30 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a82b1e11a52..a2a2c4637c5 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2856,7 +2856,7 @@ impl<'a> Parser<'a> { hi = self.prev_span; ex = ExprKind::Mac(respan(lo.to(hi), Mac_ { path, tts, delim })); } else if self.check(&token::OpenDelim(token::Brace)) { - if let Some(expr) = self.should_parse_struct_expr(lo, &path, &attrs) { + if let Some(expr) = self.maybe_parse_struct_expr(lo, &path, &attrs) { return expr; } else { hi = path.span; @@ -2904,47 +2904,48 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } - fn should_parse_struct_expr( + fn maybe_parse_struct_expr( &mut self, lo: Span, path: &ast::Path, attrs: &ThinVec<Attribute>, ) -> Option<PResult<'a, P<Expr>>> { + // We don't want to assume it's a struct when encountering `{ <ident>: <ident> }` because + // it could be type ascription, like in `{ ident: u32 }`. + let isnt_ascription = self.look_ahead(1, |t| t.is_ident()) && + self.look_ahead(2, |t| *t == token::Colon) && ( + (self.look_ahead(3, |t| t.is_ident()) && + self.look_ahead(4, |t| *t == token::Comma)) || + self.look_ahead(3, |t| t.is_lit()) || + self.look_ahead(3, |t| *t == token::BinOp(token::Minus)) && + self.look_ahead(4, |t| t.is_lit()) + ); let could_be_struct = self.look_ahead(1, |t| t.is_ident()) && ( - self.look_ahead(2, |t| *t == token::Colon) + self.look_ahead(2, |t| *t == token::Colon) && isnt_ascription || self.look_ahead(2, |t| *t == token::Comma) // We could also check for `token::CloseDelim(token::Brace)`, but that would // have false positives in the case of `if x == y { z } { a }`. ); - let mut bad_struct = false; - let mut parse_struct = !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); - if self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) && could_be_struct { + let bad_struct = self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL); + if !bad_struct || could_be_struct { // This is a struct literal, but we don't can't accept them here - bad_struct = true; - parse_struct = true; - } - if parse_struct { - match self.parse_struct_expr(lo, path.clone(), attrs.clone()) { - Err(err) => return Some(Err(err)), - Ok(expr) => { - if bad_struct { - let mut err = self.diagnostic().struct_span_err( - expr.span, - "struct literals are not allowed here", - ); - err.multipart_suggestion( - "surround the struct literal with parenthesis", - vec![ - (lo.shrink_to_lo(), "(".to_string()), - (expr.span.shrink_to_hi(), ")".to_string()), - ], - Applicability::MachineApplicable, - ); - err.emit(); - } - return Some(Ok(expr)); - } + let expr = self.parse_struct_expr(lo, path.clone(), attrs.clone()); + if let (Ok(expr), true) = (&expr, bad_struct) { + let mut err = self.diagnostic().struct_span_err( + expr.span, + "struct literals are not allowed here", + ); + err.multipart_suggestion( + "surround the struct literal with parenthesis", + vec![ + (lo.shrink_to_lo(), "(".to_string()), + (expr.span.shrink_to_hi(), ")".to_string()), + ], + Applicability::MachineApplicable, + ); + err.emit(); } + return Some(expr); } None } |
