@@ -585,7 +585,7 @@ impl<'a> Parser<'a> {
585
585
lhs_span : Span ,
586
586
expr_kind : fn ( P < Expr > , P < Ty > ) -> ExprKind ,
587
587
) -> 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 > | {
589
589
this. mk_expr (
590
590
this. mk_expr_sp ( & lhs, lhs_span, rhs. span ) ,
591
591
expr_kind ( lhs, rhs) ,
@@ -597,13 +597,49 @@ impl<'a> Parser<'a> {
597
597
// LessThan comparison after this cast.
598
598
let parser_snapshot_before_type = self . clone ( ) ;
599
599
let cast_expr = match self . parse_ty_no_plus ( ) {
600
- Ok ( rhs) => mk_expr ( self , rhs) ,
600
+ Ok ( rhs) => mk_expr ( self , lhs , rhs) ,
601
601
Err ( mut type_err) => {
602
602
// Rewind to before attempting to parse the type with generics, to recover
603
603
// from situations like `x as usize < y` in which we first tried to parse
604
604
// `usize < y` as a type with generic arguments.
605
605
let parser_snapshot_after_type = mem:: replace ( self , parser_snapshot_before_type) ;
606
606
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
+
607
643
match self . parse_path ( PathStyle :: Expr ) {
608
644
Ok ( path) => {
609
645
let ( op_noun, op_verb) = match self . token . kind {
@@ -630,7 +666,8 @@ impl<'a> Parser<'a> {
630
666
op_noun,
631
667
) ;
632
668
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) ) ) ;
634
671
635
672
let expr_str = self
636
673
. span_to_snippet ( expr. span )
@@ -1067,7 +1104,7 @@ impl<'a> Parser<'a> {
1067
1104
} else if self . eat_keyword ( kw:: While ) {
1068
1105
self . parse_while_expr ( None , self . prev_token . span , attrs)
1069
1106
} else if let Some ( label) = self . eat_label ( ) {
1070
- self . parse_labeled_expr ( label, attrs)
1107
+ self . parse_labeled_expr ( label, attrs, true )
1071
1108
} else if self . eat_keyword ( kw:: Loop ) {
1072
1109
self . parse_loop_expr ( None , self . prev_token . span , attrs)
1073
1110
} else if self . eat_keyword ( kw:: Continue ) {
@@ -1228,7 +1265,12 @@ impl<'a> Parser<'a> {
1228
1265
}
1229
1266
1230
1267
/// 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 > > {
1232
1274
let lo = label. ident . span ;
1233
1275
let label = Some ( label) ;
1234
1276
let ate_colon = self . eat ( & token:: Colon ) ;
@@ -1247,7 +1289,7 @@ impl<'a> Parser<'a> {
1247
1289
self . parse_expr ( )
1248
1290
} ?;
1249
1291
1250
- if !ate_colon {
1292
+ if !ate_colon && consume_colon {
1251
1293
self . error_labeled_expr_must_be_followed_by_colon ( lo, expr. span ) ;
1252
1294
}
1253
1295
0 commit comments