From 7a752788367d06e4bc20351e5235bea8c11667b4 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 3 Feb 2023 12:23:37 +0300 Subject: [PATCH 1/2] Recover from missing expression in for loop --- .../rustc_error_messages/locales/en-US/parse.ftl | 3 +++ compiler/rustc_parse/src/errors.rs | 12 ++++++++++++ compiler/rustc_parse/src/parser/expr.rs | 15 +++++++++++++++ 3 files changed, 30 insertions(+) diff --git a/compiler/rustc_error_messages/locales/en-US/parse.ftl b/compiler/rustc_error_messages/locales/en-US/parse.ftl index 244eb41eb39eb..2ef3dba557ea5 100644 --- a/compiler/rustc_error_messages/locales/en-US/parse.ftl +++ b/compiler/rustc_error_messages/locales/en-US/parse.ftl @@ -128,6 +128,9 @@ parse_missing_in_in_for_loop = missing `in` in `for` loop .use_in_not_of = try using `in` here instead .add_in = try adding `in` here +parse_missing_expression_in_for_loop = missing expression to iterate on in `for` loop + .suggestion = try adding an expression to the `for` loop + parse_missing_comma_after_match_arm = expected `,` following `match` arm .suggestion = missing a comma here to end this `match` arm diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index fd4333dbbecc3..fc7c839f1c461 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -433,6 +433,18 @@ pub(crate) enum MissingInInForLoopSub { AddIn(#[primary_span] Span), } +#[derive(Diagnostic)] +#[diag(parse_missing_expression_in_for_loop)] +pub(crate) struct MissingExpressionInForLoop { + #[primary_span] + #[suggestion( + code = "/* expression */ ", + applicability = "has-placeholders", + style = "verbose" + )] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(parse_missing_comma_after_match_arm)] pub(crate) struct MissingCommaAfterMatchArm { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 473a5bb8cb8c1..c37808f8c3d19 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -2471,6 +2471,21 @@ impl<'a> Parser<'a> { let pat = self.recover_parens_around_for_head(pat, begin_paren); + // Recover from missing expression in `for` loop + if matches!(expr.kind, ExprKind::Block(..)) + && !matches!(self.token.kind, token::OpenDelim(token::Delimiter::Brace)) + && self.may_recover() + { + self.sess + .emit_err(errors::MissingExpressionInForLoop { span: expr.span.shrink_to_lo() }); + let err_expr = self.mk_expr(expr.span, ExprKind::Err); + let block = self.mk_block(vec![], BlockCheckMode::Default, self.prev_token.span); + return Ok(self.mk_expr( + lo.to(self.prev_token.span), + ExprKind::ForLoop(pat, err_expr, block, opt_label), + )); + } + let (attrs, loop_block) = self.parse_inner_attrs_and_block()?; let kind = ExprKind::ForLoop(pat, expr, loop_block, opt_label); From 17b6bd6b70fd49c034b32b5b9b2869d139ed4d46 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 3 Feb 2023 12:25:01 +0300 Subject: [PATCH 2/2] Add ui test for missing expression in for loop --- tests/ui/parser/missing-expression-in-for-loop.rs | 5 +++++ .../ui/parser/missing-expression-in-for-loop.stderr | 13 +++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 tests/ui/parser/missing-expression-in-for-loop.rs create mode 100644 tests/ui/parser/missing-expression-in-for-loop.stderr diff --git a/tests/ui/parser/missing-expression-in-for-loop.rs b/tests/ui/parser/missing-expression-in-for-loop.rs new file mode 100644 index 0000000000000..518a89a0e6fcf --- /dev/null +++ b/tests/ui/parser/missing-expression-in-for-loop.rs @@ -0,0 +1,5 @@ +fn main() { + for i in { + //~^ ERROR missing expression to iterate on in `for` loop + } +} diff --git a/tests/ui/parser/missing-expression-in-for-loop.stderr b/tests/ui/parser/missing-expression-in-for-loop.stderr new file mode 100644 index 0000000000000..74a7c4224fae1 --- /dev/null +++ b/tests/ui/parser/missing-expression-in-for-loop.stderr @@ -0,0 +1,13 @@ +error: missing expression to iterate on in `for` loop + --> $DIR/missing-expression-in-for-loop.rs:2:14 + | +LL | for i in { + | ^ + | +help: try adding an expression to the `for` loop + | +LL | for i in /* expression */ { + | ++++++++++++++++ + +error: aborting due to previous error +