mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-21 04:54:26 +00:00
more recovery in if-parsing
This commit is contained in:
parent
7262dcc4a7
commit
44ff4df49d
@ -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 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);
|
||||
let thn = self.parse_block().map_err(|mut err| {
|
||||
self.parse_block().map_err(|mut err| {
|
||||
if not_block {
|
||||
err.span_label(lo, "this `if` statement has a condition, but no block");
|
||||
err.span_label(lo, "this `if` expression has a condition, but no block");
|
||||
}
|
||||
err
|
||||
})?;
|
||||
let mut els: Option<P<Expr>> = None;
|
||||
})?
|
||||
};
|
||||
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()))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
@ -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?");
|
||||
| ^
|
||||
| |
|
||||
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
@ -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 `{`
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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`.
|
||||
|
@ -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 `{`
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
| ^^^-
|
||||
| |
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user