mirror of
https://github.com/Z3Prover/z3
synced 2026-06-19 15:16:29 +00:00
`seq_offset_eq::find` returned the stored offset with the wrong sign
whenever the enode arguments were reordered to match the canonical key
ordering (`r1.id ≤ r2.id`), causing `len_based_split` to silently skip
~50% of eligible length-based splits.
### Root cause
`m_offset_equalities` stores `(rA, rB) → v` meaning `len(rA) − len(rB) =
v` with `rA.id ≤ rB.id`. `len_offset()` correctly negates `val` when
inserting with swapped keys. `find()` performed the same swap for the
lookup but never negated the returned value, so callers received
`len(n2) − len(n1)` instead of `len(n1) − len(n2)`.
### Fix
```cpp
// BEFORE
if (n1->get_owner_id() > n2->get_owner_id())
std::swap(n1, n2);
if (m_offset_equalities.find(n1, n2, offset))
return offset; // wrong sign when swapped
// AFTER
bool swapped = n1->get_owner_id() > n2->get_owner_id();
if (swapped)
std::swap(n1, n2);
if (m_offset_equalities.find(n1, n2, offset))
return swapped ? -offset : offset;
```
This makes `find` consistent with the documented contract (`r1 = r2 +
offset`) and symmetric with the insertion logic in `len_offset()`.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
|
||
|---|---|---|
| .. | ||
| ackermannization | ||
| api | ||
| ast | ||
| cmd_context | ||
| math | ||
| model | ||
| muz | ||
| nlsat | ||
| opt | ||
| params | ||
| parsers | ||
| qe | ||
| sat | ||
| shell | ||
| smt | ||
| solver | ||
| tactic | ||
| test | ||
| util | ||
| CMakeLists.txt | ||