@@ -3612,20 +3612,36 @@ impl<'a> Parser<'a> {
36123612 self . token . is_keyword ( kw:: Async ) && self . is_gen_block ( kw:: Gen , 1 )
36133613 }
36143614
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+
36153621 fn maybe_parse_struct_expr (
36163622 & mut self ,
36173623 qself : & Option < Box < ast:: QSelf > > ,
36183624 path : & ast:: Path ,
36193625 ) -> Option < PResult < ' a , Box < Expr > > > {
36203626 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 ) => {
36263642 // We have something like `match foo { bar,` or `match foo { bar:`, which means the
36273643 // 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.
36293645 let snapshot = self . create_snapshot_for_diagnostic ( ) ;
36303646 if let Err ( err) = self . expect ( exp ! ( OpenBrace ) ) {
36313647 return Some ( Err ( err) ) ;
@@ -3651,15 +3667,6 @@ impl<'a> Parser<'a> {
36513667 }
36523668 }
36533669 }
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 ,
36633670 }
36643671 }
36653672
0 commit comments