From a08dedf76bdde8340b7fca0dcc01420338cb7afd Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Mon, 30 Dec 2024 19:43:23 -0800 Subject: [PATCH] Fix ranges bailout edge cases with assignment --- src/expr.rs | 26 ++++++++++++++++++++++++-- tests/test_expr.rs | 25 ++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index cde51cdebb..49f050e2a6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1324,6 +1324,11 @@ pub(crate) mod parsing { if precedence < base { break; } + if precedence == Precedence::Assign { + if let Expr::Range(_) = lhs { + break; + } + } if precedence == Precedence::Compare { if let Expr::Binary(lhs) = &lhs { if Precedence::of_binop(&lhs.op) == Precedence::Compare { @@ -1339,7 +1344,13 @@ pub(crate) mod parsing { op, right, }); - } else if Precedence::Assign >= base && input.peek(Token![=]) && !input.peek(Token![=>]) + } else if Precedence::Assign >= base + && input.peek(Token![=]) + && !input.peek(Token![=>]) + && match lhs { + Expr::Range(_) => false, + _ => true, + } { let eq_token: Token![=] = input.parse()?; let right = parse_binop_rhs(input, allow_struct, Precedence::Assign)?; @@ -2874,7 +2885,18 @@ pub(crate) mod parsing { || input.peek(Token![.]) && !input.peek(Token![..]) || input.peek(Token![?]) || input.peek(Token![=>]) - || !allow_struct.0 && input.peek(token::Brace)) + || !allow_struct.0 && input.peek(token::Brace) + || input.peek(Token![=]) && !input.peek(Token![==]) + || input.peek(Token![+=]) + || input.peek(Token![-=]) + || input.peek(Token![*=]) + || input.peek(Token![/=]) + || input.peek(Token![%=]) + || input.peek(Token![^=]) + || input.peek(Token![&=]) + || input.peek(Token![|=]) + || input.peek(Token![<<=]) + || input.peek(Token![>>=])) { Ok(None) } else { diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 5783c778b2..1bcc0941fa 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -408,7 +408,7 @@ fn test_range_precedence() { } #[test] -fn test_ranges_dots_bailout() { +fn test_ranges_bailout() { syn::parse_str::(".. ?").unwrap_err(); syn::parse_str::(".. .field").unwrap_err(); @@ -476,6 +476,29 @@ fn test_ranges_dots_bailout() { member: Member::Named("field"), } "#); + + snapshot!("return .. = ()" as Expr, @r" + Expr::Assign { + left: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + right: Expr::Tuple, + } + "); + + snapshot!("return .. += ()" as Expr, @r" + Expr::Binary { + left: Expr::Return { + expr: Some(Expr::Range { + limits: RangeLimits::HalfOpen, + }), + }, + op: BinOp::AddAssign, + right: Expr::Tuple, + } + "); } #[test]