@@ -13,10 +13,12 @@ use rustc_ast::tokenstream::Spacing;
1313use rustc_ast:: util:: classify;
1414use rustc_ast:: util:: literal:: LitError ;
1515use rustc_ast:: util:: parser:: { prec_let_scrutinee_needs_par, AssocOp , Fixity } ;
16+ use rustc_ast:: StmtKind ;
1617use rustc_ast:: { self as ast, AttrStyle , AttrVec , CaptureBy , ExprField , Lit , UnOp , DUMMY_NODE_ID } ;
1718use rustc_ast:: { AnonConst , BinOp , BinOpKind , FnDecl , FnRetTy , MacCall , Param , Ty , TyKind } ;
1819use rustc_ast:: { Arm , Async , BlockCheckMode , Expr , ExprKind , Label , Movability , RangeLimits } ;
1920use rustc_ast_pretty:: pprust;
21+ use rustc_data_structures:: thin_vec:: ThinVec ;
2022use rustc_errors:: { Applicability , Diagnostic , DiagnosticBuilder , ErrorGuaranteed , PResult } ;
2123use rustc_session:: lint:: builtin:: BREAK_WITH_LABEL_AND_LOOP ;
2224use rustc_session:: lint:: BuiltinLintDiagnostics ;
@@ -1548,9 +1550,33 @@ impl<'a> Parser<'a> {
15481550 Ok ( self . mk_expr_err ( lo) )
15491551 } else {
15501552 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+
15521557 // 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
15541580 } ?;
15551581
15561582 if !ate_colon && consume_colon {
0 commit comments