Skip to content

Support contracts on functions#45

Draft
keyboardDrummer-bot wants to merge 329 commits into
transparencyPassBasefrom
transparency-pass-only
Draft

Support contracts on functions#45
keyboardDrummer-bot wants to merge 329 commits into
transparencyPassBasefrom
transparency-pass-only

Conversation

@keyboardDrummer-bot
Copy link
Copy Markdown
Collaborator

@keyboardDrummer-bot keyboardDrummer-bot commented May 8, 2026

Summary

This PR is a copy of PR #28 (Add contract and transparency pass) but without the first two phases:

  • EliminateReturnStatements: rewrite return to exit statements
  • ContractPass: translate away pre and postconditions entirely by introducing assertion and assumptions at call sites and at procedure starts and ends

What's included

The remaining passes from PR #28 are kept:

  • [New] TransparencyPass: for each Core procedure, generate a function with the same signature and name suffixed with $asFunction. If a Core procedure is marked as transparent, attempt to generate a functional version of it, where assertions are erased and all calls are to functional versions. Tie the functional version to the procedure using a free postcondition.
  • [Existing] LiftImperativeExpressions: extended to handle asserts, assumes, and more expression types
  • [New] EliminateMultipleOutputs: collapse multi-output functions into single result datatypes
  • [New] InlineLocalVariablesInExpressions: inline local variables in function bodies
  • CoreGroupingAndOrdering: refactored to compute SCC ordering for functions and proofs separately

Fixes included

Includes fixes from:

Changes from PR #28

  • Removed ContractPass.lean and EliminateReturnStatements.lean
  • Removed their invocations from LaurelCompilationPipeline
  • Restored invokeOn axiom handling in the translator (since the contract pass no longer populates proc.axioms)
  • Reverted test expectations that depended on contract pass behavior (precondition error messages at call sites)

