Skip to content

refactor: separate the generic and the monadic weakest-precondition modules - #14778

Merged
sgraf812 merged 9 commits into
masterfrom
sg/wp-generic-split
Aug 13, 2026
Merged

refactor: separate the generic and the monadic weakest-precondition modules#14778
sgraf812 merged 9 commits into
masterfrom
sg/wp-generic-split

Conversation

@sgraf812

@sgraf812 sgraf812 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

This PR splits the modules of Std.Internal.Do so that each one holds generic material or monadic material. The generic modules apply to any program type with a WP interpretation, including deep embeddings.

The monadic material moves under Std.Internal.Do.WP.Monad and Std.Internal.Do.Triple.Monad. The namespaces stay the same, and import Std.Internal.Do still supplies every instance. A later PR renames the result to Std.WP and Std.WP.Do.

…he order library

This PR states the frame closure as a map from predicate transformers to predicate transformers. It also moves the closure and `PredTrans` to `Std.Internal.Order`.

The closure took a bare post-transformer before. Its type therefore did not show what it was. It is now `PredTrans.frameClosure op : PredTrans Pred EPred β → PredTrans Pred EPred β`. The `WP` instance built from it reduces to `wpTrans x := (base.wpTrans x).frameClosure op`.

`Std/Internal/Do/PredTrans.lean` is gone. The structure and its instances are now together in `Lean.Order`, because instances belong with their type. The declarations that name `EPost` remain in `Std.Internal.Do`, because the order library does not import `EPost`. `PredTrans.pushExcept` and `pushOption` join the `WPMonad` instances that use them. The two `EPost.Cons` helpers join the rest of the `EPost` API in `ExceptPost.lean`.

Four proofs in `ExceptT` and `OptionT` now use `apply_pushExcept` and `apply_pushOption`. Before, they restated the unfolded form.

The split changes one behaviour. It changes the relative declaration order of the three `MonadExceptOf` instances on `PredTrans`. Instance search at equal priority therefore reaches them in a different order. No goal in the tree matches more than one of them.
…odules

This PR splits four modules of `Std.Internal.Do` so that each module holds either generic or monadic material. The generic side names no monad. It applies to any program type with a `WP` interpretation, including deep embeddings.

`WP`, `wp` and the `wp_consequence` family stay in `Std.Internal.Do.WP.Basic`. `WP.Frames` stays in `Std.Internal.Do.WP.Frame`. The `WPConjunctive` class stays in `Std.Internal.Do.WP.Conjunctive`. `Triple` and its notation stay in `Std.Internal.Do.Triple.Basic`.

`WPMonad`, the transformer instances, the adequacy lemmas, the `WPConjunctive` instances and `WPMonad.of_frameClosure` move under `Std.Internal.Do.WP.Monad`. The triples for `pure`, `bind`, `map` and `seq` move to `Std.Internal.Do.Triple.Monad`. `Std.Internal.Do.WP.Lemmas` becomes `Std.Internal.Do.WP.Monad.Lemmas`, because every lemma in it names a monad.

The namespaces stay unchanged. Only files move. A later PR will rename the result to `Std.WP` and `Std.WP.Do`.

`Std.Internal.Do.WP` publicly imports `Std.Internal.Do.WP.Monad`, so `import Std.Internal.Do` still supplies every instance.

This PR stacks on #14774. It must be rebased once that PR merges.
@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 Aug 13, 2026
@mathlib-lean-pr-testing

mathlib-lean-pr-testing Bot commented Aug 13, 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 537e47ab40ae11dd67a4024d2b5aad3bdbfd6e7a --onto 3fc29d37a70f8fd904ebab848557c12383543008. You can force Mathlib CI using the force-mathlib-ci label. (2026-08-13 13:38:26)
  • ❗ Batteries/Mathlib CI will not be attempted unless your PR branches off the nightly-with-mathlib branch. Try git rebase bc59d63228f0a0fa569480b161e304ff54d4ec84 --onto 3fc29d37a70f8fd904ebab848557c12383543008. You can force Mathlib CI using the force-mathlib-ci label. (2026-08-13 15:17:04)

@leanprover-bot

leanprover-bot commented Aug 13, 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 537e47ab40ae11dd67a4024d2b5aad3bdbfd6e7a --onto 3fc29d37a70f8fd904ebab848557c12383543008. You can force reference manual CI using the force-manual-ci label. (2026-08-13 13:38:28)
  • ❗ Reference manual CI will not be attempted unless your PR branches off the nightly-with-manual branch. Try git rebase bc59d63228f0a0fa569480b161e304ff54d4ec84 --onto 3fc29d37a70f8fd904ebab848557c12383543008. You can force reference manual CI using the force-manual-ci label. (2026-08-13 15:17:06)

This PR rewrites the module, class, and field docstrings in `Std.Internal.Do.WP.Conjunctive`. They glossed `wp_meet_wp_le` as mapping a meet of postconditions below the `wp` of their meet, but the left-hand side `wp x Q₁ E₁ ⊓ wp x Q₂ E₂` is a meet of two weakest preconditions. The docstrings now say that this meet lies below the weakest precondition `wp x (Q₁ ⊓ Q₂) (E₁ ⊓ E₂)` of the componentwise meet of the postconditions.
This PR expands the module docstring of `Std.Internal.Do.WP.Basic` with the `outParam` behaviour of the `WP` class and two worked examples, and it states what the frame closure buys a separation logic.

The `WP` docstring now says that `Prog` determines `Value`, `Pred` and `EPred`, and gives `EStateM ε σ` and the `Cmd` deep embedding of `tests/elab/vcgenImp.lean` as the two ends of the range of program types. `WPMonad.of_frameClosure` gains a paragraph on the frame obligation moving from the spec application site to the spec proof site. The import of `Std.Internal.Do.WP.Frame` in `RuleConstruction.lean` gains a comment, since the constant it supplies is built by name and no signature in that file mentions it.
Master carries PR 14777, which moved the tactic to `Lean.Elab.Tactic.VCGen`. The import of `Std.Internal.Do.WP.Frame` that this branch adds moves with `RuleConstruction.lean` to the new path.

The conflicts in `Std/Internal/Do/WP/{Basic,Frame}.lean` and `Lean/Elab/Tactic/VCGen/LatticeOp.lean` come from PR 14774 landing as a squash. Master's `src/Std/` is identical to the base of this branch, so the resolution keeps this branch's split for the two `Std` files and master's version of `LatticeOp.lean`.
This PR marks the import that `RuleConstruction.lean` needs for `WP.Frames.op_wp_upperAdjoint_le_wp` as a `meta import`, which states that the constant is needed at elaboration time only.

The tactic builds that constant by name with `mkAppOptM`, so no signature in the file mentions it. `meta import` says so in the syntax.
This PR rewrites the closing paragraph of the `WPMonad.of_frameClosure` docstring to state that every frame passes through the `wp` and that a caller of a spec picks a frame and applies the frame rule. It also shortens the deep-embedding paragraph of the `Std.Internal.Do.WP.Basic` module docstring to speak of `wp` and an operational semantics such as an omnisemantics.
@sgraf812
sgraf812 marked this pull request as ready for review August 13, 2026 15:06
@sgraf812
sgraf812 requested review from TwoFX and kim-em as code owners August 13, 2026 15:06
@sgraf812
sgraf812 enabled auto-merge August 13, 2026 15:09
@sgraf812
sgraf812 added this pull request to the merge queue Aug 13, 2026
Merged via the queue into master with commit 0bfd592 Aug 13, 2026
30 checks passed
@sgraf812
sgraf812 deleted the sg/wp-generic-split branch August 13, 2026 16:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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