diff options
| author | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-06-05 16:45:29 +0400 |
|---|---|---|
| committer | Maybe Waffle <waffle.lapkin@gmail.com> | 2022-06-05 16:45:29 +0400 |
| commit | f21c0a274ebfb35612359e32bee965afb09640d6 (patch) | |
| tree | df6f875894b8f7ce83b4a67b07521cccb8931a3e /compiler/rustc_parse/src/parser | |
| parent | a2da4af33c5e6a22fff0a223f99d53cba4a5aa52 (diff) | |
| download | rust-f21c0a274ebfb35612359e32bee965afb09640d6.tar.gz rust-f21c0a274ebfb35612359e32bee965afb09640d6.zip | |
Suggest adding `{}` for `'label: non_block_expr`
Diffstat (limited to 'compiler/rustc_parse/src/parser')
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 30 |
1 files changed, 28 insertions, 2 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 63c7decbb2f..761d521a07e 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -13,10 +13,12 @@ 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::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 +1550,33 @@ 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 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 { |
