@@ -13,10 +13,12 @@ use rustc_ast::tokenstream::Spacing;
13
13
use rustc_ast:: util:: classify;
14
14
use rustc_ast:: util:: literal:: LitError ;
15
15
use rustc_ast:: util:: parser:: { prec_let_scrutinee_needs_par, AssocOp , Fixity } ;
16
+ use rustc_ast:: StmtKind ;
16
17
use rustc_ast:: { self as ast, AttrStyle , AttrVec , CaptureBy , ExprField , Lit , UnOp , DUMMY_NODE_ID } ;
17
18
use rustc_ast:: { AnonConst , BinOp , BinOpKind , FnDecl , FnRetTy , MacCall , Param , Ty , TyKind } ;
18
19
use rustc_ast:: { Arm , Async , BlockCheckMode , Expr , ExprKind , Label , Movability , RangeLimits } ;
19
20
use rustc_ast_pretty:: pprust;
21
+ use rustc_data_structures:: thin_vec:: ThinVec ;
20
22
use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed , PResult } ;
21
23
use rustc_session:: lint:: builtin:: BREAK_WITH_LABEL_AND_LOOP ;
22
24
use rustc_session:: lint:: BuiltinLintDiagnostics ;
@@ -1548,9 +1550,33 @@ impl<'a> Parser<'a> {
1548
1550
Ok ( self . mk_expr_err ( lo) )
1549
1551
} else {
1550
1552
let msg = "expected `while`, `for`, `loop` or `{` after a label" ;
1551
- self . struct_span_err ( self . token . span , msg) . span_label ( self . token . span , msg) . emit ( ) ;
1553
+
1554
+ let mut err = self . struct_span_err ( self . token . span , msg) ;
1555
+ err. span_label ( self . token . span , msg) ;
1556
+
1552
1557
// Continue as an expression in an effort to recover on `'label: non_block_expr`.
1553
- self . parse_expr ( )
1558
+ let expr = self . parse_expr ( ) . map ( |expr| {
1559
+ let span = expr. span ;
1560
+ let sugg_msg = "consider enclosing expression in a block" ;
1561
+ let suggestions = vec ! [
1562
+ ( span. shrink_to_lo( ) , "{" . to_owned( ) ) ,
1563
+ ( span. shrink_to_hi( ) , "}" . to_owned( ) ) ,
1564
+ ] ;
1565
+
1566
+ err. multipart_suggestion_verbose (
1567
+ sugg_msg,
1568
+ suggestions,
1569
+ Applicability :: MachineApplicable ,
1570
+ ) ;
1571
+
1572
+ // Replace `'label: non_block_expr` with `'label: {non_block_expr}` in order to supress future errors about `break 'label`.
1573
+ let stmt = self . mk_stmt ( span, StmtKind :: Expr ( expr) ) ;
1574
+ let blk = self . mk_block ( vec ! [ stmt] , BlockCheckMode :: Default , span) ;
1575
+ self . mk_expr ( span, ExprKind :: Block ( blk, label) , ThinVec :: new ( ) )
1576
+ } ) ;
1577
+
1578
+ err. emit ( ) ;
1579
+ expr
1554
1580
} ?;
1555
1581
1556
1582
if !ate_colon && consume_colon {
0 commit comments