Skip to content

feat: support postconditions on Laurel functions#668

Draft
fabiomadge wants to merge 1 commit intomainfrom
feat/function-postconditions
Draft

feat: support postconditions on Laurel functions#668
fabiomadge wants to merge 1 commit intomainfrom
feat/function-postconditions

Conversation

@fabiomadge
Copy link
Contributor

@fabiomadge fabiomadge commented Mar 26, 2026

Adds support for function postconditions (both ensures clauses and constrained return types) via a new Laurel-to-Laurel pass.

What it does:

  • Generates a f$post function per function with postconditions
  • Generates a $check_f procedure that verifies the body satisfies the postcondition
  • Inserts assume f$post(args, result) at call sites
  • Lifts nested postconditioned function calls out of expressions
  • Functions remain functions in Core (not converted to procedures)

Grammar:

  • function f(): int ensures result > 0 { ... } — transparent, body visible to callers
  • opaque function f(): int ensures result > 0 { ... } — body hidden, callers only see postcondition
  • function f(): nat { ... } — constrained return type becomes a postcondition

AST change:

  • Body.Transparent now carries a postconditions list, allowing functions to have postconditions without becoming Opaque

What changes:

  • Laurel.lean: add postconditions field to Body.Transparent
  • LaurelGrammar.st: add opaque modifier on function
  • ConcreteToAbstractTreeTranslator.lean: route function bodies to Transparent with postconditions
  • ConstrainedTypeElim.lean: attach constrained return ensures directly to Transparent postconditions for functions
  • FunctionPostcondElim.lean: new pass (~310 lines)
  • LaurelToCoreTranslator.lean: wire in new pass, drop body for opaque functions
  • All Laurel passes: preserve new Transparent postconditions field
  • Tests: 17 new test cases

@fabiomadge fabiomadge force-pushed the feat/function-postconditions branch 30 times, most recently from 258b65f to 65bc9af Compare March 26, 2026 07:09
@fabiomadge fabiomadge force-pushed the feat/function-postconditions branch 3 times, most recently from 7e03bc1 to 65afa61 Compare March 27, 2026 03:48
Add a new Laurel-to-Laurel pass (FunctionPostcondElim) that eliminates
function postconditions from both explicit ensures clauses and
constrained return types.

For each function with postconditions, the pass generates:
- A postcondition function (f$post)
- A check procedure ($check_f) that verifies the body
- assume statements at call sites

Functions remain functions in Core with transparent bodies.
Opaque functions (opaque keyword) hide the body from callers.

Changes:
- Laurel.lean: add postconditions field to Body.Transparent
- LaurelGrammar.st: add opaque modifier on function
- ConcreteToAbstractTreeTranslator.lean: route function bodies to
  Transparent with postconditions
- ConstrainedTypeElim.lean: attach constrained return ensures directly
  to Transparent postconditions for functions
- FunctionPostcondElim.lean: new pass
- LaurelToCoreTranslator.lean: wire in new pass, drop body for opaque
  functions
- All Laurel passes: preserve new Transparent postconditions field
- Tests: new test cases for all scenarios
@fabiomadge fabiomadge force-pushed the feat/function-postconditions branch from 65afa61 to 0fdf007 Compare March 27, 2026 03:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant