about summary refs log tree commit diff
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
parent7262dcc4a78a4e63db29410365fe7d47f2b56fd0 (diff)
downloadrust-44ff4df49dfbff2d21999ec9360ed8df655a6d9b.tar.gz
rust-44ff4df49dfbff2d21999ec9360ed8df655a6d9b.zip
more recovery in if-parsing
-rw-r--r--src/librustc_parse/parser/expr.rs41
-rw-r--r--src/librustc_parse/parser/stmt.rs8
-rw-r--r--src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr2
-rw-r--r--src/test/ui/if/if-without-block.rs2
-rw-r--r--src/test/ui/if/if-without-block.stderr2
-rw-r--r--src/test/ui/issues/issue-13483.rs2
-rw-r--r--src/test/ui/issues/issue-13483.stderr23
-rw-r--r--src/test/ui/issues/issue-39848.stderr2
-rw-r--r--src/test/ui/issues/issue-51602.stderr2
-rw-r--r--src/test/ui/issues/issue-61858.stderr2
-rw-r--r--src/test/ui/issues/issue-62554.stderr2
-rw-r--r--src/test/ui/label/label_break_value_illegal_uses.stderr2
-rw-r--r--src/test/ui/missing/missing-block-hint.stderr4
-rw-r--r--src/test/ui/parser/attr-stmt-expr-attr-bad.stderr8
-rw-r--r--src/test/ui/parser/doc-comment-in-if-statement.stderr2
15 files changed, 68 insertions, 36 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 }
     }
 }
diff --git a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
index f5edbe2a3af..8025886a9eb 100644
--- a/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
+++ b/src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr
@@ -26,7 +26,7 @@ error: expected `{`, found `;`
   --> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31
    |
 LL |     if not  // lack of braces is [sic]
-   |     -- this `if` statement has a condition, but no block
+   |     -- this `if` expression has a condition, but no block
 LL |         println!("Then when?");
    |                               ^
    |                               |
diff --git a/src/test/ui/if/if-without-block.rs b/src/test/ui/if/if-without-block.rs
index 3dde0ed7c71..8a4c59f3261 100644
--- a/src/test/ui/if/if-without-block.rs
+++ b/src/test/ui/if/if-without-block.rs
@@ -1,7 +1,7 @@
 fn main() {
     let n = 1;
     if 5 == {
-    //~^ NOTE this `if` statement has a condition, but no block
+    //~^ NOTE this `if` expression has a condition, but no block
         println!("five");
     }
 }
diff --git a/src/test/ui/if/if-without-block.stderr b/src/test/ui/if/if-without-block.stderr
index 1e45045adec..34df8e3d779 100644
--- a/src/test/ui/if/if-without-block.stderr
+++ b/src/test/ui/if/if-without-block.stderr
@@ -2,7 +2,7 @@ error: expected `{`, found `}`
   --> $DIR/if-without-block.rs:7:1
    |
 LL |     if 5 == {
-   |     -- this `if` statement has a condition, but no block
+   |     -- this `if` expression has a condition, but no block
 ...
 LL | }
    | ^ expected `{`
diff --git a/src/test/ui/issues/issue-13483.rs b/src/test/ui/issues/issue-13483.rs
index cb53523b3b0..a2fd9264b15 100644
--- a/src/test/ui/issues/issue-13483.rs
+++ b/src/test/ui/issues/issue-13483.rs
@@ -1,6 +1,7 @@
 fn main() {
     if true {
     } else if { //~ ERROR missing condition
+    //~^ ERROR mismatched types
     } else {
     }
 }
@@ -8,6 +9,7 @@ fn main() {
 fn foo() {
     if true {
     } else if { //~ ERROR missing condition
+    //~^ ERROR mismatched types
     }
     bar();
 }
diff --git a/src/test/ui/issues/issue-13483.stderr b/src/test/ui/issues/issue-13483.stderr
index df9f1dd0115..5fd05b18ce0 100644
--- a/src/test/ui/issues/issue-13483.stderr
+++ b/src/test/ui/issues/issue-13483.stderr
@@ -5,10 +5,29 @@ LL |     } else if {
    |              ^ expected if condition here
 
 error: missing condition for `if` expression
-  --> $DIR/issue-13483.rs:10:14
+  --> $DIR/issue-13483.rs:11:14
    |
 LL |     } else if {
    |              ^ expected if condition here
 
-error: aborting due to 2 previous errors
+error[E0308]: mismatched types
+  --> $DIR/issue-13483.rs:3:15
+   |
+LL |       } else if {
+   |  _______________^
+LL | |
+LL | |     } else {
+   | |_____^ expected `bool`, found `()`
+
+error[E0308]: mismatched types
+  --> $DIR/issue-13483.rs:11:15
+   |
+LL |       } else if {
+   |  _______________^
+LL | |
+LL | |     }
+   | |_____^ expected `bool`, found `()`
+
+error: aborting due to 4 previous errors
 
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-39848.stderr b/src/test/ui/issues/issue-39848.stderr
index 47aa8e17a30..11b145d6e0d 100644
--- a/src/test/ui/issues/issue-39848.stderr
+++ b/src/test/ui/issues/issue-39848.stderr
@@ -4,7 +4,7 @@ error: expected `{`, found `foo`
 LL |         if $tgt.has_$field() {}
    |         --                -- help: try placing this code inside a block: `{ () }`
    |         |
-   |         this `if` statement has a condition, but no block
+   |         this `if` expression has a condition, but no block
 ...
 LL |     get_opt!(bar, foo);
    |                   ^^^ expected `{`
