You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
chore: target nightly-2026-08-21 and port to exception stacks
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.
Copy file name to clipboardExpand all lines: Manual/VCGen.lean
+17-12Lines changed: 17 additions & 12 deletions
Original file line number
Diff line number
Diff line change
@@ -165,9 +165,14 @@ Since unit and pair types come with {name}`Assertion` instances, such exception
165
165
The {name}`WP` translation turns monad transformer stacks turn into exception postcondition stacks.
166
166
The notation `EStack⟨e₁, e₂, ...⟩` abbreviates the type of exception postcondition stack `e₁ × (e₂ × (... × Unit))`, and the notation `estack⟨v₁, v₂, ...⟩` builds a value `(v₁, v₂, ..., ())` of such a stack.
167
167
168
+
:::syntax term (title := "Exception Postcondition Stacks") (namespace := Std.WP)
168
169
```grammar
169
-
Insert this, Claude!
170
+
EStack⟨$_,*⟩
170
171
```
172
+
```grammar
173
+
estack⟨$_,*⟩
174
+
```
175
+
:::
171
176
172
177
{TODO}[I think the partial vs. total correctness discussion should maybe happen after we have actually introduced Triple? It discusses its syntax.]
173
178
@@ -209,15 +214,15 @@ The {name}`bind` operator composes predicate transformers.
209
214
210
215
{docstring Lean.Order.instMonadPredTrans}
211
216
212
-
The helper operators {name}`Lean.Order.pushArg`, {name}`PredTrans.pushExcept`, and {name}`PredTrans.pushOption` modify a predicate transformer by adding a standard side effect.
217
+
The helper operators {name}`Lean.Order.pushArg`, {name}`PredTrans.pushExceptT`, and {name}`PredTrans.pushOptionT` modify a predicate transformer by adding a standard side effect.
213
218
They are used to implement the {name}`WP` instances for transformers such as {name}`StateT`, {name}`ExceptT`, and {name}`OptionT`; they can also be used to implement monads that can be thought of in terms of one of these.
214
219
For example, {name}`Lean.Order.pushArg` is typically used for state monads, but can also be used to implement a reader monad's instance, treating the reader's value as read-only state.
215
220
216
221
{docstring Lean.Order.pushArg}
217
222
218
-
{docstring PredTrans.pushExcept}
223
+
{docstring PredTrans.pushExceptT}
219
224
220
-
{docstring PredTrans.pushOption}
225
+
{docstring PredTrans.pushOptionT}
221
226
222
227
### Weakest Preconditions
223
228
@@ -291,7 +296,7 @@ The {name}`WP` interpretation of {name}`Identity` is a plain definition marked {
291
296
{TODO}[It is a wart of `vcgen` that we cannot declare the WP instancebelow.I'llthinkaboutfixingitbycanonicalizing `WPMonad.toWP`tothe `WP`instance,butnotintimefor4.35.Let'smaybeleavean "underconstruction"signforthereader.]
292
297
```lean
293
298
@[instance_reducible] defIdentity.wpInst :
294
-
WP (Identity α) α PropEPost.Nilwhere
299
+
WP (Identity α) α PropEStack⟨⟩where
295
300
wpTrans x := ⟨fun post _ => post x.run⟩
296
301
wp_trans_monotone x := fun _ _ _ _ _ hpost => hpost x.run
297
302
@@ -303,7 +308,7 @@ This interpretation alone suffices to state weakest preconditions and to prove a
Copy file name to clipboardExpand all lines: Tutorial/VCGen.lean
+8-9Lines changed: 8 additions & 9 deletions
Original file line number
Diff line number
Diff line change
@@ -768,7 +768,7 @@ variable {m : Type u → Type v} [Monad m] {Pred EPred : Type} [Assertion Pred]
768
768
```
769
769
770
770
A {lean}`StateT σ` layer turns the assertion type `Pred` into `σ → Pred` and leaves the exception postcondition type unchanged.
771
-
An {lean}`ExceptT ε` layer leaves the assertion type unchanged and turns the exception postcondition type `EPred` into {lean}`EPost.Cons (ε → Pred) EPred`, adding one exception branch of type `ε → Pred`.
771
+
An {lean}`ExceptT ε` layer leaves the assertion type unchanged and turns the exception postcondition type `EPred` into {lean}`(ε → Pred) × EPred`, adding one exception branch of type `ε → Pred`.
772
772
The {name}`WP` instancefor {lean}`EStateM ε σ` uses assertions of type `σ → Prop` and exception postconditions of type `ε → σ → Prop`, mirroring the single exception branch of the equivalent transformer stack {lean}`ExceptT ε (StateM σ)`.
773
773
:::
774
774
@@ -836,8 +836,8 @@ Supporting this monad in {tactic}`vcgen` is a matter of:
836
836
universe u v
837
837
variable {α : Type u} {v : α} {e : Error}
838
838
```
839
-
The {name}`WPMonad` instancefor {name}`Result` picks the assertion type {lean}`Prop` because there are no state-like effects, and the exception postcondition type {lean}`EPost⟨Error → Prop⟩` because there is a single exception of type {lean}`Error`.
840
-
Its {name}`WP` interpretation translates a program in {lean}`Result α` to a predicate transformer in {lean}`PredTrans PropEPost⟨Error → Prop⟩ α`.
839
+
The {name}`WPMonad` instancefor {name}`Result` picks the assertion type {lean}`Prop` because there are no state-like effects, and the exception postcondition type {lean}`Error → Prop` because there is a single exception of type {lean}`Error`.
840
+
Its {name}`WP` interpretation translates a program in {lean}`Result α` to a predicate transformer in {lean}`PredTrans Prop(Error → Prop) α`.
841
841
That is, a function mapping a postcondition and an exception postcondition to the weakest precondition.
842
842
Each case of {name}`Result` determines the precondition directly:
843
843
* {lean}`Result.ok v` yields the success postcondition at {lean}`v`.
@@ -850,16 +850,15 @@ For {name}`WPMonad.bind_le_wp_bind`, a case split on the program exposes the {ke
850
850
::::
851
851
```lean
852
852
instanceResult.instWPMonad :
853
-
WPMonad Result PropEPost⟨Error → Prop⟩where
853
+
WPMonad Result Prop(Error → Prop)where
854
854
toWP α := {
855
855
wpTrans x := ⟨fun post epost =>
856
856
match x with
857
857
| .ok v => post v
858
-
| .fail e => epost.head e
858
+
| .fail e => epost e
859
859
| .div => False⟩
860
860
wp_trans_monotone x := by
861
861
intro post post' epost epost' hepost hpost
862
-
have hhead := EPost.Cons.le_head hepost
863
862
cases x <;> simp_all [PartialOrder.rel]
864
863
}
865
864
pure_le_wp_pure x post epost := PartialOrder.rel_refl
@@ -873,7 +872,7 @@ Finally, we also prove an adequacy lemma similar to {name}`Except.of_eq_wp` for
873
872
```lean
874
873
theoremResult.of_eq_wp {α} {x prog : Result α}
875
874
(h : prog = x) (P : Result α → Prop)
876
-
(hwp : wp prog (fun a => P (.ok a)) epost⟨fun e => P (.fail e)⟩) :
875
+
(hwp : wp prog (fun a => P (.ok a)) (fun e => P (.fail e))) :
877
876
P x := by
878
877
subst h
879
878
match prog with
@@ -911,8 +910,8 @@ There are two relevant specification lemmas to register:
0 commit comments