diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2019-04-14 17:09:03 -0700 |
|---|---|---|
| committer | Esteban Küber <esteban@kuber.com.ar> | 2019-04-19 10:13:44 -0700 |
| commit | 2f36b54f0f33427e926872935c325a660967af6f (patch) | |
| tree | 1ed541f3fee0898fef1b7676da1c248effc29f88 /src/libsyntax | |
| parent | a2bbf7debaab60be33bd8008a71bca69576945a0 (diff) | |
| download | rust-2f36b54f0f33427e926872935c325a660967af6f.tar.gz rust-2f36b54f0f33427e926872935c325a660967af6f.zip | |
Emit specific error for struct literal in conditions
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/parse/parser.rs | 57 |
1 files changed, 52 insertions, 5 deletions
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a5adb37f745..7d130470c6a 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2855,11 +2855,13 @@ impl<'a> Parser<'a> { let (delim, tts) = self.expect_delimited_token_tree()?; hi = self.prev_span; ex = ExprKind::Mac(respan(lo.to(hi), Mac_ { path, tts, delim })); - } else if self.check(&token::OpenDelim(token::Brace)) && - !self.restrictions.contains(Restrictions::NO_STRUCT_LITERAL) { - // This is a struct literal, unless we're prohibited - // from parsing struct literals here. - return self.parse_struct_expr(lo, path, attrs); + } else if self.check(&token::OpenDelim(token::Brace)) { + if let Some(expr) = self.should_parse_struct_expr(lo, path.clone(), attrs.clone()) { + return expr; + } else { + hi = path.span; + ex = ExprKind::Path(None, path); + } } else { hi = path.span; ex = ExprKind::Path(None, path); @@ -2902,6 +2904,51 @@ impl<'a> Parser<'a> { self.maybe_recover_from_bad_qpath(expr, true) } + fn should_parse_struct_expr( + &mut self, + lo: Span, + path: ast::Path, + attrs: ThinVec<Attribute>, + ) -> Option<PResult<'a, P<Expr>>> { + 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::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 { + // 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, attrs) { + 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)); + } + } + } + None + } + fn parse_struct_expr(&mut self, lo: Span, pth: ast::Path, mut attrs: ThinVec<Attribute>) -> PResult<'a, P<Expr>> { let struct_sp = lo.to(self.prev_span); |
