Skip to content

Commit 44ff4df

Browse files
committed
more recovery in if-parsing
1 parent 7262dcc commit 44ff4df

15 files changed

+68
-36
lines changed

src/librustc_parse/parser/expr.rs

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,21 +1412,18 @@ impl<'a> Parser<'a> {
14121412
// verify that the last statement is either an implicit return (no `;`) or an explicit
14131413
// return. This won't catch blocks with an explicit `return`, but that would be caught by
14141414
// the dead code lint.
1415-
if self.eat_keyword(kw::Else) || !cond.returns() {
1416-
let sp = self.sess.source_map().next_point(lo);
1417-
let mut err =
1418-
self.diagnostic().struct_span_err(sp, "missing condition for `if` expression");
1419-
err.span_label(sp, "expected if condition here");
1420-
return Err(err);
1421-
}
1422-
let not_block = self.token != token::OpenDelim(token::Brace);
1423-
let thn = self.parse_block().map_err(|mut err| {
1424-
if not_block {
1425-
err.span_label(lo, "this `if` statement has a condition, but no block");
1426-
}
1427-
err
1428-
})?;
1429-
let mut els: Option<P<Expr>> = None;
1415+
let thn = if self.eat_keyword(kw::Else) || !cond.returns() {
1416+
self.error_missing_if_cond(lo, cond.span)
1417+
} else {
1418+
let not_block = self.token != token::OpenDelim(token::Brace);
1419+
self.parse_block().map_err(|mut err| {
1420+
if not_block {
1421+
err.span_label(lo, "this `if` expression has a condition, but no block");
1422+
}
1423+
err
1424+
})?
1425+
};
1426+
let mut els = None;
14301427
let mut hi = thn.span;
14311428
if self.eat_keyword(kw::Else) {
14321429
let elexpr = self.parse_else_expr()?;
@@ -1436,6 +1433,16 @@ impl<'a> Parser<'a> {
14361433
Ok(self.mk_expr(lo.to(hi), ExprKind::If(cond, thn, els), attrs))
14371434
}
14381435

1436+
fn error_missing_if_cond(&self, lo: Span, span: Span) -> P<ast::Block> {
1437+
let sp = self.sess.source_map().next_point(lo);
1438+
self.struct_span_err(sp, "missing condition for `if` expression")
1439+
.span_label(sp, "expected if condition here")
1440+
.emit();
1441+
let expr = self.mk_expr_err(span);
1442+
let stmt = self.mk_stmt(span, ast::StmtKind::Expr(expr));
1443+
self.mk_block(vec![stmt], BlockCheckMode::Default, span)
1444+
}
1445+
14391446
/// Parses the condition of a `if` or `while` expression.
14401447
fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
14411448
let cond = self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL, None)?;
@@ -1465,10 +1472,10 @@ impl<'a> Parser<'a> {
14651472
/// Parses an `else { ... }` expression (`else` token already eaten).
14661473
fn parse_else_expr(&mut self) -> PResult<'a, P<Expr>> {
14671474
if self.eat_keyword(kw::If) {
1468-
return self.parse_if_expr(AttrVec::new());
1475+
self.parse_if_expr(AttrVec::new())
14691476
} else {
14701477
let blk = self.parse_block()?;
1471-
return Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()));
1478+
Ok(self.mk_expr(blk.span, ExprKind::Block(blk, None), AttrVec::new()))
14721479
}
14731480
}
14741481

src/librustc_parse/parser/stmt.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,7 @@ impl<'a> Parser<'a> {
411411
continue;
412412
};
413413
}
414-
Ok(P(ast::Block { stmts, id: DUMMY_NODE_ID, rules: s, span: lo.to(self.prev_span) }))
414+
Ok(self.mk_block(stmts, s, lo.to(self.prev_span)))
415415
}
416416

417417
/// Parses a statement, including the trailing semicolon.
@@ -471,7 +471,11 @@ impl<'a> Parser<'a> {
471471
.emit();
472472
}
473473

