Declare the sorts of quantifier binders in the emitted SMT-LIB2 - #247
Draft
coord-e wants to merge 3 commits into
Draft
Declare the sorts of quantifier binders in the emitted SMT-LIB2#247coord-e wants to merge 3 commits into
coord-e wants to merge 3 commits into
Conversation
The MIR analyzer is not the only place that discovers a type whose enums have to be declared as datatypes, so give the collection a home on the analyzer that owns the definitions. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015HS3g7RPk9yEa3DuGQ9kTo
Enum definitions are collected from the local declarations of the body under analysis, so an enum that a specification only mentions as the type of an `exists`/`forall` variable never reaches the CHC system and its datatype is missing from the emitted SMT-LIB2. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015HS3g7RPk9yEa3DuGQ9kTo
The sorts to declare were gathered from predicate signatures, clause variables and atom arguments, none of which mention the binder of an `exists`/`forall`. A specification quantifying over a variable whose sort appears nowhere else in its clause therefore produced a query referring to an undefined sort, which any SMT solver rejects while parsing. Fixes #142 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015HS3g7RPk9yEa3DuGQ9kTo
Contributor
There was a problem hiding this comment.
🟡 Changes recommended
The added UI tests do not detect regression of the central SMT declaration fix because their solver accepts malformed input.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
Fixes missing SMT datatype declarations for sorts used only by quantifier binders.
Changes:
- Collects quantified-variable sorts from clauses, bodies, and atom guards.
- Registers enum definitions reachable from quantified parameter types.
- Adds enum and tuple binder UI test pairs.
File summaries
| File | Description |
|---|---|
src/chc/format_context.rs |
Collects binder sorts for SMT formatting. |
src/chc.rs |
Adds recursive quantified-variable iterators. |
src/analyze.rs |
Centralizes enum-definition collection. |
src/analyze/basic_block.rs |
Uses the centralized enum collector. |
src/analyze/annot_fn.rs |
Registers enums used by quantified parameters. |
tests/ui/pass/annot_exists_enum_binder.rs |
Adds passing enum-binder coverage. |
tests/ui/fail/annot_exists_enum_binder.rs |
Adds failing enum-binder coverage. |
tests/ui/pass/annot_exists_tuple_binder.rs |
Adds passing tuple-binder coverage. |
tests/ui/fail/annot_exists_tuple_binder.rs |
Adds failing tuple-binder coverage. |
Review details
- Files reviewed: 9/9 changed files
- Comments generated: 1
- Review effort level: Balanced
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| @@ -0,0 +1,13 @@ | |||
| //@check-pass | |||
| //@compile-flags: -C debug-assertions=off | |||
| //@rustc-env: THRUST_SOLVER=tests/thrust-pcsat-wrapper | |||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #142.
collect_sortsgathers the sorts to declare from predicate signatures, clause variables and atom arguments.iter_atomsdescends into the body of anExists/Forall, but the binder list is metadata no atom references, so a sort that appears only as a binder is never collected and the query names an undefined sort — rejected while parsing, by any backend.Fixing that alone turns the reported program into an ICE rather than a fix: enum definitions are collected from the local declarations of the body under analysis (
basic_block::Analyzer::register_enum_defs), so an enum a specification only mentions as the type of a quantified variable is not insystem.datatypesat all, andmonomorphize_datatypeunwraps aNoneon the now-collected sort. Both halves are needed.Reading order
The diff is 4 source files, but only ~40 lines carry behavior; the commits are meant to be read one by one.
7272014Lift the enum definition collection out of the basic block analyzerEnumCollectoris unchanged, it takes theTypeBuilderby reference instead of cloning it and walks one type per call instead of a loop of locals. The one behavioral nuance:visitedno longer spans the whole local list, which only means a type shared by two locals is walked twice;get_or_register_enum_defis idempotent.4f232a3Register the enums a quantified variable's type is built fromAnnotFnTranslator::to_formula_with_quantified_vars. No effect on its own — nothing yet asks for the binder's sort.9ef66ffDeclare the sorts of quantifier binders in the emitted SMT-LIB2iter_quantified_varsonFormula/Atom/Bodyinchc.rs, mirroring the shape ofiter_atoms/fvnext to them, and five lines incollect_sorts.Atom::iter_quantified_varscovers the guard becausesmtlib2::Atomrenders it as(=> guard ...), so a quantifier there needs its sorts declared too, exactly like one in the body formula. The issue also suggests inserting the sort in theFormulaQuantifiedVararm ofterm_sorts; that arm is already covered by thesorts.insert(clause.term_sort(t))at the top of the function, so it is left alone.Testing
Verified against Z3 5.0.0 and the COAR image CI pins.
cargo testpasses (332 UI tests, plus doc tests);cargo fmt --checkandcargo clippy -- -D warningsare clean.The program from the issue, which reported
unknown sort 'E'before:Under Z3 the query is now well-formed but comes back
unknown, as any quantified specification does; under PCSat it verifies.Tests added
Two
pass/failpairs, both quantifying over a sort that appears nowhere else in the clause, which is what it takes to reach the bug — a binder used in the body has its sort collected through the atom arguments already:tests/ui/{pass,fail}/annot_exists_enum_binder.rs— an enum-sorted binder, the case in the issuetests/ui/{pass,fail}/annot_exists_tuple_binder.rs— a tuple-sorted binder, the second reproduction in the issueOne caveat worth knowing before reviewing them: PCSat, which the quantifier tests have to use, accepts the malformed query instead of rejecting it, so the
passfiles verify even without this change — under Z3 they fail loudly. What they do pin under CI is the ICE: with the sort collected and the registration reverted,pass/annot_exists_enum_binder.rspanics. I could not find a program that pins the declaration itself through PCSat; if you would rather have that covered, a unit test overFormatContext::from_systemwith a hand-built system would do it, and I am happy to add one.Generated by Claude Code