Skip to content

Commit

Permalink
recover from for-else and while-else
Browse files Browse the repository at this point in the history
  • Loading branch information
y21 committed Feb 24, 2023
1 parent 07c993e commit 8574085
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 0 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_parse/locales/en-US.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop
parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop
.suggestion = try adding an expression to the `for` loop
parse_loop_else = `{$loop_kind}...else` loops are not supported
.note = consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
parse_missing_comma_after_match_arm = expected `,` following `match` arm
.suggestion = missing a comma here to end this `match` arm
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_parse/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,15 @@ pub(crate) struct MissingExpressionInForLoop {
pub span: Span,
}

#[derive(Diagnostic)]
#[diag(parse_loop_else)]
#[note]
pub(crate) struct LoopElseNotSupported {
#[primary_span]
pub span: Span,
pub loop_kind: &'static str,
}

#[derive(Diagnostic)]
#[diag(parse_missing_comma_after_match_arm)]
pub(crate) struct MissingCommaAfterMatchArm {
Expand Down
20 changes: 20 additions & 0 deletions compiler/rustc_parse/src/parser/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2491,9 +2491,26 @@ impl<'a> Parser<'a> {
let (attrs, loop_block) = self.parse_inner_attrs_and_block()?;

let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label);

self.recover_loop_else("for")?;

Ok(self.mk_expr_with_attrs(lo.to(self.prev_token.span), kind, attrs))
}

/// Recovers from an `else` clause after a loop (`for...else`, `while...else`)
fn recover_loop_else(&mut self, loop_kind: &'static str) -> PResult<'a, ()> {
if self.token.is_keyword(kw::Else) && self.may_recover() {
let else_span = self.token.span;
self.bump();
let else_clause = self.parse_else_expr()?;
self.sess.emit_err(errors::LoopElseNotSupported {
span: else_span.to(else_clause.span),
loop_kind,
});
}
Ok(())
}

fn error_missing_in_for_loop(&mut self) {
let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
// Possibly using JS syntax (#75311).
Expand All @@ -2518,6 +2535,9 @@ impl<'a> Parser<'a> {
err.span_label(cond.span, "this `while` condition successfully parsed");
err
})?;

self.recover_loop_else("while")?;

Ok(self.mk_expr_with_attrs(
lo.to(self.prev_token.span),
ExprKind::While(cond, body, opt_label),
Expand Down
8 changes: 8 additions & 0 deletions tests/ui/for/for-else-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
for _ in 0..1 {

} else {
//~^ ERROR `for...else` loops are not supported
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
}
}
14 changes: 14 additions & 0 deletions tests/ui/for/for-else-err.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `for...else` loops are not supported
--> $DIR/for-else-err.rs:4:7
|
LL | } else {
| _______^
LL | |
LL | |
LL | | }
| |_____^
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run

error: aborting due to previous error

8 changes: 8 additions & 0 deletions tests/ui/for/for-else-let-else-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
let _ = for _ in 0..1 {

} else {
//~^ ERROR `for...else` loops are not supported
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
};
}
14 changes: 14 additions & 0 deletions tests/ui/for/for-else-let-else-err.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `for...else` loops are not supported
--> $DIR/for-else-let-else-err.rs:4:7
|
LL | } else {
| _______^
LL | |
LL | |
LL | | };
| |_____^
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run

error: aborting due to previous error

8 changes: 8 additions & 0 deletions tests/ui/while/while-else-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
while false {

} else {
//~^ ERROR `while...else` loops are not supported
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
};
}
14 changes: 14 additions & 0 deletions tests/ui/while/while-else-err.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `while...else` loops are not supported
--> $DIR/while-else-err.rs:4:7
|
LL | } else {
| _______^
LL | |
LL | |
LL | | };
| |_____^
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run

error: aborting due to previous error

8 changes: 8 additions & 0 deletions tests/ui/while/while-else-let-else-err.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
fn main() {
let _ = while false {

} else {
//~^ ERROR `while...else` loops are not supported
//~| NOTE consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
};
}
14 changes: 14 additions & 0 deletions tests/ui/while/while-else-let-else-err.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
error: `while...else` loops are not supported
--> $DIR/while-else-let-else-err.rs:4:7
|
LL | } else {
| _______^
LL | |
LL | |
LL | | };
| |_____^
|
= note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run

error: aborting due to previous error

0 comments on commit 8574085

Please sign in to comment.