diff --git a/src/test/ui/issues/issue-51602.stderr b/src/test/ui/issues/issue-51602.stderr
index 1ad69c0191b..d800890bca3 100644
--- a/src/test/ui/issues/issue-51602.stderr
+++ b/src/test/ui/issues/issue-51602.stderr
@@ -4,7 +4,7 @@ error: expected `{`, found keyword `in`
 LL |     if i in 1..10 {
    |     --   ^^ expected `{`
    |     |
-   |     this `if` statement has a condition, but no block
+   |     this `if` expression has a condition, but no block
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-61858.stderr b/src/test/ui/issues/issue-61858.stderr
index ea2ec3d013f..8b95d9c6ae4 100644
--- a/src/test/ui/issues/issue-61858.stderr
+++ b/src/test/ui/issues/issue-61858.stderr
@@ -4,7 +4,7 @@ error: expected `{`, found `)`
 LL |     (if foobar)
    |      --       ^ expected `{`
    |      |
-   |      this `if` statement has a condition, but no block
+   |      this `if` expression has a condition, but no block
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-62554.stderr b/src/test/ui/issues/issue-62554.stderr
index 87aaa036613..d59546e2383 100644
--- a/src/test/ui/issues/issue-62554.stderr
+++ b/src/test/ui/issues/issue-62554.stderr
@@ -17,7 +17,7 @@ error: expected `{`, found `macro_rules`
 LL | fn foo(u: u8) { if u8 macro_rules! u8 { (u6) => { fn uuuuuuuuuuu() { use s loo mod u8 {
    |                 --    ^^^^^^^^^^^ expected `{`
    |                 |
-   |                 this `if` statement has a condition, but no block
+   |                 this `if` expression has a condition, but no block
    |
 help: try placing this code inside a block
    |
diff --git a/src/test/ui/label/label_break_value_illegal_uses.stderr b/src/test/ui/label/label_break_value_illegal_uses.stderr
index 0036f0f1db0..46b53c65b48 100644
--- a/src/test/ui/label/label_break_value_illegal_uses.stderr
+++ b/src/test/ui/label/label_break_value_illegal_uses.stderr
@@ -12,7 +12,7 @@ LL |     if true 'b: {}
    |     |       |
    |     |       expected `{`
    |     |       help: try placing this code inside a block: `{ 'b: {} }`
-   |     this `if` statement has a condition, but no block
+   |     this `if` expression has a condition, but no block
 
 error: expected `{`, found `'b`
   --> $DIR/label_break_value_illegal_uses.rs:14:21
diff --git a/src/test/ui/missing/missing-block-hint.stderr b/src/test/ui/missing/missing-block-hint.stderr
index ee86a3241e8..0f635817bf4 100644
--- a/src/test/ui/missing/missing-block-hint.stderr
+++ b/src/test/ui/missing/missing-block-hint.stderr
@@ -4,13 +4,13 @@ error: expected `{`, found `=>`
 LL |         if (foo) => {}
    |         --       ^^ expected `{`
    |         |
-   |         this `if` statement has a condition, but no block
+   |         this `if` expression has a condition, but no block
 
 error: expected `{`, found `bar`
   --> $DIR/missing-block-hint.rs:7:13
    |
 LL |         if (foo)
-   |         -- this `if` statement has a condition, but no block
+   |         -- this `if` expression has a condition, but no block
 LL |             bar;
    |             ^^^-
    |             |
diff --git a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
index 9a0d3176714..30aa820141c 100644
--- a/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
+++ b/src/test/ui/parser/attr-stmt-expr-attr-bad.stderr
@@ -149,7 +149,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 #[attr] {}; }
    |                                --   ^       --- help: try placing this code inside a block: `{ {}; }`
    |                                |    |
    |                                |    expected `{`
-   |                                this `if` statement has a condition, but no block
+   |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:43:38
@@ -202,7 +202,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if 0 {} else if 0 #[attr] {}; }
    |                                             --   ^       --- help: try placing this code inside a block: `{ {}; }`
    |                                             |    |
    |                                             |    expected `{`
-   |                                             this `if` statement has a condition, but no block
+   |                                             this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:56:51
@@ -225,7 +225,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 #[attr] {}; }
    |                                --           ^       --- help: try placing this code inside a block: `{ {}; }`
    |                                |            |
    |                                |            expected `{`
-   |                                this `if` statement has a condition, but no block
+   |                                this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:62:46
@@ -278,7 +278,7 @@ LL | #[cfg(FALSE)] fn e() { let _ = if let _ = 0 {} else if let _ = 0 #[attr] {}
    |                                                     --           ^       --- help: try placing this code inside a block: `{ {}; }`
    |                                                     |            |
    |                                                     |            expected `{`
-   |                                                     this `if` statement has a condition, but no block
+   |                                                     this `if` expression has a condition, but no block
 
 error: an inner attribute is not permitted in this context
   --> $DIR/attr-stmt-expr-attr-bad.rs:75:67
diff --git a/src/test/ui/parser/doc-comment-in-if-statement.stderr b/src/test/ui/parser/doc-comment-in-if-statement.stderr
index 6bcb77385d7..a720dd68bd0 100644
--- a/src/test/ui/parser/doc-comment-in-if-statement.stderr
+++ b/src/test/ui/parser/doc-comment-in-if-statement.stderr
@@ -4,7 +4,7 @@ error: expected `{`, found doc comment `/*!*/`
 LL |     if true /*!*/ {}
    |     --      ^^^^^ expected `{`
    |     |
-   |     this `if` statement has a condition, but no block
+   |     this `if` expression has a condition, but no block
 
 error: aborting due to previous error