refactor: replace the bespoke exception postcondition types with tuples - #14836
Merged
Conversation
|
Mathlib CI status (docs):
|
Collaborator
|
Reference manual CI status:
|
sgraf812
force-pushed
the
sg/epost-to-prod
branch
3 times, most recently
from
August 19, 2026 16:26
1916ec4 to
8269c29
Compare
This PR replaces the `EPost.Nil`/`EPost.Cons` exception postcondition types of `Std.WP` with `Unit` and `Prod`, and gives each base monad the exception postcondition it throws: `Except ε` carries `ε → Prop`, `Option` carries `Unit → Prop`, `Id` carries `Unit`, and a transformer stacks a product layer on the postcondition of the monad below it. The `EPost⟨…⟩` and `epost⟨…⟩` notations become `EStack⟨…⟩` and `estack⟨…⟩` over the tuple types, so `EStack⟨ε → Pred⟩` is `(ε → Pred) × EStackEnd` and `estack⟨E⟩` is `(E, ())`, where `EStackEnd` is a reducible abbreviation of `Unit` that closes a stack. `Prod` and `Unit` gain the `PartialOrder`, `CCPO` and `CompleteLattice` instances that `EPost.Cons` and `EPost.Nil` carried, transported from the `PProd` instances, together with the componentwise meet, supremum and bottom lemmas and the `PreservesSup (meet p)` instance a product lattice needs for its Heyting arrow. `pushExcept` and `pushOption`, which give a postcondition to the `Except` or `Option` value a transformer exposes when it runs, join `pushArg` in `Std.Internal.Order.PredTrans`. `vcgen` reads a component as `Prod.fst`/`Prod.snd` and closes the terminator with `Unit.unit_le`, matching it under reduction so that any name for `Unit` fires. A `CCPO` on a product is reachable both directly and through `instCCPOOfCompleteLattice`, and the two are defeq because the whole order hierarchy adds only `Prop` fields to `rel`. `vcgen` reduces a `⊥` exception postcondition through either, and `Prod.fst_bot` and `bot_apply` are stated at `CCPO` so they apply to both. A stack type prints back as `EStack⟨…⟩`, since `EStackEnd` names the terminator. A stack value prints as an ordinary tuple, since `()` carries no such name. Since a terminator is no longer appended by notation, `ExceptT ε Id` and `Except ε` are visibly distinct: their exception postconditions are `(ε → Prop) × Unit` and `ε → Prop`, isomorphic rather than equal.
sgraf812
force-pushed
the
sg/epost-to-prod
branch
from
August 19, 2026 16:50
8269c29 to
0c5885b
Compare
This PR keeps `vcgen` reducing a `⊥` exception postcondition to a `pre ⊑ ⊥` verification condition, with no change in behaviour. `replaceExceptPostFstBot?` now simplifies the entailment's right-hand side with a `Sym.simp` theorem set holding `Prod.fst_bot` and `Lean.Order.bot_apply`, and applies the resulting equation with `replaceTargetEq`. This replaces the hand-built proof term that folded the two lemmas over the excess arguments and extracted the `CCPO` instances from the `⊥` instance term. The helpers `prodCCPOComponents?` and `piCodomainCCPO?` go away with it. The `pre` method of the theorem set confines the traversal to the `Prod.fst`/`⊥` spine, so the state arguments are never visited.
This PR speeds up `vcgen` on programs that specify the exception postcondition as `⊥`, by reducing each such verification condition with a rule built once per goal shape. `mkExceptPostBotRule` builds the backward rule `pre ⊑ ⊥ → pre ⊑ (⊥ : eh × et).fst x₁ … xₙ`, holding `eh`, `et` and the `⊥` concrete and making the precondition and the excess arguments schematic. `Prod.fst_bot` and `Lean.Order.bot_apply` establish the equation the rule carries. `mkExceptPostBotRuleCached` keys it on the `Prod.fst eh et ⊥` prefix and the argument count, so `reduceExceptPostFst?` looks the rule up and applies it, instead of simplifying and assembling a proof term per goal.
Contributor
Author
|
!bench |
|
Benchmark results for b1d2f49 against 01fe110 are in. No significant results found. @sgraf812
Small changes (7✅, 5🟥)
|
…e ops This PR makes `vcgen` reduce a projected `⊥` or `⊤` exception postcondition through the generic lattice-split pipeline, and closes the `⊤` case outright. `LatticeOp.fst` and `LatticeOp.snd` register `Prod.fst`/`Prod.snd` as built-in lattice operators with the rewrites `Prod.fst_bot`/`Prod.fst_top`/`Prod.snd_bot`/`Prod.snd_top` and the pointwise `bot_apply`/`top_apply`; the last three product lemmas are new. `numConst := 3` holds the tuple operand concrete, since which rewrite fires depends on it. The `⊥` residual becomes the sole subgoal, the `⊤` residual closes with the `le_top` terminal. A new `LatticeOp.applies?` filter lets an operator decline a shape before rule construction; the projections decline every operand not headed by `⊥`/`⊤` (for example a schematic stack projection `E.fst s`), and `splitLatticeOp?` then falls through to the remaining dispatch. The bespoke `mkExceptPostBotRule`, its cache field and its cached wrapper are gone.
sgraf812
force-pushed
the
sg/epost-to-prod
branch
from
August 20, 2026 13:42
268b60e to
2414232
Compare
sgraf812
marked this pull request as ready for review
August 20, 2026 14:05
Contributor
Author
|
!bench |
|
Benchmark results for 0cbce06 against 01fe110 are in. No significant results found. @sgraf812
Small changes (11✅, 5🟥)
|
sgraf812
enabled auto-merge
August 20, 2026 14:36
# Conflicts: # src/Lean/Elab/Tactic/VCGen/FrameProc.lean
github-merge-queue
Bot
removed this pull request from the merge queue due to failed status checks
Aug 20, 2026
sgraf812
added a commit
to leanprover/reference-manual
that referenced
this pull request
Aug 21, 2026
The tuple refactor (leanprover/lean4#14836) replaces the bespoke exception postcondition types. In the vcgen documents, EPost.Nil becomes EStack⟨⟩, EPost.Nil.mk becomes (), and the Result monad carries a bare Error → Prop exception postcondition, so epost e replaces epost.head e and the head-projection step leaves the monotonicity proof. The push helpers for transformers are PredTrans.pushExceptT and PredTrans.pushOptionT. The EStack⟨…⟩ and estack⟨…⟩ notations get a syntax block in the exception postcondition section. The recorded Lake transcripts gain the new lint option --checks and the package configuration field checks. Verified with ./generate-html.sh on nightly-2026-08-21.
sgraf812
added a commit
to leanprover/reference-manual
that referenced
this pull request
Aug 21, 2026
The tuple refactor (leanprover/lean4#14836) replaces the bespoke exception postcondition types. EPost.Nil becomes EStack⟨⟩, EPost.Nil.mk becomes (), and the Result monad carries a bare Error → Prop exception postcondition, so epost e replaces epost.head e and the head-projection step leaves the monotonicity proof. The push helpers for transformers are PredTrans.pushExceptT and PredTrans.pushOptionT. The EStack⟨…⟩ and estack⟨…⟩ notations get a syntax block in the exception postcondition section. Verified with ./generate-html.sh on nightly-2026-08-21.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR replaces the exception postcondition types
EPost.NilandEPost.Conswith products. An exception postcondition stack is now(ε₁ → Pred) × (ε₂ → Pred) × EStack⟨⟩, so theProdAPI applies to it. The base monads carry bare postconditions:Except εusesε → Prop, andOptionusesUnit → Prop. The notationEStack⟨A, B⟩writes a stack type, andestack⟨e₁, e₂⟩writes a stack value. Both print back as written.vcgensplits⊥and⊤exception postconditions with the same cached backward rules as the other lattice connectives.