diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2022-06-06 08:37:03 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-06-06 08:37:03 +0200 |
| commit | 554674b98cb5fdf2fd55620775d359b16423817c (patch) | |
| tree | ee2bc35c4c1cf1c156d29b647729f80e1e74d402 /compiler/rustc_parse/src/parser/expr.rs | |
| parent | c9c6c2e7de0b651617e0cc2b5c1ae368c516361e (diff) | |
| parent | 4f85a73e516530844aecc44fb91d0db7604f7ac4 (diff) | |
| download | rust-554674b98cb5fdf2fd55620775d359b16423817c.tar.gz rust-554674b98cb5fdf2fd55620775d359b16423817c.zip | |
Rollup merge of #97759 - WaffleLapkin:recover_label_expr, r=compiler-errors
Suggest adding `{}` for `'label: non_block_expr`
Adds suggestions like this:
```text
help: consider enclosing expression in a block
|
3 | 'l {0};
| + +
```
inspired by https://github.com/rust-lang/rust/issues/48594#issuecomment-1146744400
r? ``@compiler-errors``
Diffstat (limited to 'compiler/rustc_parse/src/parser/expr.rs')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 64 |
1 files changed, 62 insertions, 2 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 63c7decbb2f..b786c52e688 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -13,10 +13,13 @@ use rustc_ast::tokenstream::Spacing; use rustc_ast::util::classify; use rustc_ast::util::literal::LitError; use rustc_ast::util::parser::{prec_let_scrutinee_needs_par, AssocOp, Fixity}; +use rustc_ast::visit::Visitor; +use rustc_ast::StmtKind; use rustc_ast::{self as ast, AttrStyle, AttrVec, CaptureBy, ExprField, Lit, UnOp, DUMMY_NODE_ID}; use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty, TyKind}; use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits}; use rustc_ast_pretty::pprust; +use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult}; use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP; use rustc_session::lint::BuiltinLintDiagnostics; @@ -1548,9 +1551,66 @@ impl<'a> Parser<'a> { Ok(self.mk_expr_err(lo)) } else { let msg = "expected `while`, `for`, `loop` or `{` after a label"; - self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit(); + + let mut err = self.struct_span_err(self.token.span, msg); + err.span_label(self.token.span, msg); + // Continue as an expression in an effort to recover on `'label: non_block_expr`. - self.parse_expr() + let expr = self.parse_expr().map(|expr| { + let span = expr.span; + + let found_labeled_breaks = { + struct FindLabeledBreaksVisitor(bool); + + impl<'ast> Visitor<'ast> for FindLabeledBreaksVisitor { + fn visit_expr_post(&mut self, ex: &'ast Expr) { + if let ExprKind::Break(Some(_label), _) = ex.kind { + self.0 = true; + } + } + } + + let mut vis = FindLabeledBreaksVisitor(false); + vis.visit_expr(&expr); + vis.0 + }; + + // Suggestion involves adding a (as of time of writing this, unstable) labeled block. + // + // If there are no breaks that may use this label, suggest removing the label and + // recover to the unmodified expression. + if !found_labeled_breaks { + let msg = "consider removing the label"; + err.span_suggestion_verbose( + lo.until(span), + msg, + "", + Applicability::MachineApplicable, + ); + + return expr; + } + + let sugg_msg = "consider enclosing expression in a block"; + let suggestions = vec![ + (span.shrink_to_lo(), "{ ".to_owned()), + (span.shrink_to_hi(), " }".to_owned()), + ]; + + err.multipart_suggestion_verbose( + sugg_msg, + suggestions, + Applicability::MachineApplicable, + ); + + // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`. + let stmt = self.mk_stmt(span, StmtKind::Expr(expr)); + let blk = self.mk_block(vec![stmt], BlockCheckMode::Default, span); + self.mk_expr(span, ExprKind::Block(blk, label), ThinVec::new()) + }); + + err.emit(); + expr }?; if !ate_colon && consume_colon { |
