3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-28 03:18:49 +00:00
z3/src/sat/smt
Copilot 881360db5a
Fix constant array UNSAT missed for small-domain store chains (#9907)
Z3 incorrectly returns SAT for formulas like `store(store(const(x), i0,
e0), i1, e1) = store(store(const(y), i0, e0), i1, e1) ∧ x ≠ y` when the
index sort has a small finite domain (e.g. `(_ BitVec 2)` = 4 elements).
The quantifier-based encoding of the same constraint correctly returns
UNSAT.

## Changes

### `src/sat/smt/array_solver.cpp` — `add_parent_lambda()`

When a store is added to an array's `m_parent_lambdas` after that array
already has `m_has_default = true` (i.e., a `default(array)` term
already exists in the e-graph), the default axiom for the new store was
silently dropped. This breaks the propagation chain:

```
default(const(x)) = x
  ↓ [via store default axiom]
default(store(const(x), i, v)) = x
  ↓ [via store default axiom]
default(store(store(const(x), ...), ...)) = x
  ↓ [EUF congruence from store equality]
x = y  →  contradiction
```

Fix: push `default_axiom(lambda)` in `add_parent_lambda` when
`m_has_default` is already set, so late-arriving stores still get their
default axioms instantiated.

```cpp
void solver::add_parent_lambda(theory_var v_child, euf::enode* lambda) {
    auto& d = get_var_data(find(v_child));
    ctx.push_vec(d.m_parent_lambdas, lambda);
    if (should_prop_upward(d))
        propagate_select_axioms(d, lambda);
    if (d.m_has_default)           // new: fire default axiom retroactively
        push_axiom(default_axiom(lambda));
}
```

### Known remaining gap

`mk_eq_core` in `array_rewriter.cpp` also has a related issue: the
unconditional store-chain expansion fires only when `domain_size >
num_lhs + num_rhs` (line 893), but the correct threshold is `domain_size
> max(num_lhs, num_rhs)`. With 4-element domain and 2 stores per side,
`2+2 = 4` equals the domain size so the expansion is skipped. The
variant gated by `m_expand_store_eq` already uses `max()` correctly
(line 911); the unconditional path needs the same fix.

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
2026-06-19 18:31:44 -06:00
..
arith_axioms.cpp fix #7753 2025-08-17 17:20:10 -07:00
arith_diagnostics.cpp Eliminate unnecessary copies with std::move for ref-counted types (#8591) 2026-02-13 12:16:47 +00:00
arith_internalize.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
arith_solver.cpp Adopt C++17 structured bindings for map/pair iteration (#8159) 2026-01-11 17:44:12 -08:00
arith_solver.h remove set cardinality operators from array theory. Make final-check use priority levels 2025-11-26 15:35:19 -08:00
arith_theory_checker.h Remove copies (#8583) 2026-02-11 18:14:36 +00:00
arith_value.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
arith_value.h Add intblast solver 2023-12-15 13:50:38 -08:00
array_axioms.cpp Add SMT-LIB choice support via array OP_CHOICE and instantiate choice axioms in array solvers (#9649) 2026-05-27 10:05:06 -07:00
array_diagnostics.cpp Add SMT-LIB choice support via array OP_CHOICE and instantiate choice axioms in array solvers (#9649) 2026-05-27 10:05:06 -07:00
array_internalize.cpp Add SMT-LIB choice support via array OP_CHOICE and instantiate choice axioms in array solvers (#9649) 2026-05-27 10:05:06 -07:00
array_model.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
array_solver.cpp Fix constant array UNSAT missed for small-domain store chains (#9907) 2026-06-19 18:31:44 -06:00
array_solver.h Add SMT-LIB choice support via array OP_CHOICE and instantiate choice axioms in array solvers (#9649) 2026-05-27 10:05:06 -07:00
atom2bool_var.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
atom2bool_var.h mbp (#4741) 2020-10-21 15:48:40 -07:00
ba_xor.h arrays (#4684) 2020-09-13 19:29:59 -07:00
bv_ackerman.cpp Sls (#7439) 2024-11-02 12:32:48 -07:00
bv_ackerman.h don't have bv-ackerman influence simplification 2022-08-21 15:25:18 -07:00
bv_delay_internalize.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
bv_internalize.cpp Add arity and bit-width SASSERTs to internalize_overflow (#8802) 2026-02-27 14:30:50 -10:00
bv_invariant.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
bv_solver.cpp Refactor bv_solver to use structured bindings for var_pos patterns (#8384) 2026-01-27 11:48:21 -08:00
bv_solver.h Handle overflow predicates in new core bit-vector internalization 2026-02-27 13:07:39 -10:00
bv_theory_checker.cpp remove once pragma from cpp file 2022-10-18 14:57:49 -07:00
bv_theory_checker.h wip - add bit-vector validator plugins and logging 2022-10-18 14:50:21 -07:00
CMakeLists.txt move smt params to params directory, update release.yml 2025-06-09 10:47:22 -07:00
distinct_theory_checker.h wip - features and bug-fixes to proof logging 2022-10-18 07:54:49 -07:00
dt_solver.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
dt_solver.h remove stale experimental code #8063 2025-12-12 05:49:05 +00:00
euf_ackerman.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
euf_ackerman.h Remove redundant default constructors when they're the only constructor (#8461) 2026-02-01 16:51:26 -08:00
euf_internalize.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
euf_invariant.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
euf_model.cpp remove a few useless dynamic casts 2025-09-13 21:06:55 +01:00
euf_proof.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
euf_proof_checker.cpp Sls (#7439) 2024-11-02 12:32:48 -07:00
euf_proof_checker.h Replace empty destructors with = default for compiler optimization (#8189) 2026-01-13 10:50:10 -08:00
euf_relevancy.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
euf_relevancy.h more fixes on relevancy 2022-01-04 22:02:28 -08:00
euf_solver.cpp remove set cardinality operators from array theory. Make final-check use priority levels 2025-11-26 15:35:19 -08:00
euf_solver.h add an option to register callback on quantifier instantiation 2025-08-06 21:11:55 -07:00
fpa_solver.cpp Refactor mk_concat call sites to use std::initializer_list (#8494) 2026-02-04 13:45:20 -08:00
fpa_solver.h #6364 - remove option of redundant clauses from internalization 2022-10-24 00:38:31 -07:00
intblast_solver.cpp Fix intblast ubv_to_int bug: add bv2int axioms for compound expressions 2026-02-25 00:46:13 +00:00
intblast_solver.h Fix intblast ubv_to_int bug: add bv2int axioms for compound expressions 2026-02-25 00:46:13 +00:00
pb_card.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
pb_card.h Use noexcept more. (#7058) 2023-12-16 12:14:53 +00:00
pb_constraint.cpp streamline pb solver interface and naming after removal of xor 2021-02-28 12:32:04 -08:00
pb_constraint.h remove unneeded iterator functions 2024-09-23 12:59:04 +01:00
pb_internalize.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
pb_pb.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
pb_pb.h #8552 2026-02-11 17:38:45 -08:00
pb_solver.cpp Fix true positive critical bugs from static analysis discussion #8764 2026-02-25 00:41:59 +00:00
pb_solver.h #8552 2026-02-11 17:38:45 -08:00
pb_solver_interface.h Add and fix a few general compiler warnings. (#5628) 2021-10-29 15:42:32 +02:00
q_clause.cpp fixes to sat.euf ematching #5573 2021-10-16 15:52:37 -07:00
q_clause.h log also quantifier generation (besides binding) 2022-10-20 17:49:15 -07:00
q_ematch.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
q_ematch.h update namespace, hoist exported functions outside of embedded namespace 2025-05-07 15:57:47 -07:00
q_eval.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
q_eval.h #5753 2022-01-15 09:35:25 -08:00
q_mbi.cpp Fix assertion violation in q_mbi diagnostic output 2026-02-28 11:15:28 -10:00
q_mbi.h track quantifier instantiation method in proof hint #7080 2024-01-20 17:44:07 -08:00
q_model_fixer.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
q_model_fixer.h Use = default for virtual constructors. 2022-08-05 18:11:46 +03:00
q_queue.cpp Standardize for-loop increments to prefix form (++i) (#8199) 2026-01-14 19:55:31 -08:00
q_queue.h redo bindings/fingerprints 2021-10-05 10:15:56 -07:00
q_solver.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
q_solver.h track quantifier instantiation method in proof hint #7080 2024-01-20 17:44:07 -08:00
q_theory_checker.cpp #6364 2022-10-20 16:39:43 -07:00
q_theory_checker.h wip - updates to proof logging and self-checking 2022-10-16 23:33:30 +02:00
recfun_solver.cpp Eliminate unnecessary copies with std::move for ref-counted types (#8591) 2026-02-13 12:16:47 +00:00
recfun_solver.h #6364 - remove option of redundant clauses from internalization 2022-10-24 00:38:31 -07:00
sat_internalizer.h fix #6623 2023-04-09 21:10:24 -07:00
sat_smt.h Remove redundant default constructors when they're the only constructor (#8461) 2026-02-01 16:51:26 -08:00
sat_th.cpp Refactor sat_th to use structured bindings for enode_pair patterns (#8386) 2026-01-27 12:02:28 -08:00
sat_th.h move smt params to params directory, update release.yml 2025-06-09 10:47:22 -07:00
sls_solver.cpp throttle value smt -> sls 2025-01-26 14:16:43 -08:00
sls_solver.h build fixes 2024-11-14 21:55:44 -08:00
specrel_solver.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
specrel_solver.h remove default destructors 2024-10-02 22:20:12 +01:00
tseitin_theory_checker.cpp strengthen Tseitin checker to take true/false constants into account 2023-07-28 16:54:33 -07:00
tseitin_theory_checker.h wip - proof checking, add support for distinct, other fixes 2022-10-17 17:51:10 -07:00
user_solver.cpp Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
user_solver.h fix bugs with tracking premises in user propagator in sat/smt 2024-05-31 11:25:09 +04:00
xor_solver.cpp wip - remove stale skaffolding for retrieving sub-hints. 2022-10-16 17:18:08 -07:00
xor_solver.d Centralize and document TRACE tags using X-macros (#7657) 2025-05-28 14:31:25 +01:00
xor_solver.h fix build 2022-10-24 10:23:50 +01:00