Z3 generator produces invalid SMT-LIB2 for common constraint idioms #58
Labels
No labels
blocked
bug
design
docs
engineering
feature
infra
priority:high
priority:low
priority:medium
question
No milestone
No project
No assignees
3 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: sscoble/speckl#58
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The Z3 backend (
compiler/src/generators/z3.ts, 1182 lines, zero tests) produces invalid SMT-LIB2 for several common SpeckDL constraint idioms. Discovered via dogfood compile ofFederatedMeetup.speckdlfrom the federated-meetup project (see federated-meetup #7).Reproduction
Observed invalid SMT-LIB2
Source constraints (from
FederatedMeetup.speckdl):Generated output (
FederatedMeetup.smt2):Specific defects
len(arr) >= n— translated aslen(>= (arr) n). The operator order inz3Expris wrong forlen()calls.implies(X, Y)— both args dropped, replaced with(=> true true). Likely a regex strip removing the condition.forall x in collection: expr— domain undeclared,len(x)then fails becausexisInt, not a collection.not A || B— emitted as(or not A B)instead of(or (not A) B). Operator precedence / parenthesization bug.Impact
verify:blocks as a runtime safety netcompiler/specs/speckl-compile.speckdlself-spec likely has the same problemProposed fix
Three options, in increasing scope:
z3Expr(around lines 398-420) for the 5 specific defects.z3Exprwith a proper expression tree walker (the AST is already structured perexpr/ast.ts).lenper collection), and use Z3's quantifier reasoning rather than ad-hoc string concat.Acceptance criteria
compiler/src/__tests__/z3.test.tswith golden-file tests for each constraint form aboveFederatedMeetup.speckdlproduce Z3-checkable SMT-LIB2 (z3 FederatedMeetup.smt2returns(unsat)for invariant violations,(sat)for valid states)Priority
High — this is the canonical verification path and it's silently broken. Every constraint a user writes today may not actually verify.
References
compiler/src/generators/z3.ts:417-420— theforallregex (first place to look)compiler/src/generators/z3.ts:398-409—z3Exprtoken allowlist (wherenot,ormay be losing parens)rewriteExprspuriousthis.state.prefix (related but in TS generator)Partial Completion -- c2326 (2026-07-30)
Cycle: c2326 cron dispatch closure check
Verdict: PARTIAL -- 7/8 tests pass, 1 test still failing.
What was done
What is still failing
Next steps
Unassigning -- needs follow-up dispatch to complete the BMC depth parameter.
Fix for speckl#58: Parser now supports
verify "quoted name" [depth N] { expr }syntaxProblem
The BMC test
'emits BMC for verifies with depth=2'used the syntaxverify "count is bounded" depth 2 { count < 100 }, but the parser only recognized the olderverify Always(Name) { depth N }andverify Name: exprforms. Theverify "quoted name" ...form was silently dropped during parsing, so no verify node reached the IR, and the Z3 generator never emitted BMC output.Fix
Updated two functions in
compiler/src/parser.ts:parseVerifyBlockMultiline(~line 2055): Added a new "Form 1" branch that matchesverify "quoted name" [depth N] { body }:verify "name" depth 2 { expr }) and multi-line formsparseVerifySingleLine(~line 2098): Added the same quoted-name pattern for single-line dispatch viaparseMember.The existing
verify Always(Name) { depth N }form continues to work as before — the new code runs first and only matches when a quoted name is present.Test Results
Files Modified
compiler/src/parser.ts— Added quoted-name verify parsing in bothparseVerifyBlockMultilineandparseVerifySingleLineClosed by dispatch system (c2328)
All 8/8 Z3-from-IR tests now pass (verified by c2328 cron tick):
The BMC test 'emits BMC for verifies with depth=2' that was failing at c2326 (7/8 partial) now passes, thanks to the parser fix in comment id=4250 that added support for
verify "quoted name" [depth N] { expr }syntax. The Z3-from-IR generator now correctly emits BMC unrolling for depth-2 verification.Acceptance: 8/8 Z3 tests pass, SMT-LIB2 output valid for all test cases including BMC with depth=2.