@@ -1353,9 +1353,6 @@ impl<'a> Parser<'a> {
13531353 err. span_label ( sp, "while parsing this `loop` expression" ) ;
13541354 err
13551355 } )
1356- } else if self . eat_keyword ( kw:: Continue ) {
1357- let kind = ExprKind :: Continue ( self . eat_label ( ) ) ;
1358- Ok ( self . mk_expr ( lo. to ( self . prev_token . span ) , kind) )
13591356 } else if self . eat_keyword ( kw:: Match ) {
13601357 let match_sp = self . prev_token . span ;
13611358 self . parse_match_expr ( ) . map_err ( |mut err| {
@@ -1379,6 +1376,8 @@ impl<'a> Parser<'a> {
13791376 self . parse_try_block ( lo)
13801377 } else if self . eat_keyword ( kw:: Return ) {
13811378 self . parse_return_expr ( )
1379+ } else if self . eat_keyword ( kw:: Continue ) {
1380+ self . parse_continue_expr ( lo)
13821381 } else if self . eat_keyword ( kw:: Break ) {
13831382 self . parse_break_expr ( )
13841383 } else if self . eat_keyword ( kw:: Yield ) {
@@ -1715,10 +1714,10 @@ impl<'a> Parser<'a> {
17151714 fn parse_break_expr ( & mut self ) -> PResult < ' a , P < Expr > > {
17161715 let lo = self . prev_token . span ;
17171716 let mut label = self . eat_label ( ) ;
1718- let kind = if label . is_some ( ) && self . token == token:: Colon {
1717+ let kind = if self . token == token:: Colon && let Some ( label ) = label . take ( ) {
17191718 // The value expression can be a labeled loop, see issue #86948, e.g.:
17201719 // `loop { break 'label: loop { break 'label 42; }; }`
1721- let lexpr = self . parse_labeled_expr ( label. take ( ) . unwrap ( ) , true ) ?;
1720+ let lexpr = self . parse_labeled_expr ( label, true ) ?;
17221721 self . sess . emit_err ( LabeledLoopInBreak {
17231722 span : lexpr. span ,
17241723 sub : WrapExpressionInParentheses {
@@ -1730,8 +1729,8 @@ impl<'a> Parser<'a> {
17301729 } else if self . token != token:: OpenDelim ( Delimiter :: Brace )
17311730 || !self . restrictions . contains ( Restrictions :: NO_STRUCT_LITERAL )
17321731 {
1733- let expr = self . parse_expr_opt ( ) ?;
1734- if let Some ( expr) = & expr {
1732+ let mut expr = self . parse_expr_opt ( ) ?;
1733+ if let Some ( expr) = & mut expr {
17351734 if label. is_some ( )
17361735 && matches ! (
17371736 expr. kind,
@@ -1749,7 +1748,19 @@ impl<'a> Parser<'a> {
17491748 BuiltinLintDiagnostics :: BreakWithLabelAndLoop ( expr. span ) ,
17501749 ) ;
17511750 }
1751+
1752+ // Recover `break label aaaaa`
1753+ if self . may_recover ( )
1754+ && let ExprKind :: Path ( None , p) = & expr. kind
1755+ && let [ segment] = & * p. segments
1756+ && let & ast:: PathSegment { ident, args : None , .. } = segment
1757+ && let Some ( next) = self . parse_expr_opt ( ) ?
1758+ {
1759+ label = Some ( self . recover_ident_into_label ( ident) ) ;
1760+ * expr = next;
1761+ }
17521762 }
1763+
17531764 expr
17541765 } else {
17551766 None
@@ -1758,6 +1769,23 @@ impl<'a> Parser<'a> {
17581769 self . maybe_recover_from_bad_qpath ( expr)
17591770 }
17601771
1772+ /// Parse `"continue" label?`.
1773+ fn parse_continue_expr ( & mut self , lo : Span ) -> PResult < ' a , P < Expr > > {
1774+ let mut label = self . eat_label ( ) ;
1775+
1776+ // Recover `continue label` -> `continue 'label`
1777+ if self . may_recover ( )
1778+ && label. is_none ( )
1779+ && let Some ( ( ident, _) ) = self . token . ident ( )
1780+ {
1781+ self . bump ( ) ;
1782+ label = Some ( self . recover_ident_into_label ( ident) ) ;
1783+ }
1784+
1785+ let kind = ExprKind :: Continue ( label) ;
1786+ Ok ( self . mk_expr ( lo. to ( self . prev_token . span ) , kind) )
1787+ }
1788+
17611789 /// Parse `"yield" expr?`.
17621790 fn parse_yield_expr ( & mut self ) -> PResult < ' a , P < Expr > > {
17631791 let lo = self . prev_token . span ;
@@ -3046,6 +3074,25 @@ impl<'a> Parser<'a> {
30463074 false
30473075 }
30483076
3077+ /// Converts an ident into 'label and emits an "expected a label, found an identifier" error.
3078+ fn recover_ident_into_label ( & mut self , ident : Ident ) -> Label {
3079+ // Convert `label` -> `'label`,
3080+ // so that nameres doesn't complain about non-existing label
3081+ let label = format ! ( "'{}" , ident. name) ;
3082+ let ident = Ident { name : Symbol :: intern ( & label) , span : ident. span } ;
3083+
3084+ self . struct_span_err ( ident. span , "expected a label, found an identifier" )
3085+ . span_suggestion (
3086+ ident. span ,
3087+ "labels start with a tick" ,
3088+ label,
3089+ Applicability :: MachineApplicable ,
3090+ )
3091+ . emit ( ) ;
3092+
3093+ Label { ident }
3094+ }
3095+
30493096 /// Parses `ident (COLON expr)?`.
30503097 fn parse_expr_field ( & mut self ) -> PResult < ' a , ExprField > {
30513098 let attrs = self . parse_outer_attributes ( ) ?;
0 commit comments