@@ -1391,8 +1391,6 @@ impl<'a> Parser<'a> {
1391
1391
} else if self . is_do_yeet ( ) {
1392
1392
self . parse_yeet_expr ( attrs)
1393
1393
} else if self . check_keyword ( kw:: Let ) {
1394
- self . manage_let_chains_context ( ) ;
1395
- self . bump ( ) ;
1396
1394
self . parse_let_expr ( attrs)
1397
1395
} else if self . eat_keyword ( kw:: Underscore ) {
1398
1396
Ok ( self . mk_expr ( self . prev_token . span , ExprKind :: Underscore , attrs) )
@@ -2342,32 +2340,24 @@ impl<'a> Parser<'a> {
2342
2340
2343
2341
/// Parses the condition of a `if` or `while` expression.
2344
2342
fn parse_cond_expr ( & mut self ) -> PResult < ' a , P < Expr > > {
2345
- self . with_let_management ( true , |local_self| {
2346
- local_self. parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL , None )
2347
- } )
2343
+ self . parse_expr_res ( Restrictions :: NO_STRUCT_LITERAL | Restrictions :: ALLOW_LET , None )
2348
2344
}
2349
2345
2350
- // Checks if `let` is in an invalid position like `let x = let y = 1;` or
2351
- // if the current `let` is in a let_chains context but nested in another
2352
- // expression like `if let Some(_) = _opt && [1, 2, 3][let _ = ()] = 1`.
2353
- //
2354
- // This method expects that the current token is `let`.
2355
- fn manage_let_chains_context ( & mut self ) {
2356
- debug_assert ! ( matches!( self . token. kind, TokenKind :: Ident ( kw:: Let , _) ) ) ;
2357
- let is_in_a_let_chains_context_but_nested_in_other_expr = self . let_expr_allowed
2358
- && !matches ! (
2359
- self . prev_token. kind,
2360
- TokenKind :: AndAnd | TokenKind :: Ident ( kw:: If , _) | TokenKind :: Ident ( kw:: While , _)
2361
- ) ;
2362
- if !self . let_expr_allowed || is_in_a_let_chains_context_but_nested_in_other_expr {
2346
+ /// Parses a `let $pat = $expr` pseudo-expression.
2347
+ fn parse_let_expr ( & mut self , attrs : AttrVec ) -> PResult < ' a , P < Expr > > {
2348
+ // This is a *approximate* heuristic that detects if `let` chains are
2349
+ // being parsed in the right position. It's approximate because it
2350
+ // doesn't deny all invalid `let` expressions, just completely wrong usages.
2351
+ let not_in_chain = !matches ! (
2352
+ self . prev_token. kind,
2353
+ TokenKind :: AndAnd | TokenKind :: Ident ( kw:: If , _) | TokenKind :: Ident ( kw:: While , _)
2354
+ ) ;
2355
+ if !self . restrictions . contains ( Restrictions :: ALLOW_LET ) || not_in_chain {
2363
2356
self . struct_span_err ( self . token . span , "expected expression, found `let` statement" )
2364
2357
. emit ( ) ;
2365
2358
}
2366
- }
2367
2359
2368
- /// Parses a `let $pat = $expr` pseudo-expression.
2369
- /// The `let` token has already been eaten.
2370
- fn parse_let_expr ( & mut self , attrs : AttrVec ) -> PResult < ' a , P < Expr > > {
2360
+ self . bump ( ) ; // Eat `let` token
2371
2361
let lo = self . prev_token . span ;
2372
2362
let pat = self . parse_pat_allow_top_alt (
2373
2363
None ,
@@ -2687,7 +2677,9 @@ impl<'a> Parser<'a> {
2687
2677
// `&&` tokens.
2688
2678
fn check_let_expr ( expr : & Expr ) -> bool {
2689
2679
match expr. kind {
2690
- ExprKind :: Binary ( _, ref lhs, ref rhs) => check_let_expr ( lhs) || check_let_expr ( rhs) ,
2680
+ ExprKind :: Binary ( BinOp { node : BinOpKind :: And , .. } , ref lhs, ref rhs) => {
2681
+ check_let_expr ( lhs) || check_let_expr ( rhs)
2682
+ }
2691
2683
ExprKind :: Let ( ..) => true ,
2692
2684
_ => false ,
2693
2685
}
@@ -2703,9 +2695,8 @@ impl<'a> Parser<'a> {
2703
2695
) ?;
2704
2696
let guard = if this. eat_keyword ( kw:: If ) {
2705
2697
let if_span = this. prev_token . span ;
2706
- let cond = this. with_let_management ( true , |local_this| local_this. parse_expr ( ) ) ?;
2707
- let has_let_expr = check_let_expr ( & cond) ;
2708
- if has_let_expr {
2698
+ let cond = this. parse_expr_res ( Restrictions :: ALLOW_LET , None ) ?;
2699
+ if check_let_expr ( & cond) {
2709
2700
let span = if_span. to ( cond. span ) ;
2710
2701
this. sess . gated_spans . gate ( sym:: if_let_guard, span) ;
2711
2702
}
@@ -3279,17 +3270,4 @@ impl<'a> Parser<'a> {
3279
3270
Ok ( ( res, trailing) )
3280
3271
} )
3281
3272
}
3282
-
3283
- // Calls `f` with the internal `let_expr_allowed` set to `let_expr_allowed` and then
3284
- // sets the internal `let_expr_allowed` back to its original value.
3285
- fn with_let_management < T > (
3286
- & mut self ,
3287
- let_expr_allowed : bool ,
3288
- f : impl FnOnce ( & mut Self ) -> T ,
3289
- ) -> T {
3290
- let last_let_expr_allowed = mem:: replace ( & mut self . let_expr_allowed , let_expr_allowed) ;
3291
- let rslt = f ( self ) ;
3292
- self . let_expr_allowed = last_let_expr_allowed;
3293
- rslt
3294
- }
3295
3273
}
0 commit comments