Skip to content

synth's requirements for a Z3 replacement — QF_BV one-shot validation; the static-link build is the real pain, not the solver #246

Description

@avrabe

Filed from synth (issue-hunt loop, not gale) in response to the "should we replace Z3?" question. These are synth's concrete requirements so an ecosystem solver decision — which loom is already partly making (#231 forwards Z3-discharged wsc.facts invariants to synth; #169 tracks Rocq gating) — is grounded in what synth actually needs.

TL;DR

synth's Z3 usage is the simplest possible SMT fragment, and the pain is the build, not the solver. Any decision should optimize for hermetic/reproducible builds and CI stability, because the solver capability is a non-issue at synth's fragment.

What synth uses Z3 for

synth-verify is a translation validator: for each lowering it asserts wasm_op_semantics ≠ arm_instruction_sequence_semantics and expects UNSAT (i.e. they're equivalent). Concretely:

  • Theory: QF_BV only (quantifier-free bitvectors). Active op surface in the validator: bvadd/bvsub/bvmul/bvudiv, bvand/bvor/bvxor, bvshl/bvlshr/bvashr, bvrotr, extract/concat, zero_ext/sign_ext, and signed+unsigned comparisons (bvult/bvule/bvugt/bvuge/bvslt/bvsgt). 32- and 64-bit widths.
  • Query model: one-shot check-sat + a counterexample model. No quantifiers, no arrays, no floating-point, no Optimize, no incremental push/pop/assumptions (verified by grep over synth-verify/src).
  • Pulled as the z3 crate 0.19 with features = ["static-link-z3"] — i.e. it compiles Z3 from C++ source via z3-sys's build.rs.

Why replace it (the actual pain)

It is a build/hermeticity problem, not a solver-quality problem:

  • z3-sys build.rs breaks local cargo test --workspace (panics around build.rs:374); synth's own docs tell contributors to --exclude synth-verify locally.
  • CI's Z3 Verification job flakes and the "comprehensive verification" step runs ~16 min and intermittently times out (seen this week on a RISC-V-only PR that can't even affect ARM semantics — pure infra flake, forced a re-run).
  • The from-source C++ compile is the long pole and the fragile part. The solver answers synth's QF_BV queries instantly and correctly; z3-the-build is what hurts.

Requirements for a replacement (synth side)

MUST

  1. Decide QF_BV check-sat with a returned model (counterexample) for the op set above, 32/64-bit.
  2. Hermetic, reproducible build — no from-source C++ compile in the critical path (prebuilt/vendored binary, or pure-Rust, or shell-out to an already-present solver binary). This is the whole point.
  3. Fast enough to gate CI without multi-minute timeouts at synth's query sizes (per-op equivalence checks are tiny).
  4. Permissive license (Z3 is MIT today — don't regress).
  5. Stable, thin Rust API (build a BV term graph, assert, check, read model).

NICE

  • Solver-agnostic interface (so the choice isn't a one-way door).
  • Deterministic results across platforms (macOS/Linux CI parity).

NOT required today (don't over-buy): quantifiers, arrays, floating-point, optimization, incremental solving. One flag for the future: the #369 FPU work (hard-float f32/f64) may eventually want QF_FP verification — worth keeping on the radar, but it is not a current dependency and shouldn't gate the decision.

Directions (synth has no strong preference — loom decides the ecosystem story)

Coordination ask

Whatever loom picks for discharging wsc.facts invariants (#231), synth would prefer the same solver/interface so the ecosystem has one solver story and one build story. If loom standardizes on an SMT-LIB2-text contract, synth can adopt it directly for translation validation.

Refs: loom #231, loom #169; synth #242 (VCR North Star), synth #73, synth #369.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions