diff options
| author | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-12-06 23:23:30 +0100 |
|---|---|---|
| committer | Mazdak Farrokhzad <twingoow@gmail.com> | 2019-12-23 13:42:25 +0100 |
| commit | 44ff4df49dfbff2d21999ec9360ed8df655a6d9b (patch) | |
| tree | af62c5be9a100517fbd4b794c7a0946e1c97d413 /src/librustc_parse/parser | |
| parent | 7262dcc4a78a4e63db29410365fe7d47f2b56fd0 (diff) | |
| download | rust-44ff4df49dfbff2d21999ec9360ed8df655a6d9b.tar.gz rust-44ff4df49dfbff2d21999ec9360ed8df655a6d9b.zip | |
more recovery in if-parsing
Diffstat (limited to 'src/librustc_parse/parser')
| -rw-r--r-- | src/librustc_parse/parser/expr.rs | 41 | ||||
| -rw-r--r-- | src/librustc_parse/parser/stmt.rs | 8 |
2 files changed, 30 insertions, 19 deletions
diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index 17198040d25..e67d3f6991a 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -1412,21 +1412,18 @@ impl<'a> Parser<'a> { // verify that the last statement is either an implicit return (no `;`) or an explicit // return. This won't catch blocks with an explicit `return`, but that would be caught by // the dead code lint. - if self.eat_keyword(kw::Else) || !cond.returns() { - let sp = self.sess.source_map().next_point(lo); - let mut err = - self.diagnostic().struct_span_err(sp, "missing condition for `if` expression"); - err.span_label(sp, "expected if condition here"); - return Err(err); - } - let not_block = self.token != token::OpenDelim(token::Brace); - let thn = self.parse_block().map_err(|mut err| { - if not_block { - err.span_label(lo, "this `if` statement has a condition, but no block"); - } - err - })?; - let mut els: Option<P<Expr>> = None; + let thn = if self.eat_keyword(kw::Else) || !cond.returns() { + self.error_missing_if_cond(lo, cond.span) + } else { + let not_block = self.token != token::OpenDelim(token::Brace); + self.parse_block().map_err(|mut err| { + if not_block { + err.span_label(lo, "this `if` expression has a condition, but no block"); + } + err + })? + }; + let mut els = None; let mut hi = thn.span; if self.eat_keyword(kw::Else) { let elexpr = self.parse_else_expr()?; @@ -1436,6 +1433,16 @@ impl<'a> Parser<'a> { Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs)) } + fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> { + let sp = self.sess.source_map().next_point(lo); + self.struct_span_err(sp, "missing condition for `if` expression") + .span_label(sp, "expected if condition here") + .emit(); + let expr = self.mk_expr_err(span); + let stmt = self.mk_stmt(span, ast::StmtKind::Expr(expr)); + self.mk_block(vec![stmt], BlockCheckMode::Default, span) + } + /// Parses the condition of a `if` or `while` expression. fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> { let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?; @@ -1465,10 +1472,10 @@ impl<'a> Parser<'a> { /// Parses an `else { ... }` expression (`else` token already eaten). fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> { if self.eat_keyword(kw::If) { - return self.parse_if_expr(AttrVec::new()); + self.parse_if_expr(AttrVec::new()) } else { let blk = self.parse_block()?; - return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())); + Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new())) } } diff --git a/src/librustc_parse/parser/stmt.rs b/src/librustc_parse/parser/stmt.rs index ed5649310e3..44a197503bd 100644 --- a/src/librustc_parse/parser/stmt.rs +++ b/src/librustc_parse/parser/stmt.rs @@ -411,7 +411,7 @@ impl<'a> Parser<'a> { continue; }; } - Ok(P(ast::Block { stmts, id: DUMMY_NODE_ID, rules: s, span: lo.to(self.prev_span) })) + Ok(self.mk_block(stmts, s, lo.to(self.prev_span))) } /// Parses a statement, including the trailing semicolon. @@ -471,7 +471,11 @@ impl<'a> Parser<'a> { .emit(); } - fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { + pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> { + P(Block { stmts, id: DUMMY_NODE_ID, rules, span }) + } + + pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt { Stmt { id: DUMMY_NODE_ID, kind, span } } } |
