3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-06-11 03:15:36 +00:00

Fix MBP QEL soundness bug in datatype accessor elimination (#9571) (#9692)

Two fixes for mbp_dt_tg::apply() when encountering an accessor whose
argument has a different constructor in the model:

1. Don't call rm_accessor (which would assert a contradictory
recognizer, making the formula false). This prevents the original bug
where QEL returned 'false' for satisfiable formulas.

2. Branch on the model-assigned constructor for the accessor's argument.

The correct output should include the literal introduced in (2).
However, this fix does not produce it. Spacer is sound with this
over-approximation, as long as the counter example does not depend on
value of mismatched accessors (e.g. (tl nil)).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Hari Govind V K 2026-06-03 15:23:21 +01:00 committed by GitHub
parent a0a3047e36
commit 922f49e187
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 270 additions and 0 deletions

View file

@ -163,6 +163,24 @@ struct mbp_dt_tg::impl {
if (is_app(term) &&
m_dt_util.is_accessor(to_app(term)->get_decl()) &&
has_var(to_app(term)->get_arg(0))) {
// Only apply rm_accessor if the model confirms the argument
// has the constructor that this accessor belongs to.
// Otherwise we introduce a contradictory is-cons literal.
func_decl *cons =
m_dt_util.get_accessor_constructor(to_app(term)->get_decl());
func_decl *rec = m_dt_util.get_constructor_recognizer(cons);
expr_ref is_rec(m.mk_app(rec, to_app(term)->get_arg(0)), m);
if (!m_mdl.is_true(is_rec)) {
// Ground the argument so the accessor term becomes
// constructively ground. This preserves any enclosing
// literal (e.g., (not (is-nil (tl nil)))) as a guard in
// the output, preventing an over-approximation.
expr_ref is(m.mk_not(is_rec), m);
m_tg.add_lit(is);
mark_seen(term);
progress = true;
continue;
}
mark_seen(term);
progress = true;
rm_accessor(term);