Known issues

  • Some test assertions may fail because without the contract pass, postconditions are not assumed at call sites (callers can't prove properties about return values of opaque procedures)
  • Error messages for precondition violations at call sites will say "precondition does not hold" instead of "assertion could not be proved"

Related: #28, #43

keyboardDrummer and others added 30 commits April 20, 2026 15:50
…opaqueSpec

- Changed procedureToOp to produce opaqueSpec op with ensures and modifies
  as nested args (matching the grammar), instead of separate top-level args
- Added missing opaque keyword in MapStmtExprTest and T2_ModifiesClauses tests
…lator

- Add `axioms : List StmtExprMd` field to Laurel's Procedure structure
- In ContractPass, build axiom expressions from invokeOn trigger + ensures
  clauses (nested Forall with trigger on innermost quantifier), then clear
  the invokeOn field
- Update LaurelToCoreTranslator to translate proc.axioms directly instead
  of using the now-removed translateInvokeOnAxiom function
- Update CoreGroupingAndOrdering to use axioms instead of invokeOn for
  procedure ordering and callee collection
- Update Resolution to preserve axioms through name resolution
- Update MapStmtExpr to traverse axioms in mapProcedureM
- Fix InvokeOn test expected error messages
- Grammar: Add `modifiesWildcard` op for `modifies *` syntax
- Parser: Handle `modifiesWildcard` by producing `StmtExpr.All` in modifies list
- Printer: Emit `modifiesWildcard` when modifies list contains `All`
- ModifiesClauses: Skip frame condition generation for wildcard modifies
- FilterNonCompositeModifies: Preserve `All` entries (don't filter as non-composite)
- HeapParameterization: Don't treat wildcard `All` as evidence of heap access
- PythonToLaurel: Use `modifies *` for all opaque procedures
- Specs/ToLaurel: Use `modifies *` for spec procedures
- T2_ModifiesClauses: Uncomment wildcard test case
Two issues were causing the Python test failures:

1. dbg_trace statements in LaurelCompilationPipeline.lean were printing
   massive debug output that polluted #guard_msgs test expectations.

2. The contract pass (ContractPass.lean) created Assert/Assume nodes
   with source := none (via mkMd). When these reached the Core
   translator, getNameFromMd triggered 'BUG: metadata without a
   filerange' debug traces, further polluting test output.

Fix: propagate source locations from the original preconditions and
body to the Assert/Assume/Block nodes created by transformProcBody.
Prefix `program` parameter with underscore to suppress the
'unused variable' warning that causes the docs build to fail
with --wfail.
…nditions

Key fixes to TransparencyPass.lean:
- Keep already-functional procedures (like readField, updateField,
  nat$constraint) as functions instead of converting them to procedures.
  This fixes 'calls to procedures are not supported in functions' errors.
- Only create $asFunction copies for imperative procedures, not for
  procedures that are already functional.
- Clear preconditions on $asFunction copies to prevent spurious
  precondition check failures in free postconditions.

Update test expectations to match the new behavior:
- Functions with assert/assume now report 'not YET supported' errors
  (since they're properly translated as functions now)
- Some assertions that previously failed now pass (transparency pass
  provides free postconditions that make them provable)
- Error message format changes (e.g. 'does not hold' vs 'could not be proved')
- T1_MutableFields remains a pre-existing failure (multi-target assignment
  type translation issue)
The second lifting pass (liftImperativeExpressionsInCore) was keeping
variable declarations inside blocks while lifting assignments that
reference those variables to the outer scope. This created dangling
references that the resolution pass couldn't resolve, causing
'Unknown' types that triggered the 'Core program was suppressed due
to superfluous errors' bug.

Fix: restore the original behavior of prepending Declare statements
from blocks to the outer scope, so they remain visible to lifted
assignments that reference them.

Also add a defensive check in translateExpr for Var (.Local name):
when a variable's type is Unknown (unresolved), omit the type
annotation instead of calling invalidCoreType, which would set
coreProgramHasSuperfluousErrors without emitting a diagnostic.

Update T2_ModifiesClauses test expectations: two assertions that
previously failed are now provable thanks to the transparency pass
providing free postconditions with correct modifies frame conditions.
The transparency pass generates free postconditions for each procedure,
which adds extra passing verification conditions to the output. Update
all 206 expected files to reflect the new postcondition VCs.
The benchmark job hardcodes --source-location-override to strata-org/Strata.git,
so it fails on forks where the PR head SHA doesn't exist in that repo.
Add an 'if' condition to only run when github.repository is strata-org/Strata.
@keyboardDrummer keyboardDrummer changed the base branch from issue-21-assign-variable-type to main May 13, 2026 17:19
@github-actions github-actions Bot added the Git conflicts PR has merge conflicts with the base branch label May 13, 2026
@keyboardDrummer
Copy link
Copy Markdown
Owner

@keyboardDrummer-bot please resolve the conflicts

@github-actions github-actions Bot removed the Git conflicts PR has merge conflicts with the base branch label May 13, 2026
@keyboardDrummer keyboardDrummer force-pushed the transparency-pass-only branch from 284c852 to 7380f7c Compare May 14, 2026 08:40
@keyboardDrummer-bot
Copy link
Copy Markdown
Collaborator Author

@keyboardDrummer The branch transparency-pass-only already contains the latest main (5f5a701) — there are no merge conflicts to resolve. The PR's "unstable" mergeable state appears to be due to failing CI checks rather than conflicts. Let me know if there's something else I should address.

@keyboardDrummer keyboardDrummer changed the base branch from main to transparencyPassBase May 14, 2026 08:44
@keyboardDrummer keyboardDrummer force-pushed the transparency-pass-only branch from ee8185b to bd66145 Compare May 14, 2026 08:50
@keyboardDrummer keyboardDrummer changed the title Add transparency pass (without contract and return elimination) Merge Laurel functions and procedures May 14, 2026
@keyboardDrummer keyboardDrummer changed the title Merge Laurel functions and procedures Unify Laurel functions and procedures May 14, 2026
@keyboardDrummer keyboardDrummer changed the title Unify Laurel functions and procedures Support contracts on functions May 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants