From 95028c0ca9ed7c44e58006f32b2d82cc8bd9ef7f Mon Sep 17 00:00:00 2001 From: David Leong <116610336+leongdl@users.noreply.github.com> Date: Mon, 10 Aug 2026 19:53:44 -0700 Subject: [PATCH] refactor(expr): split path/string equality or-pattern MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Split the combined or-pattern in ExprValue::equals into two arms with position-consistent bindings, so the left operand always binds to a. Equality is symmetric, so behavior is unchanged — but the identical swapped-binding pattern in compare() silently reversed path/string ordering (issue #290), and keeping the pattern here invites copying it back into an ordering context. Signed-off-by: David Leong <116610336+leongdl@users.noreply.github.com> --- crates/openjd-expr/src/value.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/crates/openjd-expr/src/value.rs b/crates/openjd-expr/src/value.rs index 99c86464..06c6188f 100644 --- a/crates/openjd-expr/src/value.rs +++ b/crates/openjd-expr/src/value.rs @@ -1253,8 +1253,13 @@ impl ExprValue { (Self::Float(a), Self::Int(b)) => int_float_eq(*b, a.value), (Self::String(a), Self::String(b)) => a == b, (Self::Path { value: a, .. }, Self::Path { value: b, .. }) => a == b, - (Self::String(a), Self::Path { value: b, .. }) - | (Self::Path { value: b, .. }, Self::String(a)) => a == b, + // Split into two arms with position-consistent bindings so `a` is + // always the left operand. Equality is symmetric so a combined + // or-pattern with swapped bindings gives the same answer here, but + // the identical pattern in an ordering context silently reverses + // the comparison (see `compare`). + (Self::String(a), Self::Path { value: b, .. }) => a == b, + (Self::Path { value: a, .. }, Self::String(b)) => a == b, // Same-variant typed lists: primitive element comparison (no // per-element ExprValue construction), charged per comparison // actually performed after the O(1) length check — a mismatch