about summary refs log tree commit diff
path: root/src/librustc_parse/parser
diff options
context:
space:
mode:
authorMazdak Farrokhzad <twingoow@gmail.com>2019-12-06 23:23:30 +0100
committerMazdak Farrokhzad <twingoow@gmail.com>2019-12-23 13:42:25 +0100
commit44ff4df49dfbff2d21999ec9360ed8df655a6d9b (patch)
treeaf62c5be9a100517fbd4b794c7a0946e1c97d413 /src/librustc_parse/parser
parent7262dcc4a78a4e63db29410365fe7d47f2b56fd0 (diff)
downloadrust-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.rs41
-rw-r--r--src/librustc_parse/parser/stmt.rs8
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 }
     }
 }