@@ -907,6 +907,12 @@ impl<'a> Parser<'a> {
907907 }
908908 }
909909
910+ fn look_ahead_type_ascription_as_field ( & mut self ) -> bool {
911+ self . look_ahead ( 1 , |t| t. is_ident ( ) )
912+ && self . look_ahead ( 2 , |t| t == & token:: Colon )
913+ && self . look_ahead ( 3 , |t| t. can_begin_expr ( ) )
914+ }
915+
910916 fn parse_dot_suffix_expr ( & mut self , lo : Span , base : P < Expr > ) -> PResult < ' a , P < Expr > > {
911917 match self . token . uninterpolate ( ) . kind {
912918 token:: Ident ( ..) => self . parse_dot_suffix ( base, lo) ,
@@ -1056,12 +1062,76 @@ impl<'a> Parser<'a> {
10561062
10571063 /// Parse a function call expression, `expr(...)`.
10581064 fn parse_fn_call_expr ( & mut self , lo : Span , fun : P < Expr > ) -> P < Expr > {
1059- let seq = self . parse_paren_expr_seq ( ) . map ( |args| {
1065+ let snapshot = if self . token . kind == token:: OpenDelim ( token:: Paren )
1066+ && self . look_ahead_type_ascription_as_field ( )
1067+ {
1068+ Some ( ( self . clone ( ) , fun. kind . clone ( ) ) )
1069+ } else {
1070+ None
1071+ } ;
1072+ let open_paren = self . token . span ;
1073+
1074+ let mut seq = self . parse_paren_expr_seq ( ) . map ( |args| {
10601075 self . mk_expr ( lo. to ( self . prev_token . span ) , self . mk_call ( fun, args) , AttrVec :: new ( ) )
10611076 } ) ;
1077+ if let Some ( expr) =
1078+ self . maybe_recover_struct_lit_bad_delims ( lo, open_paren, & mut seq, snapshot)
1079+ {
1080+ return expr;
1081+ }
10621082 self . recover_seq_parse_error ( token:: Paren , lo, seq)
10631083 }
10641084
1085+ /// If we encounter a parser state that looks like the user has written a `struct` literal with
1086+ /// parentheses instead of braces, recover the parser state and provide suggestions.
1087+ fn maybe_recover_struct_lit_bad_delims (
1088+ & mut self ,
1089+ lo : Span ,
1090+ open_paren : Span ,
1091+ seq : & mut PResult < ' a , P < Expr > > ,
1092+ snapshot : Option < ( Self , ExprKind ) > ,
1093+ ) -> Option < P < Expr > > {
1094+ match ( seq. as_mut ( ) , snapshot) {
1095+ ( Err ( ref mut err) , Some ( ( mut snapshot, ExprKind :: Path ( None , path) ) ) ) => {
1096+ let name = pprust:: path_to_string ( & path) ;
1097+ snapshot. bump ( ) ; // `(`
1098+ match snapshot. parse_struct_fields ( path. clone ( ) , false , token:: Paren ) {
1099+ Ok ( ( fields, ..) ) if snapshot. eat ( & token:: CloseDelim ( token:: Paren ) ) => {
1100+ // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
1101+ // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
1102+ * self = snapshot;
1103+ let close_paren = self . prev_token . span ;
1104+ let span = lo. to ( self . prev_token . span ) ;
1105+ err. cancel ( ) ;
1106+ self . struct_span_err (
1107+ span,
1108+ "invalid `struct` delimiters or `fn` call arguments" ,
1109+ )
1110+ . multipart_suggestion (
1111+ & format ! ( "if `{}` is a struct, use braces as delimiters" , name) ,
1112+ vec ! [ ( open_paren, " { " . to_string( ) ) , ( close_paren, " }" . to_string( ) ) ] ,
1113+ Applicability :: MaybeIncorrect ,
1114+ )
1115+ . multipart_suggestion (
1116+ & format ! ( "if `{}` is a function, use the arguments directly" , name) ,
1117+ fields
1118+ . into_iter ( )
1119+ . map ( |field| ( field. span . until ( field. expr . span ) , String :: new ( ) ) )
1120+ . collect ( ) ,
1121+ Applicability :: MaybeIncorrect ,
1122+ )
1123+ . emit ( ) ;
1124+ return Some ( self . mk_expr_err ( span) ) ;
1125+ }
1126+ Ok ( _) => { }
1127+ Err ( mut err) => err. emit ( ) ,
1128+ }
1129+ }
1130+ _ => { }
1131+ }
1132+ None
1133+ }
1134+
10651135 /// Parse an indexing expression `expr[...]`.
10661136 fn parse_index_expr ( & mut self , lo : Span , base : P < Expr > ) -> PResult < ' a , P < Expr > > {
10671137 self . bump ( ) ; // `[`
@@ -2374,14 +2444,12 @@ impl<'a> Parser<'a> {
23742444 . emit ( ) ;
23752445 }
23762446
2377- /// Precondition: already parsed the '{'.
2378- pub ( super ) fn parse_struct_expr (
2447+ pub ( super ) fn parse_struct_fields (
23792448 & mut self ,
2380- qself : Option < ast:: QSelf > ,
23812449 pth : ast:: Path ,
2382- attrs : AttrVec ,
23832450 recover : bool ,
2384- ) -> PResult < ' a , P < Expr > > {
2451+ close_delim : token:: DelimToken ,
2452+ ) -> PResult < ' a , ( Vec < ExprField > , ast:: StructRest , bool ) > {
23852453 let mut fields = Vec :: new ( ) ;
23862454 let mut base = ast:: StructRest :: None ;
23872455 let mut recover_async = false ;
@@ -2393,11 +2461,11 @@ impl<'a> Parser<'a> {
23932461 e. note ( "for more on editions, read https://doc.rust-lang.org/edition-guide" ) ;
23942462 } ;
23952463
2396- while self . token != token:: CloseDelim ( token :: Brace ) {
2464+ while self . token != token:: CloseDelim ( close_delim ) {
23972465 if self . eat ( & token:: DotDot ) {
23982466 let exp_span = self . prev_token . span ;
23992467 // We permit `.. }` on the left-hand side of a destructuring assignment.
2400- if self . check ( & token:: CloseDelim ( token :: Brace ) ) {
2468+ if self . check ( & token:: CloseDelim ( close_delim ) ) {
24012469 self . sess . gated_spans . gate ( sym:: destructuring_assignment, self . prev_token . span ) ;
24022470 base = ast:: StructRest :: Rest ( self . prev_token . span . shrink_to_hi ( ) ) ;
24032471 break ;
@@ -2438,7 +2506,7 @@ impl<'a> Parser<'a> {
24382506 }
24392507 } ;
24402508
2441- match self . expect_one_of ( & [ token:: Comma ] , & [ token:: CloseDelim ( token :: Brace ) ] ) {
2509+ match self . expect_one_of ( & [ token:: Comma ] , & [ token:: CloseDelim ( close_delim ) ] ) {
24422510 Ok ( _) => {
24432511 if let Some ( f) = parsed_field. or ( recovery_field) {
24442512 // Only include the field if there's no parse error for the field name.
@@ -2469,8 +2537,21 @@ impl<'a> Parser<'a> {
24692537 }
24702538 }
24712539 }
2540+ Ok ( ( fields, base, recover_async) )
2541+ }
24722542
2473- let span = pth. span . to ( self . token . span ) ;
2543+ /// Precondition: already parsed the '{'.
2544+ pub ( super ) fn parse_struct_expr (
2545+ & mut self ,
2546+ qself : Option < ast:: QSelf > ,
2547+ pth : ast:: Path ,
2548+ attrs : AttrVec ,
2549+ recover : bool ,
2550+ ) -> PResult < ' a , P < Expr > > {
2551+ let lo = pth. span ;
2552+ let ( fields, base, recover_async) =
2553+ self . parse_struct_fields ( pth. clone ( ) , recover, token:: Brace ) ?;
2554+ let span = lo. to ( self . token . span ) ;
24742555 self . expect ( & token:: CloseDelim ( token:: Brace ) ) ?;
24752556 let expr = if recover_async {
24762557 ExprKind :: Err
0 commit comments