@@ -585,7 +585,7 @@ impl<'a> Parser<'a> {
585585 lhs_span : Span ,
586586 expr_kind : fn ( P < Expr > , P < Ty > ) -> ExprKind ,
587587 ) -> PResult < ' a , P < Expr > > {
588- let mk_expr = |this : & mut Self , rhs : P < Ty > | {
588+ let mk_expr = |this : & mut Self , lhs : P < Expr > , rhs : P < Ty > | {
589589 this. mk_expr (
590590 this. mk_expr_sp ( & lhs, lhs_span, rhs. span ) ,
591591 expr_kind ( lhs, rhs) ,
@@ -597,13 +597,49 @@ impl<'a> Parser<'a> {
597597 // LessThan comparison after this cast.
598598 let parser_snapshot_before_type = self . clone ( ) ;
599599 let cast_expr = match self . parse_ty_no_plus ( ) {
600- Ok ( rhs) => mk_expr ( self , rhs) ,
600+ Ok ( rhs) => mk_expr ( self , lhs , rhs) ,
601601 Err ( mut type_err) => {
602602 // Rewind to before attempting to parse the type with generics, to recover
603603 // from situations like `x as usize < y` in which we first tried to parse
604604 // `usize < y` as a type with generic arguments.
605605 let parser_snapshot_after_type = mem:: replace ( self , parser_snapshot_before_type) ;
606606
607+ // Check for typo of `'a: loop { break 'a }` with a missing `'`.
608+ match ( & lhs. kind , & self . token . kind ) {
609+ (
610+ // `foo: `
611+ ExprKind :: Path ( None , ast:: Path { segments, .. } ) ,
612+ TokenKind :: Ident ( kw:: For | kw:: Loop | kw:: While , false ) ,
613+ ) if segments. len ( ) == 1 => {
614+ let snapshot = self . clone ( ) ;
615+ let label = Label {
616+ ident : Ident :: from_str_and_span (
617+ & format ! ( "'{}" , segments[ 0 ] . ident) ,
618+ segments[ 0 ] . ident . span ,
619+ ) ,
620+ } ;
621+ match self . parse_labeled_expr ( label, AttrVec :: new ( ) , false ) {
622+ Ok ( expr) => {
623+ type_err. cancel ( ) ;
624+ self . struct_span_err ( label. ident . span , "malformed loop label" )
625+ . span_suggestion (
626+ label. ident . span ,
627+ "use the correct loop label format" ,
628+ label. ident . to_string ( ) ,
629+ Applicability :: MachineApplicable ,
630+ )
631+ . emit ( ) ;
632+ return Ok ( expr) ;
633+ }
634+ Err ( mut err) => {
635+ err. cancel ( ) ;
636+ * self = snapshot;
637+ }
638+ }
639+ }
640+ _ => { }
641+ }
642+
607643 match self . parse_path ( PathStyle :: Expr ) {
608644 Ok ( path) => {
609645 let ( op_noun, op_verb) = match self . token . kind {
@@ -630,7 +666,8 @@ impl<'a> Parser<'a> {
630666 op_noun,
631667 ) ;
632668 let span_after_type = parser_snapshot_after_type. token . span ;
633- let expr = mk_expr ( self , self . mk_ty ( path. span , TyKind :: Path ( None , path) ) ) ;
669+ let expr =
670+ mk_expr ( self , lhs, self . mk_ty ( path. span , TyKind :: Path ( None , path) ) ) ;
634671
635672 let expr_str = self
636673 . span_to_snippet ( expr. span )
@@ -1067,7 +1104,7 @@ impl<'a> Parser<'a> {
10671104 } else if self . eat_keyword ( kw:: While ) {
10681105 self . parse_while_expr ( None , self . prev_token . span , attrs)
10691106 } else if let Some ( label) = self . eat_label ( ) {
1070- self . parse_labeled_expr ( label, attrs)
1107+ self . parse_labeled_expr ( label, attrs, true )
10711108 } else if self . eat_keyword ( kw:: Loop ) {
10721109 self . parse_loop_expr ( None , self . prev_token . span , attrs)
10731110 } else if self . eat_keyword ( kw:: Continue ) {
@@ -1228,7 +1265,12 @@ impl<'a> Parser<'a> {
12281265 }
12291266
12301267 /// Parse `'label: $expr`. The label is already parsed.
1231- fn parse_labeled_expr ( & mut self , label : Label , attrs : AttrVec ) -> PResult < ' a , P < Expr > > {
1268+ fn parse_labeled_expr (
1269+ & mut self ,
1270+ label : Label ,
1271+ attrs : AttrVec ,
1272+ consume_colon : bool ,
1273+ ) -> PResult < ' a , P < Expr > > {
12321274 let lo = label. ident . span ;
12331275 let label = Some ( label) ;
12341276 let ate_colon = self . eat ( & token:: Colon ) ;
@@ -1247,7 +1289,7 @@ impl<'a> Parser<'a> {
12471289 self . parse_expr ( )
12481290 } ?;
12491291
1250- if !ate_colon {
1292+ if !ate_colon && consume_colon {
12511293 self . error_labeled_expr_must_be_followed_by_colon ( lo, expr. span ) ;
12521294 }
12531295
0 commit comments