@@ -3612,20 +3612,36 @@ impl<'a> Parser<'a> {
3612
3612
self . token . is_keyword ( kw:: Async ) && self . is_gen_block ( kw:: Gen , 1 )
3613
3613
}
3614
3614
3615
+ fn is_likely_struct_lit ( & self ) -> bool {
3616
+ // `{ ident, ` and `{ ident: ` cannot start a block.
3617
+ self . look_ahead ( 1 , |t| t. is_ident ( ) )
3618
+ && self . look_ahead ( 2 , |t| t == & token:: Comma || t == & token:: Colon )
3619
+ }
3620
+
3615
3621
fn maybe_parse_struct_expr (
3616
3622
& mut self ,
3617
3623
qself : & Option < Box < ast:: QSelf > > ,
3618
3624
path : & ast:: Path ,
3619
3625
) -> Option < PResult < ' a , Box < Expr > > > {
3620
3626
let struct_allowed = !self . restrictions . contains ( Restrictions :: NO_STRUCT_LITERAL ) ;
3621
- let is_ident = self . look_ahead ( 1 , |t| t. is_ident ( ) ) ;
3622
- let is_comma = self . look_ahead ( 2 , |t| t == & token:: Comma ) ;
3623
- let is_colon = self . look_ahead ( 2 , |t| t == & token:: Colon ) ;
3624
- match ( struct_allowed, is_ident, is_comma, is_colon) {
3625
- ( false , true , true , _) | ( false , true , _, true ) => {
3627
+ match ( struct_allowed, self . is_likely_struct_lit ( ) ) {
3628
+ // A struct literal isn't expected and one is pretty much assured not to be present. The
3629
+ // only situation that isn't detected is when a struct with a single field was attempted
3630
+ // in a place where a struct literal wasn't expected, but regular parser errors apply.
3631
+ // Happy path.
3632
+ ( false , false ) => None ,
3633
+ ( true , _) => {
3634
+ // A struct is accepted here, try to parse it and rely on `parse_expr_struct` for
3635
+ // any kind of recovery. Happy path.
3636
+ if let Err ( err) = self . expect ( exp ! ( OpenBrace ) ) {
3637
+ return Some ( Err ( err) ) ;
3638
+ }
3639
+ Some ( self . parse_expr_struct ( qself. clone ( ) , path. clone ( ) , true ) )
3640
+ }
3641
+ ( false , true ) => {
3626
3642
// We have something like `match foo { bar,` or `match foo { bar:`, which means the
3627
3643
// user might have meant to write a struct literal as part of the `match`
3628
- // discriminant.
3644
+ // discriminant. This is done purely for error recovery.
3629
3645
let snapshot = self . create_snapshot_for_diagnostic ( ) ;
3630
3646
if let Err ( err) = self . expect ( exp ! ( OpenBrace ) ) {
3631
3647
return Some ( Err ( err) ) ;
@@ -3651,15 +3667,6 @@ impl<'a> Parser<'a> {
3651
3667
}
3652
3668
}
3653
3669
}
3654
- ( true , _, _, _) => {
3655
- // A struct is accepted here, try to parse it and rely on `parse_expr_struct` for
3656
- // any kind of recovery.
3657
- if let Err ( err) = self . expect ( exp ! ( OpenBrace ) ) {
3658
- return Some ( Err ( err) ) ;
3659
- }
3660
- Some ( self . parse_expr_struct ( qself. clone ( ) , path. clone ( ) , true ) )
3661
- }
3662
- ( false , _, _, _) => None ,
3663
3670
}
3664
3671
}
3665
3672
0 commit comments