@@ -957,6 +957,8 @@ pub(crate) fn requires_terminator(expr: &Expr) -> bool {
957
957
#[ cfg( feature = "parsing" ) ]
958
958
pub ( crate ) mod parsing {
959
959
use super :: * ;
960
+ #[ cfg( feature = "full" ) ]
961
+ use crate :: ext:: IdentExt ;
960
962
use crate :: parse:: discouraged:: Speculative ;
961
963
#[ cfg( feature = "full" ) ]
962
964
use crate :: parse:: ParseBuffer ;
@@ -1155,6 +1157,25 @@ pub(crate) mod parsing {
1155
1157
}
1156
1158
}
1157
1159
1160
+ #[ cfg( feature = "full" ) ]
1161
+ fn can_begin_expr ( input : ParseStream ) -> bool {
1162
+ input. peek ( Ident :: peek_any) // value name or keyword
1163
+ || input. peek ( token:: Paren ) // tuple
1164
+ || input. peek ( token:: Bracket ) // array
1165
+ || input. peek ( token:: Brace ) // block
1166
+ || input. peek ( Lit ) // literal
1167
+ || input. peek ( Token ! [ !] ) && !input. peek ( Token ! [ !=] ) // operator not
1168
+ || input. peek ( Token ! [ -] ) && !input. peek ( Token ! [ -=] ) && !input. peek ( Token ! [ ->] ) // unary minus
1169
+ || input. peek ( Token ! [ * ] ) && !input. peek ( Token ! [ *=] ) // dereference
1170
+ || input. peek ( Token ! [ |] ) && !input. peek ( Token ! [ |=] ) // closure
1171
+ || input. peek ( Token ! [ & ] ) && !input. peek ( Token ! [ &=] ) // reference
1172
+ || input. peek ( Token ! [ ..] ) // range notation
1173
+ || input. peek ( Token ! [ <] ) && !input. peek ( Token ! [ <=] ) && !input. peek ( Token ! [ <<=] ) // associated path
1174
+ || input. peek ( Token ! [ :: ] ) // global path
1175
+ || input. peek ( Lifetime ) // labeled loop
1176
+ || input. peek ( Token ! [ #] ) // expression attributes
1177
+ }
1178
+
1158
1179
#[ cfg( feature = "full" ) ]
1159
1180
fn parse_expr (
1160
1181
input : ParseStream ,
@@ -2247,7 +2268,7 @@ pub(crate) mod parsing {
2247
2268
attrs : Vec :: new ( ) ,
2248
2269
yield_token : input. parse ( ) ?,
2249
2270
expr : {
2250
- if !input . is_empty ( ) && ! input. peek ( Token ! [ , ] ) && !input . peek ( Token ! [ ; ] ) {
2271
+ if can_begin_expr ( input) {
2251
2272
Some ( input. parse ( ) ?)
2252
2273
} else {
2253
2274
None
@@ -2447,15 +2468,11 @@ pub(crate) mod parsing {
2447
2468
break_token : input. parse ( ) ?,
2448
2469
label : input. parse ( ) ?,
2449
2470
expr : {
2450
- if input. is_empty ( )
2451
- || input. peek ( Token ! [ , ] )
2452
- || input. peek ( Token ! [ ; ] )
2453
- || !allow_struct. 0 && input. peek ( token:: Brace )
2454
- {
2455
- None
2456
- } else {
2471
+ if can_begin_expr ( input) && ( allow_struct. 0 || !input. peek ( token:: Brace ) ) {
2457
2472
let expr = ambiguous_expr ( input, allow_struct) ?;
2458
2473
Some ( Box :: new ( expr) )
2474
+ } else {
2475
+ None
2459
2476
}
2460
2477
} ,
2461
2478
} )
@@ -2467,16 +2484,16 @@ pub(crate) mod parsing {
2467
2484
attrs : Vec :: new ( ) ,
2468
2485
return_token : input. parse ( ) ?,
2469
2486
expr : {
2470
- if input. is_empty ( ) || input. peek ( Token ! [ , ] ) || input. peek ( Token ! [ ; ] ) {
2471
- None
2472
- } else {
2487
+ if can_begin_expr ( input) {
2473
2488
// NOTE: return is greedy and eats blocks after it even when in a
2474
2489
// position where structs are not allowed, such as in if statement
2475
2490
// conditions. For example:
2476
2491
//
2477
2492
// if return { println!("A") } {} // Prints "A"
2478
2493
let expr = ambiguous_expr ( input, allow_struct) ?;
2479
2494
Some ( Box :: new ( expr) )
2495
+ } else {
2496
+ None
2480
2497
}
2481
2498
} ,
2482
2499
} )
0 commit comments