From 8df4dd0fa4c353a2979bd56c34955e9335bb701d Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Fri, 27 Sep 2024 11:08:43 -0700 Subject: [PATCH] Force cursor to advance in parse_expr calls --- src/expr.rs | 11 ++++++++++- tests/test_expr.rs | 8 ++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/expr.rs b/src/expr.rs index 8216191c2f..409131b4f6 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1390,6 +1390,7 @@ pub(crate) mod parsing { loop { let next = peek_precedence(input); if next > precedence || next == precedence && precedence == Precedence::Assign { + let cursor = input.cursor(); rhs = parse_expr( input, rhs, @@ -1397,10 +1398,18 @@ pub(crate) mod parsing { allow_struct, next, )?; + if cursor == input.cursor() { + // Bespoke grammar restrictions separate from precedence can + // cause parsing to not advance, such as `..a` being + // disallowed in the left-hand side of binary operators, + // even ones that have lower precedence than `..`. + break; + } } else { - return Ok(Box::new(rhs)); + break; } } + Ok(Box::new(rhs)) } fn peek_precedence(input: ParseStream) -> Precedence { diff --git a/tests/test_expr.rs b/tests/test_expr.rs index 399972c424..24d36aeb28 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -646,9 +646,17 @@ fn test_assign_range_precedence() { fn test_chained_comparison() { // https://github.com/dtolnay/syn/issues/1738 let _ = syn::parse_str::("a = a < a <"); + let _ = syn::parse_str::("a = a .. a .."); + let _ = syn::parse_str::("a = a .. a +="); let err = syn::parse_str::("a < a < a").unwrap_err(); assert_eq!("comparison operators cannot be chained", err.to_string()); + + let err = syn::parse_str::("a .. a .. a").unwrap_err(); + assert_eq!("unexpected token", err.to_string()); + + let err = syn::parse_str::("a .. a += a").unwrap_err(); + assert_eq!("unexpected token", err.to_string()); } #[test]