@@ -882,6 +882,12 @@ impl<'a> Parser<'a> {
882
882
}
883
883
}
884
884
885
+ fn look_ahead_type_ascription_as_field ( & mut self ) -> bool {
886
+ self . look_ahead ( 1 , |t| t. is_ident ( ) )
887
+ && self . look_ahead ( 2 , |t| t == & token:: Colon )
888
+ && self . look_ahead ( 3 , |t| t. can_begin_expr ( ) )
889
+ }
890
+
885
891
fn parse_dot_suffix_expr ( & mut self , lo : Span , base : P < Expr > ) -> PResult < ' a , P < Expr > > {
886
892
match self . token . uninterpolate ( ) . kind {
887
893
token:: Ident ( ..) => self . parse_dot_suffix ( base, lo) ,
@@ -1031,9 +1037,56 @@ impl<'a> Parser<'a> {
1031
1037
1032
1038
/// Parse a function call expression, `expr(...)`.
1033
1039
fn parse_fn_call_expr ( & mut self , lo : Span , fun : P < Expr > ) -> P < Expr > {
1034
- let seq = self . parse_paren_expr_seq ( ) . map ( |args| {
1040
+ let snapshot = if self . token . kind == token:: OpenDelim ( token:: Paren )
1041
+ && self . look_ahead_type_ascription_as_field ( )
1042
+ {
1043
+ Some ( ( self . clone ( ) , fun. kind . clone ( ) ) )
1044
+ } else {
1045
+ None
1046
+ } ;
1047
+ let open_paren = self . token . span ;
1048
+
1049
+ let mut seq = self . parse_paren_expr_seq ( ) . map ( |args| {
1035
1050
self . mk_expr ( lo. to ( self . prev_token . span ) , self . mk_call ( fun, args) , AttrVec :: new ( ) )
1036
1051
} ) ;
1052
+ match ( seq. as_mut ( ) , snapshot) {
1053
+ ( Err ( ref mut err) , Some ( ( mut snapshot, ExprKind :: Path ( None , path) ) ) ) => {
1054
+ let name = pprust:: path_to_string ( & path) ;
1055
+ snapshot. bump ( ) ; // `(`
1056
+ match snapshot. parse_struct_fields ( path. clone ( ) , false , token:: Paren ) {
1057
+ Ok ( ( fields, ..) ) if snapshot. eat ( & token:: CloseDelim ( token:: Paren ) ) => {
1058
+ // We have are certain we have `Enum::Foo(a: 3, b: 4)`, suggest
1059
+ // `Enum::Foo { a: 3, b: 4 }` or `Enum::Foo(3, 4)`.
1060
+ * self = snapshot;
1061
+ let close_paren = self . prev_token . span ;
1062
+ let span = lo. to ( self . prev_token . span ) ;
1063
+ err. cancel ( ) ;
1064
+ self . struct_span_err (
1065
+ span,
1066
+ "invalid `struct` delimiters or `fn` call arguments" ,
1067
+ )
1068
+ . multipart_suggestion (
1069
+ & format ! ( "if `{}` is a struct, use braces as delimiters" , name) ,
1070
+ vec ! [ ( open_paren, " { " . to_string( ) ) , ( close_paren, " }" . to_string( ) ) ] ,
1071
+ Applicability :: MaybeIncorrect ,
1072
+ )
1073
+ . multipart_suggestion (
1074
+ & format ! ( "if `{}` is a function, use the arguments directly" , name) ,
1075
+ fields
1076
+ . into_iter ( )
1077
+ . map ( |field| ( field. span . until ( field. expr . span ) , String :: new ( ) ) )
1078
+ . collect ( ) ,
1079
+ Applicability :: MaybeIncorrect ,
1080
+ )
1081
+ . emit ( ) ;
1082
+ return self . mk_expr_err ( span) ;
1083
+ }
1084
+ Ok ( _) => { }
1085
+ Err ( mut err) => err. emit ( ) ,
1086
+ }
1087
+ }
1088
+ _ => { }
1089
+ }
1037
1090
self . recover_seq_parse_error ( token:: Paren , lo, seq)
1038
1091
}
1039
1092
@@ -2332,14 +2385,12 @@ impl<'a> Parser<'a> {
2332
2385
. emit ( ) ;
2333
2386
}
2334
2387
2335
- /// Precondition: already parsed the '{'.
2336
- pub ( super ) fn parse_struct_expr (
2388
+ pub ( super ) fn parse_struct_fields (
2337
2389
& mut self ,
2338
- qself : Option < ast:: QSelf > ,
2339
2390
pth : ast:: Path ,
2340
- attrs : AttrVec ,
2341
2391
recover : bool ,
2342
- ) -> PResult < ' a , P < Expr > > {
2392
+ close_delim : token:: DelimToken ,
2393
+ ) -> PResult < ' a , ( Vec < ExprField > , ast:: StructRest , bool ) > {
2343
2394
let mut fields = Vec :: new ( ) ;
2344
2395
let mut base = ast:: StructRest :: None ;
2345
2396
let mut recover_async = false ;
@@ -2351,11 +2402,11 @@ impl<'a> Parser<'a> {
2351
2402
e. note ( "for more on editions, read https://doc.rust-lang.org/edition-guide" ) ;
2352
2403
} ;
2353
2404
2354
- while self . token != token:: CloseDelim ( token :: Brace ) {
2405
+ while self . token != token:: CloseDelim ( close_delim ) {
2355
2406
if self . eat ( & token:: DotDot ) {
2356
2407
let exp_span = self . prev_token . span ;
2357
2408
// We permit `.. }` on the left-hand side of a destructuring assignment.
2358
- if self . check ( & token:: CloseDelim ( token :: Brace ) ) {
2409
+ if self . check ( & token:: CloseDelim ( close_delim ) ) {
2359
2410
self . sess . gated_spans . gate ( sym:: destructuring_assignment, self . prev_token . span ) ;
2360
2411
base = ast:: StructRest :: Rest ( self . prev_token . span . shrink_to_hi ( ) ) ;
2361
2412
break ;
@@ -2396,7 +2447,7 @@ impl<'a> Parser<'a> {
2396
2447
}
2397
2448
} ;
2398
2449
2399
- match self . expect_one_of ( & [ token:: Comma ] , & [ token:: CloseDelim ( token :: Brace ) ] ) {
2450
+ match self . expect_one_of ( & [ token:: Comma ] , & [ token:: CloseDelim ( close_delim ) ] ) {
2400
2451
Ok ( _) => {
2401
2452
if let Some ( f) = parsed_field. or ( recovery_field) {
2402
2453
// Only include the field if there's no parse error for the field name.
@@ -2427,8 +2478,21 @@ impl<'a> Parser<'a> {
2427
2478
}
2428
2479
}
2429
2480
}
2481
+ Ok ( ( fields, base, recover_async) )
2482
+ }
2430
2483
2431
- let span = pth. span . to ( self . token . span ) ;
2484
+ /// Precondition: already parsed the '{'.
2485
+ pub ( super ) fn parse_struct_expr (
2486
+ & mut self ,
2487
+ qself : Option < ast:: QSelf > ,
2488
+ pth : ast:: Path ,
2489
+ attrs : AttrVec ,
2490
+ recover : bool ,
2491
+ ) -> PResult < ' a , P < Expr > > {
2492
+ let lo = pth. span ;
2493
+ let ( fields, base, recover_async) =
2494
+ self . parse_struct_fields ( pth. clone ( ) , recover, token:: Brace ) ?;
2495
+ let span = lo. to ( self . token . span ) ;
2432
2496
self . expect ( & token:: CloseDelim ( token:: Brace ) ) ?;
2433
2497
let expr = if recover_async {
2434
2498
ExprKind :: Err
0 commit comments