474-
fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
474+
pub(super) fn mk_block(&self, stmts: Vec<Stmt>, rules: BlockCheckMode, span: Span) -> P<Block> {
475+
P(Block { stmts, id: DUMMY_NODE_ID, rules, span })
476+
}
477+
478+
pub(super) fn mk_stmt(&self, span: Span, kind: StmtKind) -> Stmt {
475479
Stmt { id: DUMMY_NODE_ID, kind, span }
476480
}
477481
}

src/test/ui/did_you_mean/issue-46836-identifier-not-instead-of-negation.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ error: expected `{`, found `;`
2626
--> $DIR/issue-46836-identifier-not-instead-of-negation.rs:20:31
2727
|
2828
LL | if not // lack of braces is [sic]
29-
| -- this `if` statement has a condition, but no block
29+
| -- this `if` expression has a condition, but no block
3030
LL | println!("Then when?");
3131
| ^
3232
| |

src/test/ui/if/if-without-block.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
fn main() {
22
let n = 1;
33
if 5 == {
4-
//~^ NOTE this `if` statement has a condition, but no block
4+
//~^ NOTE this `if` expression has a condition, but no block
55
println!("five");
66
}
77
}

src/test/ui/if/if-without-block.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ error: expected `{`, found `}`
22
--> $DIR/if-without-block.rs:7:1
33
|
44
LL | if 5 == {
5-
| -- this `if` statement has a condition, but no block
5+
| -- this `if` expression has a condition, but no block
66
...
77
LL | }
88
| ^ expected `{`

src/test/ui/issues/issue-13483.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
fn main() {
22
if true {
33
} else if { //~ ERROR missing condition
4+
//~^ ERROR mismatched types
45
} else {
56
}
67
}
78

89
fn foo() {
910
if true {
1011
} else if { //~ ERROR missing condition
12+
//~^ ERROR mismatched types
1113
}
1214
bar();
1315
}

src/test/ui/issues/issue-13483.stderr

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,29 @@ LL | } else if {
55
| ^ expected if condition here
66

77
error: missing condition for `if` expression
8-
--> $DIR/issue-13483.rs:10:14
8+
--> $DIR/issue-13483.rs:11:14
99
|
1010
LL | } else if {
1111
| ^ expected if condition here
1212

13-
error: aborting due to 2 previous errors
13+
error[E0308]: mismatched types
14+
--> $DIR/issue-13483.rs:3:15
15+
|
16+
LL | } else if {
17+
| _______________^
18+
LL | |
19+
LL | | } else {
20+
| |_____^ expected `bool`, found `()`
21+
22+
error[E0308]: mismatched types
23+
--> $DIR/issue-13483.rs:11:15
24+
|
25+
LL | } else if {
26+
| _______________^
27+
LL | |
28+
LL | | }
29+
| |_____^ expected `bool`, found `()`
30+
31+
error: aborting due to 4 previous errors
1432

33+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/issues/issue-39848.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: expected `{`, found `foo`
44
LL | if $tgt.has_$field() {}
55
| -- -- help: try placing this code inside a block: `{ () }`
66
| |
7-
| this `if` statement has a condition, but no block
7+
| this `if` expression has a condition, but no block
88
...
99
LL | get_opt!(bar, foo);
1010
| ^^^ expected `{`

src/test/ui/issues/issue-51602.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: expected `{`, found keyword `in`
44
LL | if i in 1..10 {
55
| -- ^^ expected `{`
66
| |
7-
| this `if` statement has a condition, but no block
7+
| this `if` expression has a condition, but no block
88

99
error: aborting due to previous error
1010

src/test/ui/issues/issue-61858.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ error: expected `{`, found `)`
44
LL | (if foobar)
55
| -- ^ expected `{`
66
| |
7-
| this `if` statement has a condition, but no block
7+
| this `if` expression has a condition, but no block
88

99
error: aborting due to previous error
1010

0 commit comments

Comments
 (0)