@@ -1391,8 +1391,6 @@ impl<'a> Parser<'a> {
13911391 } else if self . is_do_yeet ( ) {
13921392 self . parse_yeet_expr ( attrs)
13931393 } else if self . check_keyword ( kw:: Let ) {
1394- self . manage_let_chains_context ( ) ;
1395- self . bump ( ) ;
13961394 self . parse_let_expr ( attrs)
13971395 } else if self . eat_keyword ( kw:: Underscore ) {
13981396 Ok ( self . mk_expr ( self . prev_token . span , ExprKind :: Underscore , attrs) )
@@ -2342,32 +2340,24 @@ impl<'a> Parser<'a> {
23422340
23432341 /// Parses the condition of a `if` or `while` expression.
23442342 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 )
23482344 }
23492345
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 {
23632356 self . struct_span_err ( self . token . span , "expected expression, found `let` statement" )
23642357 . emit ( ) ;
23652358 }
2366- }
23672359
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
23712361 let lo = self . prev_token . span ;
23722362 let pat = self . parse_pat_allow_top_alt (
23732363 None ,
@@ -2687,7 +2677,9 @@ impl<'a> Parser<'a> {
26872677 // `&&` tokens.
26882678 fn check_let_expr ( expr : & Expr ) -> bool {
26892679 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+ }
26912683 ExprKind :: Let ( ..) => true ,
26922684 _ => false ,
26932685 }
@@ -2703,9 +2695,8 @@ impl<'a> Parser<'a> {
27032695 ) ?;
27042696 let guard = if this. eat_keyword ( kw:: If ) {
27052697 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) {
27092700 let span = if_span. to ( cond. span ) ;
27102701 this. sess . gated_spans . gate ( sym:: if_let_guard, span) ;
27112702 }
@@ -3279,17 +3270,4 @@ impl<'a> Parser<'a> {
32793270 Ok ( ( res, trailing) )
32803271 } )
32813272 }
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- }
32953273}
0 commit comments