Skip to content

Laurel: Add constrained type support#505

Open
fabiomadge wants to merge 1 commit intomainfrom
fabiomadge/constrained-types
Open

Laurel: Add constrained type support#505
fabiomadge wants to merge 1 commit intomainfrom
fabiomadge/constrained-types

Conversation

@fabiomadge
Copy link
Contributor

@fabiomadge fabiomadge commented Mar 3, 2026

Constrained Types for Laurel

Adds constrained types to Laurel via a Laurel-to-Laurel elimination pass that inserts verification checks at type boundaries.

Syntax

constrained nat = x: int where x >= 0 witness 0
constrained posnat = x: nat where x > 0 witness 1

How it works

The pass (ConstrainedTypeElim.lean) eliminates constrained types by:

  1. requires for constrained-typed inputs — Core handles caller asserts and body assumes via call elimination
  2. ensures for constrained-typed outputs — Core handles body checks and caller assumes
  3. assert after local variable init and reassignment of constrained-typed variables
  4. Witness as default for uninitialized constrained-typed variables
  5. Witness validation via synthetic procedures that assert the witness satisfies all constraints
  6. Quantifier constraint injectionforall(n: nat) => body becomes forall(n: int) => n >= 0 ==> body; exists uses &&
  7. Type resolution — all constrained type references resolved to base types

The Core translator sees only base types and regular requires/ensures/assert — no translator changes needed beyond pipeline wiring.

Functions

Functions (isFunctional procedures) with constrained return types have isFunctional cleared since the Laurel translator does not yet support function postconditions. A TODO marks this for restoration once that support lands.

Changes

  • ConstrainedTypeElim.lean — the elimination pass
  • LaurelGrammar.st — constrained type syntax
  • ConcreteToAbstractTreeTranslator.lean — parser for constrained keyword
  • LaurelToCoreTranslator.lean — pipeline wiring (import + pass + resolve)
  • T09_ConstrainedTypes.lean — 24 test procedures covering inputs, outputs, assignments, arguments, nested types, functions, witnesses, quantifiers, capture avoidance

Known limitations

  • resolveBaseType, getAllConstraints, and substId are partial — cyclic constrained type definitions loop forever; capture avoidance prevents a termination proof for substId

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@fabiomadge fabiomadge force-pushed the fabiomadge/constrained-types branch from 1c60132 to b2d41d6 Compare March 3, 2026 07:41
@fabiomadge fabiomadge force-pushed the fabiomadge/early-return-soundness branch 3 times, most recently from 579e349 to dd1139d Compare March 4, 2026 05:41
Base automatically changed from fabiomadge/early-return-soundness to main March 5, 2026 15:37
@fabiomadge fabiomadge force-pushed the fabiomadge/constrained-types branch 8 times, most recently from fa3f500 to 566122e Compare March 6, 2026 04:48
@fabiomadge fabiomadge changed the title Laurel: add constrained type support Laurel: Add constrained type support Mar 6, 2026
@fabiomadge fabiomadge force-pushed the fabiomadge/constrained-types branch from 566122e to e2ff8b6 Compare March 9, 2026 04:24
@fabiomadge fabiomadge force-pushed the fabiomadge/constrained-types branch 4 times, most recently from 3586981 to 9c8f422 Compare March 9, 2026 05:24
A Laurel-to-Laurel elimination pass (ConstrainedTypeElim.lean) that:
- Adds requires for constrained-typed inputs
- Adds ensures for constrained-typed outputs
- Clears isFunctional when adding ensures (function postconditions not yet supported)
- Inserts assert for local variable init and reassignment
- Uses witness as default initializer for uninitialized constrained variables
- Validates witnesses via synthetic procedures
- Injects constraints into quantifier bodies (forall → implies, exists → and)
- Resolves all constrained type references to base types
- Handles capture avoidance in identifier substitution

Core's call elimination handles caller-side argument asserts and
return value assumes automatically via requires/ensures.

Grammar: constrained type syntax
Parser: parseConstrainedType + topLevelConstrainedType
Test: T09_ConstrainedTypes — 25 test procedures
@fabiomadge fabiomadge force-pushed the fabiomadge/constrained-types branch from 9c8f422 to afd9ee8 Compare March 9, 2026 05:29
@fabiomadge fabiomadge marked this pull request as ready for review March 9, 2026 05:40
@fabiomadge fabiomadge requested a review from a team March 9, 2026 05:40
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