@@ -1468,6 +1468,9 @@ impl<'a> Parser<'a> {
14681468 } else if this. check ( exp ! ( OpenParen ) ) {
14691469 this. parse_expr_tuple_parens ( restrictions)
14701470 } else if this. check ( exp ! ( OpenBrace ) ) {
1471+ if let Some ( expr) = this. maybe_recover_bad_struct_literal_path ( false ) ? {
1472+ return Ok ( expr) ;
1473+ }
14711474 this. parse_expr_block ( None , lo, BlockCheckMode :: Default )
14721475 } else if this. check ( exp ! ( Or ) ) || this. check ( exp ! ( OrOr ) ) {
14731476 this. parse_expr_closure ( ) . map_err ( |mut err| {
@@ -1542,6 +1545,9 @@ impl<'a> Parser<'a> {
15421545 } else if this. check_keyword ( exp ! ( Let ) ) {
15431546 this. parse_expr_let ( restrictions)
15441547 } else if this. eat_keyword ( exp ! ( Underscore ) ) {
1548+ if let Some ( expr) = this. maybe_recover_bad_struct_literal_path ( true ) ? {
1549+ return Ok ( expr) ;
1550+ }
15451551 Ok ( this. mk_expr ( this. prev_token . span , ExprKind :: Underscore ) )
15461552 } else if this. token_uninterpolated_span ( ) . at_least_rust_2018 ( ) {
15471553 // `Span::at_least_rust_2018()` is somewhat expensive; don't get it repeatedly.
@@ -3698,6 +3704,45 @@ impl<'a> Parser<'a> {
36983704 }
36993705 }
37003706
3707+ fn maybe_recover_bad_struct_literal_path (
3708+ & mut self ,
3709+ is_underscore_entry_point : bool ,
3710+ ) -> PResult < ' a , Option < Box < Expr > > > {
3711+ if self . may_recover ( )
3712+ && self . check_noexpect ( & token:: OpenBrace )
3713+ && ( !self . restrictions . contains ( Restrictions :: NO_STRUCT_LITERAL )
3714+ && self . is_likely_struct_lit ( ) )
3715+ {
3716+ let span = if is_underscore_entry_point {
3717+ self . prev_token . span
3718+ } else {
3719+ self . token . span . shrink_to_lo ( )
3720+ } ;
3721+
3722+ self . bump ( ) ; // {
3723+ let expr = self . parse_expr_struct (
3724+ None ,
3725+ Path :: from_ident ( Ident :: new ( kw:: Underscore , span) ) ,
3726+ false ,
3727+ ) ?;
3728+
3729+ let guar = if is_underscore_entry_point {
3730+ self . dcx ( ) . create_err ( errors:: StructLiteralPlaceholderPath { span } ) . emit ( )
3731+ } else {
3732+ self . dcx ( )
3733+ . create_err ( errors:: StructLiteralWithoutPathLate {
3734+ span : expr. span ,
3735+ suggestion_span : expr. span . shrink_to_lo ( ) ,
3736+ } )
3737+ . emit ( )
3738+ } ;
3739+
3740+ Ok ( Some ( self . mk_expr_err ( expr. span , guar) ) )
3741+ } else {
3742+ Ok ( None )
3743+ }
3744+ }
3745+
37013746 pub ( super ) fn parse_struct_fields (
37023747 & mut self ,
37033748 pth : ast:: Path ,
0 commit comments