diff --git a/src/expr.rs b/src/expr.rs index 4183ced263..8b44342eae 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -1400,6 +1400,13 @@ pub(crate) mod parsing { if precedence < base { break; } + if precedence == Precedence::Compare { + if let Expr::Binary(lhs) = &lhs { + if Precedence::of(&lhs.op) == Precedence::Compare { + break; + } + } + } input.advance_to(&ahead); let right = parse_binop_rhs(input, allow_struct, precedence)?; lhs = Expr::Binary(ExprBinary { @@ -1455,6 +1462,13 @@ pub(crate) mod parsing { if precedence < base { break; } + if precedence == Precedence::Compare { + if let Expr::Binary(lhs) = &lhs { + if Precedence::of(&lhs.op) == Precedence::Compare { + break; + } + } + } input.advance_to(&ahead); let right = parse_binop_rhs(input, precedence)?; lhs = Expr::Binary(ExprBinary { diff --git a/tests/test_expr.rs b/tests/test_expr.rs index b908311d49..f39200d3f2 100644 --- a/tests/test_expr.rs +++ b/tests/test_expr.rs @@ -577,6 +577,38 @@ fn test_tuple_comma() { "###); } +#[test] +fn test_binop_associativity() { + // Left to right. + snapshot!("() + () + ()" as Expr, @r###" + Expr::Binary { + left: Expr::Binary { + left: Expr::Tuple, + op: BinOp::Add, + right: Expr::Tuple, + }, + op: BinOp::Add, + right: Expr::Tuple, + } + "###); + + // Right to left. + snapshot!("() += () += ()" as Expr, @r###" + Expr::Binary { + left: Expr::Tuple, + op: BinOp::AddAssign, + right: Expr::Binary { + left: Expr::Tuple, + op: BinOp::AddAssign, + right: Expr::Tuple, + }, + } + "###); + + // Parenthesization is required. + syn::parse_str::("() == () == ()").unwrap_err(); +} + #[test] fn test_assign_range_precedence() { // Range has higher precedence as the right-hand of an assignment, but