Skip to content

feat: intrinsic verification syntax for do-notation loops and def contracts#14389

Draft
sgraf812 wants to merge 6 commits into
masterfrom
sg/kr1-intrinsic-do
Draft

feat: intrinsic verification syntax for do-notation loops and def contracts#14389
sgraf812 wants to merge 6 commits into
masterfrom
sg/kr1-intrinsic-do

Conversation

@sgraf812

@sgraf812 sgraf812 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

This PR adds intrinsic verification syntax for Std.Internal.Do do-notation: loop invariants and function contracts that vcgen discharges automatically.

A for x in xs invariant cur => I do … loop annotates its invariant onto the loop combinator, elaborated in the loop body's scope so mutable variables and outer-loop variables resolve by name; nested loops are supported. A def may carry require P and ensures b => Q clauses on its signature, expanding to the plain definition plus an @[spec]-tagged specification theorem f.spec : ⦃P⦄ f args ⦃fun b => Q⦄ proved by vcgen [f] with finish. The corpus example findSmallest is then fully automatic with zero manual proof.

invariant, require, and ensures remain usable as ordinary identifiers; a bare occurrence only ends the preceding term in the position where the clause is expected. The contract expander is a builtin macro, so contracts work when only Std.Tactic.Do is imported. Scope is the MVP: for loops over List and Std.Legacy.Range; while, signals, and residual-VC discharge are not included.

@sgraf812 sgraf812 added the changelog-language Language features and metaprograms label Jul 14, 2026
@sgraf812
sgraf812 force-pushed the sg/kr1-intrinsic-do branch from ae7fb19 to 2adc4e1 Compare July 14, 2026 16:50
@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Jul 14, 2026
@mathlib-lean-pr-testing

mathlib-lean-pr-testing Bot commented Jul 14, 2026

Copy link
Copy Markdown

Mathlib CI status (docs):

  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 3c080a47dbbe4b32ab01fd7ae332ad6bd30b4054 --onto 12c859a4d735fbcdb3ebbddb42dcc8619bcc7a7d. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-14 17:27:25)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase 3c080a47dbbe4b32ab01fd7ae332ad6bd30b4054 --onto a4b639c5a1e545677b36b09a4770b7b559df805b. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-15 12:12:43)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase aacd6121be3b52724ac1cd63ea5eca9f4b1c3c09 --onto 323137b022369d56a044ae5af01d1efd55872361. You can force Mathlib CI using the force-mathlib-ci label. (2026-07-21 10:29:44)

@leanprover-bot

leanprover-bot commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 3c080a47dbbe4b32ab01fd7ae332ad6bd30b4054 --onto 7847ce51363794755252279e6732240bd4f27ca8. You can force reference manual CI using the force-manual-ci label. (2026-07-14 17:27:27)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase 3c080a47dbbe4b32ab01fd7ae332ad6bd30b4054 --onto a4b639c5a1e545677b36b09a4770b7b559df805b. You can force reference manual CI using the force-manual-ci label. (2026-07-15 12:12:45)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase aacd6121be3b52724ac1cd63ea5eca9f4b1c3c09 --onto 49ff95727f98d43984726b26742d17a1ceea9dd5. You can force reference manual CI using the force-manual-ci label. (2026-07-21 10:29:46)

@sgraf812
sgraf812 force-pushed the sg/kr1-intrinsic-do branch 2 times, most recently from b94b350 to fa3413e Compare July 15, 2026 11:45
sgraf812 added 6 commits July 21, 2026 09:26
Adds `Std.Internal.Do.ForIn.forInWithInvariant`, a `forIn` gadget annotated with its loop invariant so `vcgen` reads it from the program instead of an `invariants` clause. It is definitionally `forIn xs init f`, so the annotation is erased at runtime. Provides `@[spec]` specifications for `List` and `Std.Legacy.Range` loops plus the `ForIn.toList` bridge lemmas, and exposes `ForIn.toArray`/`ForIn.toList`.
Adds a `for x in xs invariant cur => I do …` clause to `do` blocks: the invariant is lowered onto the loop combinator as the `ForIn.forInInv` annotation, elaborated in the loop body's scope so mutable variables and outer-loop variables resolve by name. Registers the control-info handler so the form nests.
Adds `require P` and `ensures b => Q` clauses on `def` signatures. A definition carrying them expands to the plain definition plus an `@[spec]`-tagged specification theorem `f.spec : ⦃P⦄ f args ⦃(fun b => Q); ⊥⦄` proved by `vcgen [f] with finish`.
…t relocation

Snapshot for main PR. Not for merge.
An @[macro] on `declaration` only fires when the defining module is imported; the builtin implementation makes `require`/`ensures` contracts work when a user imports only Std.Tactic.Do.
@sgraf812
sgraf812 force-pushed the sg/kr1-intrinsic-do branch from fa3413e to 2e74ff6 Compare July 21, 2026 10:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-language Language features and metaprograms toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants