Support Rust syntax in thrust::predicate bodies#114
Draft
coord-e wants to merge 5 commits into
Draft
Conversation
Predicate bodies can now be written as ordinary Rust boolean expressions
instead of raw SMT-LIB2 string literals, reusing the formula_fn translation
pipeline (AnnotFnTranslator).
A predicate whose body is a Rust expression is emitted by the
thrust_macros::predicate proc macro with an additional #[thrust::formula_fn]
attribute; that attribute is the discriminator. When present, the body is
translated through the existing formula_fns cache and the resulting
chc::Formula is emitted as the predicate's SMT define-fun. Raw SMT2 string
bodies continue to work unchanged.
- chc: UserDefinedPredDef gains a UserDefinedPredBody { Raw, Formula } enum
plus push_pred_define_formula; smtlib2 renders a Formula body via a
synthetic Clause; unbox unboxes Formula bodies.
- analyze: register predicate items marked formula_fn; define_as_predicate
pulls the translated formula from formula_fn_with_args and names params
v{i} to match TermVarIdx rendering.
- annot_fn: ExprKind::Field resolves named ADT fields (e.g. self.x) to tuple
projection indices, enabling struct predicates in trait impls.
- macro: detect raw-vs-Rust body, rewrite self->self_, add allow attrs.
- tests: paired pass/fail ui tests for free-function and trait predicates.
https://claude.ai/code/session_01WdLyxyy4ieAxrexj83X5MX
Rewrite the existing predicate ui tests (annot_preds, annot_preds_trait, annot_preds_trait_multi; pass and fail) to use the new Rust-expression predicate bodies instead of raw SMT-LIB2 string literals, and drop the now-redundant *_rust_syntax duplicate tests added earlier. https://claude.ai/code/session_01WdLyxyy4ieAxrexj83X5MX
Replace the synthetic `Clause` used to render a predicate's translated formula with a `TermSortEnv` trait: anything that can resolve a term-level variable's sort (a `Clause` via its `vars`, or a bare `IndexVec<TermVarIdx, Sort>` for a define-fun signature) can drive term rendering. The smtlib2 Display wrappers now hold `&dyn TermSortEnv` instead of `&Clause`, so no fake clause is fabricated. Also revert the named-struct-field translator change and the trait predicate test conversions: that field resolution is now a separate PR (#118). The trait predicate tests stay on raw SMT2 here and can move to Rust syntax once the field PR lands; the scalar free-function predicate test exercises the Rust-syntax path. https://claude.ai/code/session_01WdLyxyy4ieAxrexj83X5MX
Now that named struct-field resolution is on main (#118), flip the trait predicate tests (annot_preds_trait, annot_preds_trait_multi; pass and fail) from raw SMT-LIB2 bodies to Rust-expression bodies using `self.x`. https://claude.ai/code/session_01WdLyxyy4ieAxrexj83X5MX
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.
Summary
#[thrust::predicate]bodies can now be written as ordinary Rust boolean expressions instead of raw SMT-LIB2 string literals, reusing the existingformula_fntranslation pipeline (AnnotFnTranslator).Raw SMT2 string bodies still work unchanged (backward compatible).
How it works
A predicate written with
#[thrust_macros::predicate]whose body is a Rust expression is expanded with an additional#[thrust::formula_fn]attribute, which is the single discriminator:AnnotFnTranslatorthrough the existingformula_fnscache (formula_fn_with_args), exactly likerequires/ensures/invariant. The resultingchc::Formulais emitted as the predicate's SMTdefine-fun.The macro picks which by inspecting the body (string-literal statement ⇒ raw; otherwise Rust). Borrow-check skipping is free, since
mir_borrowck_skip_formula_fnalready keys on theformula_fnattribute. Predicate call sites are still resolved as namedUserDefinedPredatoms, so the dual attribute doesn't change call-site behavior.Changes
chc.rs—UserDefinedPredDefbody becomes aUserDefinedPredBody { Raw, Formula }enum; addpush_pred_define_formula. NewTermSortEnvtrait (var_sort/term_sort), implemented forClauseandIndexVec<TermVarIdx, Sort>.chc/smtlib2.rs— theTerm/Atom/Formula/BodyDisplay wrappers now hold&dyn TermSortEnvinstead of&Clause. AFormulapredicate body is rendered by passing the sig's sorts as anIndexVec— no synthetic/fakeClauseis fabricated.chc/format_context.rs— uses theTermSortEnvtrait (movedClause::term_sortonto it).chc/unbox.rs— unboxFormulapredicate bodies.analyze/crate_.rs— register predicate items also markedformula_fn.analyze/local_def.rs—define_as_predicatebranches on theformula_fnattribute; pulls the formula fromformula_fn_with_args, naming paramsv{i}.thrust-macros/src/spec.rs—expand_predicate: detect raw-vs-Rust body; for Rust bodies add#[thrust::formula_fn], rewriteself→self_, add allow-attrs.annot_preds), trait (annot_preds_trait), and multi-field (annot_preds_trait_multi) predicate tests (pass + fail) converted to Rust syntax.Dependency
Named struct-field access (
self.x) in the trait/multi-field predicates relies on #118 (merged), which taught the formula translator to resolve named ADT fields.mainis merged into this branch, so that support is included here.Verification
self.x * 2 == doubled.xlowers to exactly(= (* (tuple_proj<Int>.0 v0) 2) (tuple_proj<Int>.0 v1))— identical to the previous raw form.https://claude.ai/code/session_01WdLyxyy4ieAxrexj83X5MX