Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
111 commits
Select commit Hold shift + click to select a range
77cc99b
Start implementing iinv: tactic for opening invariants
alvinylt Jun 16, 2026
3f62da2
Introduce type class `ElimInv`
alvinylt Jun 16, 2026
f70f987
`iInvCore`: `ElimInv` type class synthesis
alvinylt Jun 16, 2026
7eeb1f2
Some progress with iInvCore
alvinylt Jun 16, 2026
cebd144
Add accessor and type class IntoAcc
alvinylt Jun 16, 2026
dc31ce9
Add type class ElimAcc
alvinylt Jun 16, 2026
d246841
Fix type class definitions: `mγ` and `mPclose` involve `Option` with …
alvinylt Jun 16, 2026
648635f
Add two ElimInv type class instances: `elim_inv_acc_without_close`, `…
alvinylt Jun 16, 2026
e0ebd56
Adjust `outParam` config
alvinylt Jun 16, 2026
3d39bac
Fix `outParam` config and types of mvars
alvinylt Jun 16, 2026
81cfee8
Introduce type class `IntoInv`
alvinylt Jun 18, 2026
a25e4b5
Port `into_inv_inv` and `into_acc_inv` definitions in Invariants.lean
alvinylt Jun 18, 2026
bdbe46b
Port `into_inv_na` and `into_acc_na` definitions in NaInvariants.lean
alvinylt Jun 18, 2026
c756df0
Port `into_inv_cinv` and `into_acc_cinv` definitions in CInvariants.lean
alvinylt Jun 18, 2026
1554adc
Introduce `-∗?` in BIBase.lean, optional wand premise
alvinylt Jun 18, 2026
d52087c
Port `elim_acc_bupd` and `elim_acc_fupd` definitions in InstancesUpda…
alvinylt Jun 18, 2026
f4ab6f9
Follow naming conventions for type class instances
alvinylt Jun 18, 2026
6f3b5e1
Merge remote-tracking branch 'upstream' into iInv
alvinylt Jun 19, 2026
4fe12c8
Comment out some type class instances for the moment
alvinylt Jun 21, 2026
6932d00
Towards basic tactic `iinv ... as ...` with `intoAcc_inv` and `elimAc…
alvinylt Jun 21, 2026
3135667
Focus on the basic functionalities of `iInvCore`
alvinylt Jun 21, 2026
a3879b1
Add test proofs for `iinv`
alvinylt Jun 21, 2026
412fd21
Modify `iSolveSideCondition` to use `try` to avoid failure
alvinylt Jun 21, 2026
52a0c49
`iSolveSideCondition`: use `observing?` instead of `try`
alvinylt Jun 22, 2026
ac9f040
Fix `iSolveSideCondition`: return singleton containing original goal …
alvinylt Jun 22, 2026
fb1213c
Port `wandM_sound`
alvinylt Jun 22, 2026
35407d5
Introduce assumptions into `tac_inv_elim`
alvinylt Jun 22, 2026
2c889e6
Apply `simp` for `wandM`
alvinylt Jun 22, 2026
6a87583
Test `iinv` with invalid invariant: `ElimInv` synthesis error
alvinylt Jun 22, 2026
56b8071
`iinv`: starting implementing `as` clause (`hclose`)
alvinylt Jun 22, 2026
bb64fd0
Towards implement `hclose` in `iInvCore`
alvinylt Jun 22, 2026
44d9849
Add a separate Boolean argument `close` to `ElimInv` so that the tact…
alvinylt Jun 23, 2026
ce49b38
Towards proving `tac_inv_elim`
alvinylt Jun 23, 2026
3bd0845
Further towards proving `tac_inv_elim`
alvinylt Jun 23, 2026
d12405c
Implement the metaprogramming part for `hclose`
alvinylt Jun 23, 2026
bac6132
Generalise `hclose` to be any intro patterns instead of an ident
alvinylt Jun 23, 2026
6a0d7e7
Start implementing selection pattern handling
alvinylt Jun 23, 2026
f93612e
Fix: specialisation pattern rather than selection pattern
alvinylt Jun 23, 2026
5e6f8ad
Parse `specPats` as a list of specialisation patterns
alvinylt Jun 23, 2026
332c25b
Use `iSpecializeCore` for handling `with ...`
alvinylt Jun 24, 2026
5f78067
Uncomment `intoAcc_cinv`, add two relevant tests
alvinylt Jun 24, 2026
58f83ec
Uncomment `intoAcc_na`, introduce relevant tests
alvinylt Jun 24, 2026
5760e93
Bug fix: `hyps'` -> `hyps''`
alvinylt Jun 24, 2026
93d6547
More tests
alvinylt Jun 24, 2026
02222dd
Another test with NaInvariants
alvinylt Jun 24, 2026
6330fc4
Prove `tac_inv_elim`
alvinylt Jun 24, 2026
1b6e237
Towards implementing default handling of specialisation pattern
alvinylt Jun 24, 2026
f3a6264
Fix for consistency
alvinylt Jun 24, 2026
16a0770
Add tests, including those showing an issue of wrong hypothesis choic…
alvinylt Jun 24, 2026
8b2c394
Special case to handle `Pin` being `True`
alvinylt Jun 24, 2026
f2a6e3b
Reorganise `iinv` tests and minor fixes
alvinylt Jun 24, 2026
f242b49
Minor fix: `E` in `elimAcc_fupd`
alvinylt Jun 24, 2026
692920b
`tac_inv_elim`: formatting
alvinylt Jun 25, 2026
0ac6f0d
Update comment
alvinylt Jun 25, 2026
c23adeb
New function `findInvariantWithNamespace` to find invariant using nam…
alvinylt Jun 25, 2026
4ad4d8a
Implement `iinv N ...` where `N` is a `Namespace` value
alvinylt Jun 25, 2026
d4c76a1
Minor formatting
alvinylt Jun 25, 2026
3bc2547
Add `elimAcc_wp_atomic` and `elimAcc_wp_nonatomic`
alvinylt Jun 25, 2026
5840eca
Adjust `iinv` syntax for consistency with `imod` and `ihave`
alvinylt Jun 25, 2026
5f3f0c4
Add missing `cotGt` in `iinv` syntax
alvinylt Jun 25, 2026
499886a
Modify `iSolveSidecondition` to apply `and_intros` and then to try `t…
alvinylt Jun 25, 2026
a25c57f
Uncomment `elim_acc_bupd`, test `iinv` with `elimAcc_wp_atomic`
alvinylt Jun 25, 2026
e70d793
Remove the requirement in `FrameResult.finishClose` that progress has…
alvinylt Jun 25, 2026
7d818c3
Towards restructuring `iInvCore` and `tac_inv_elim` to use `iCasesCor…
alvinylt Jun 25, 2026
db58a89
New proof for `tac_inv_elim`, adjust `iInvCore`
alvinylt Jun 25, 2026
f8b2466
Formatting: monadic bind
alvinylt Jun 25, 2026
8e106bf
Minor formatting
alvinylt Jun 25, 2026
e4a39eb
Avoid using `Option.getD` in `elimInv_acc_with_close`, force simplifi…
alvinylt Jun 25, 2026
a1d2566
`findInvariantWithNamespace`: minor simplifications
alvinylt Jun 26, 2026
03ac6bc
Add docstring for `iinv`
alvinylt Jun 26, 2026
a1a480c
More precise error message when `Namespace` value does not correspond…
alvinylt Jun 26, 2026
626e9fa
Add description of `iinv` in `tactics.md`
alvinylt Jun 26, 2026
633bb64
Update `Porting.lean`
alvinylt Jun 26, 2026
4453445
Move the two type classes to a separate file (`InstancesIris.lean`) s…
alvinylt Jun 26, 2026
6b22ce3
Use bare pattern matching in `ElimInv` to avoid unnecessary `emp`
alvinylt Jun 26, 2026
568cba8
Finish proofs for `elimInv_acc_without_close` and `elimInv_acc_with_c…
alvinylt Jun 26, 2026
75e3986
Update `tac_inv_elim` and `iInvCore` according to the updated definit…
alvinylt Jun 26, 2026
49f28b1
Complete proof for `intoAcc_inv`
alvinylt Jun 26, 2026
0cfec2f
Complete proofs for `intoAcc_cinv` and `intoAcc_na`
alvinylt Jun 26, 2026
fb84653
Complete proof for `elimAcc_wp_atomic` and `elimAcc_wp_nonatomic`
alvinylt Jun 26, 2026
b5384ff
Finish proof for `elimAcc_fupd`
alvinylt Jun 26, 2026
47f09de
Finish proof for `elimAcc_bupd`
alvinylt Jun 26, 2026
c1606d3
Merge remote-tracking branch 'upstream/master' into iInv
alvinylt Jun 26, 2026
aa39637
Update `intoAcc_cinv` in response to changes
alvinylt Jun 26, 2026
77d33b9
Rename hypotheses in `WeakestPre.lean` for consistency with the Rocq …
alvinylt Jun 26, 2026
f2b611f
`rocq_alias` typo fix: `wandM_sound` -> `bi.wandM_sound`
alvinylt Jun 26, 2026
3f488af
Port `from_wand_wandM` and `into_wand_wandM`
alvinylt Jun 26, 2026
c3e3f92
Attempt to resolve circular depedency between `ProofMode.Tactics` and…
alvinylt Jun 26, 2026
9146b46
Separate `AsEmpValid` from the rest in `InstancesInit.lean`, dependen…
alvinylt Jun 26, 2026
d697447
Define `pmReduce` so that there is no need for `addBIGoalRunTactic` or
alvinylt Jun 27, 2026
7146caf
Simplify type class instance definitions with the use of `Option.getD`
alvinylt Jun 27, 2026
555e3be
Replace some `simp` usage with `dsimp`
alvinylt Jun 27, 2026
a38f028
Condense `pmReduce`
alvinylt Jun 27, 2026
2db2ae8
Simplify `pmReduce`
alvinylt Jul 1, 2026
0592d7d
Code refactoring: moving theorem to `public section`
alvinylt Jul 3, 2026
526d27c
No need for separate file `InstancesInit.lean`
alvinylt Jul 14, 2026
6e05f4e
Merge remote-tracking branch 'upstream/master' into iInv
alvinylt Jul 22, 2026
e73137b
Function renaming `pmReduce` -> `reduceWandM`, set as private
alvinylt Jul 22, 2026
caacc54
`iSolveSidecondition`: use `simp [*]` instead
alvinylt Jul 22, 2026
4fc2ef8
Remove misleading description of the tactic
alvinylt Jul 22, 2026
42a2ad7
Typo fix
alvinylt Jul 22, 2026
b90c8b6
Implement `Hyps.findM?`, use it for `iinv`
alvinylt Jul 22, 2026
54596a4
Revert "`iSolveSidecondition`: use `simp [*]` instead"
alvinylt Jul 22, 2026
5578728
`iSolveSidecondition`: use `simp [*]` instead
alvinylt Jul 22, 2026
88e3436
Use `first | trivial | simp [*]` instead of `simp [*]`
alvinylt Jul 22, 2026
fb3b855
Make type class premises implicit
alvinylt Jul 23, 2026
956c784
Make more type classes implicit
alvinylt Jul 23, 2026
a67f1dc
Replace `outParam <| uncheckedInParam` with `semiOutParamIPM`
alvinylt Jul 23, 2026
719aaa2
Replace `simp [*]` with `simp [*] <;> done`
alvinylt Jul 23, 2026
3c4721e
`iSolveSidecondition` update
alvinylt Jul 23, 2026
45bdcb5
Replace `>>=` with `let ...`
alvinylt Jul 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Iris/Iris/BI/BIBase.lean
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ syntax "⌜" term "⌝" : term
syntax:35 term:36 " ∗ " term:35 : term
/-- Separating implication. -/
syntax:25 term:26 " -∗ " term:25 : term
/-- Separating implication with an optional wand premise. -/
syntax:25 term:26 " -∗? " term:25 : term
/-- Persistency modality. `persistently` is a primitive of BI. -/
syntax:max "<pers> " term:40 : term
/-- Later modality. `later` is a primitive of BI. -/
Expand Down Expand Up @@ -163,6 +165,18 @@ delab_rule iff
delab_rule wandIff
| `($_ $P $Q) => do ``(iprop($(← unpackIprop P) ∗-∗ $(← unpackIprop Q)))

@[simp, rocq_alias bi_wandM]
def wandM [BIBase PROP] (mP : Option PROP) (Q : PROP) : PROP :=
match mP with
| none => Q
| some P => iprop(P -∗ Q)

macro_rules
| `(iprop($mP -∗? $Q)) => ``(wandM $mP iprop($Q))

delab_rule wandM
| `($_ $mP $Q) => do ``(iprop($mP -∗? $(← unpackIprop Q)))

/-- Affine modality.
```
def affinely (P) := emp ∧ P
Expand Down
6 changes: 6 additions & 0 deletions Iris/Iris/BI/DerivedLaws.lean
Original file line number Diff line number Diff line change
Expand Up @@ -1041,6 +1041,12 @@ theorem emp_or [BI PROP] {P : PROP} [Affine P] : emp ∨ P ⊣⊢ emp := ⟨or_e
theorem emp_wand [BI PROP] {P : PROP} : (emp -∗ P) ⊣⊢ P :=
⟨emp_sep.mpr.trans wand_elim_right, wand_intro_left emp_sep.mp⟩

@[rocq_alias bi.wandM_sound]
theorem wandM_sound [BI PROP] {mP : Option PROP} {Q : PROP} :
(mP -∗? Q) ⊣⊢ (mP.getD emp -∗ Q) := by
cases mP <;> simp [BIBase.wandM]
exact emp_wand.symm

@[rocq_alias bi.or_emp]
theorem or_emp [BI PROP] {P : PROP} [Affine P] : P ∨ emp ⊣⊢ emp := or_comm.trans emp_or

Expand Down
2 changes: 1 addition & 1 deletion Iris/Iris/HeapLang/ProofMode.lean
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ public meta def iWpValueHead {u}
let p' : Q(Bool) ← mkFreshExprMVarQ q(Bool)
let A' : Q(IProp $GF) ← mkFreshExprMVarQ q(IProp $GF)
let Q' : Q(IProp $GF) ← mkFreshExprMVarQ q(IProp $GF)
if let .some _ ← ProofModeM.trySynthInstanceQ q(ElimModal $c false $p' iprop(|={$E}=> $goal) $A' $goal $Q') then
if let .some _ ← ProofModeM.trySynthInstanceQ q(ElimModal $c false .out $p' iprop(|={$E}=> $goal) $A' $goal $Q') then
if let some _ ← try? <| iSolveSidecondition c then
let pf ← addBIGoal hyps q($goal)
return some q(tac_wp_value_nofupd (s:=$s) (E:=$E) $pf)
Expand Down
23 changes: 22 additions & 1 deletion Iris/Iris/Instances/Lib/CInvariants.lean
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public import Iris.Std.List

namespace Iris

open BI CMRA OFE Iris Std LawfulSet Excl COFE
open BI CMRA OFE Iris Std LawfulSet Excl COFE ProofMode

/-! # Cancelable Invariants -/

Expand Down Expand Up @@ -289,6 +289,27 @@ theorem cancel (E : CoPset) {N : Namespace} {γ : GName} {P : IProp GF} (Hsub :
imodintro
iexact HP

@[rocq_alias into_inv_cinv]
instance intoInv_cinv (N : Namespace) (γ : GName) (P : IProp GF) :
IntoInv (cinv N γ P) N := {}

set_option synthInstance.checkSynthOrder false in
@[rocq_alias into_acc_cinv]
instance intoAcc_cinv (E : CoPset) (N : Namespace) (γ : GName) (P : IProp GF) (p : Qp) :
IntoAcc (X := Unit) (cinv N γ P) (↑N ⊆ E) (own γ p) (fupd E (E \ ↑N)) (fupd (E \ ↑N) E)
(fun _ => iprop(▷ P ∗ own γ p)) (fun _ => iprop(▷ P)) (λ _ => none) where
into_acc := by
dsimp only [accessor, Option.getD]
iintro %x #Hinv Hown
imod acc x $$ Hinv Hown with ⟨HP, Hγ, Hcl⟩
imodintro
iexists ()
isplitl [HP Hγ]
· iframe
· iintro HP
iapply (BIFUpdate.mono true_emp.mp)
iapply Hcl $$ HP

end CancelableInvariant
end Iris
end
8 changes: 4 additions & 4 deletions Iris/Iris/Instances/Lib/FUpd.lean
Original file line number Diff line number Diff line change
Expand Up @@ -379,8 +379,8 @@ instance isExcept0_fupd_finally (E : CoPset) (P : IProp GF) : IsExcept0 iprop(|=
iapply except0_mono fupd_intro $$ H

@[rocq_alias elim_modal_bupd_fupd_finally]
instance elimModal_bupd_fupd_finally p (E : CoPset) (P Q : IProp GF) :
ElimModal True p false iprop(|==> P) P iprop(|={E|}=> Q) iprop(|={E|}=> Q) where
instance elimModal_bupd_fupd_finally p io (E : CoPset) (P Q : IProp GF) :
ElimModal True p io false iprop(|==> P) P iprop(|={E|}=> Q) iprop(|={E|}=> Q) where
elim_modal _ := by
iintro ⟨H1, H2⟩
iapply fupd_fupd_finally E E
Expand All @@ -390,8 +390,8 @@ instance elimModal_bupd_fupd_finally p (E : CoPset) (P Q : IProp GF) :
iapply H2 $$ H1

@[rocq_alias elim_modal_fupd_fupd_finally]
instance elimModal_fupd_fupd_finally p (E1 E2 : CoPset) (P Q : IProp GF) :
ElimModal True p false iprop(|={E1,E2}=> P) P iprop(|={E1|}=> Q) iprop(|={E2|}=> Q) where
instance elimModal_fupd_fupd_finally p io (E1 E2 : CoPset) (P Q : IProp GF) :
ElimModal True p io false iprop(|={E1,E2}=> P) P iprop(|={E1|}=> Q) iprop(|={E2|}=> Q) where
elim_modal _ := by
iintro ⟨H1, H2⟩
iapply fupd_fupd_finally E1 E2
Expand Down
21 changes: 20 additions & 1 deletion Iris/Iris/Instances/Lib/Invariants.lean
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,26 @@ theorem except_0_inv (N : Namespace) (P : IProp GF) : ⊢ ◇ inv N P -∗ inv N
instance is_except_0_inv (N : Namespace) (P : IProp GF) : IsExcept0 (inv N P) where
is_except0 := by iintro H; iapply except_0_inv $$ H

-- TODO: into_inv_inv, into_acc_inv
@[rocq_alias into_inv_inv]
instance intoInv_inv (N : Namespace) (P : IProp GF) : IntoInv (inv N P) N := {}

set_option synthInstance.checkSynthOrder false in
@[rocq_alias into_acc_inv]
instance intoAcc_inv (N : Namespace) (P : IProp GF) E :
IntoAcc (X := Unit) (inv N P) (↑N ⊆ E) iprop(True) (fupd E (E \ ↑N)) (fupd (E \ ↑N) E)
(λ _ => iprop(▷ P)) (λ _ => iprop(▷ P)) (λ _ => none) where
into_acc := by
dsimp only [inv, accessor, Option.getD]
iintro %x #Hinv -
imod Hinv $$ %E [] with ⟨HP, Hclose⟩
· itrivial
· iexists ()
imodintro
isplitl [HP]
· iassumption
· iintro HP
iapply (BIFUpdate.mono true_emp.mp)
iapply Hclose $$ HP

end Instances

Expand Down
4 changes: 2 additions & 2 deletions Iris/Iris/Instances/Lib/LaterCredits.lean
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ open ProofMode
variable {GF : BundledGFunctors} {hlc : HasLC} [LcGS hlc GF]

@[rocq_alias le_upd.elim_bupd_le_upd]
instance {P : IProp GF} : ElimModal True p false (bupd P) P (le_upd Q) (le_upd Q) where
instance {P Q : IProp GF} : ElimModal True p io false (bupd P) P (le_upd Q) (le_upd Q) where
elim_modal := by
cases p <;> (dsimp; intro _)
· iintro ⟨H1, H2⟩
Expand Down Expand Up @@ -466,7 +466,7 @@ instance {P : IProp GF} : FromModal True modality_id (le_upd P) (le_upd P) P whe
iapply le_upd_intro

@[rocq_alias le_upd.elim_modal_le_upd]
instance {P : IProp GF} : ElimModal True p false (le_upd P) P (le_upd Q) (le_upd Q) where
instance {P Q : IProp GF} : ElimModal True p io false (le_upd P) P (le_upd Q) (le_upd Q) where
elim_modal := by
intro _
cases p <;> dsimp
Expand Down
20 changes: 19 additions & 1 deletion Iris/Iris/Instances/Lib/NaInvariants.lean
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public import Iris.Std.CoPset

namespace Iris

open BI CMRA OFE Iris Std LawfulSet DisjointLeibnizSet COFE
open BI CMRA OFE Iris Std LawfulSet DisjointLeibnizSet COFE ProofMode

abbrev NaInvF : OFunctorPre :=
ProdOF (constOF CoPsetDisjL) (constOF (DisjointLeibnizSet PosSet))
Expand Down Expand Up @@ -221,6 +221,24 @@ nonrec theorem inv_acc {p : NaInvPoolName} {E F : CoPset} {N : Namespace} {P : I
icases Hbad with %Hbad
exact Hbad i ⟨mem_singleton.mpr rfl, mem_singleton.mpr rfl⟩ |>.elim

@[rocq_alias into_inv_na]
instance intoInv_na (N : Namespace) (P : IProp GF) :
IntoInv (inv p N P) N := {}

set_option synthInstance.checkSynthOrder false in
@[rocq_alias into_acc_na]
instance intoAcc_na (p : NaInvPoolName) (E F : CoPset) (N : Namespace) (P : IProp GF) :
IntoAcc (X := Unit) (inv p N P) (↑N ⊆ E ∧ ↑N ⊆ F) (own p F) (fupd E E) (fupd E E)
(fun _ => iprop(▷ P ∗ own p (F \ ↑N))) (fun _ => iprop(▷ P ∗ own p (F \ ↑N)))
(λ _ => some (own p F)) where
into_acc := by
dsimp only [accessor, Option.getD]
intro ⟨hE, hF⟩
iintro #Hinv Hown
imod inv_acc hE hF $$ Hinv Hown with ⟨_, Hown, _⟩
iexists ()
iframe

end NonAtomicInvariant
end Iris
end
51 changes: 44 additions & 7 deletions Iris/Iris/ProgramLogic/WeakestPre.lean
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@ public import Iris.Algebra
public import Iris.Instances.Lib.FUpd
public import Iris.BI
public import Iris.BI.WeakestPre
public import Iris.BI.DerivedLaws
public import Iris.ProofMode
public import Iris.ProgramLogic.Language
public import Iris.Std.CoPset

namespace Iris

open ProgramLogic Language.Notation Std
open ProgramLogic Language.Notation Std Iris.BI

@[expose] public section

Expand Down Expand Up @@ -638,7 +639,7 @@ instance isExcept0Wp : IsExcept0 (WP e @ s ; E {{ Φ }}) where
-- this should have higher priority than elimModalFupdWpAtomic
@[rocq_alias elim_modal_fupd_wp]
instance (priority := default + 10) elimModalFupdWp p :
ElimModal True p false iprop(|={E}=> P) P (WP e @ s ; E {{ Φ }}) (WP e @ s ; E {{ Φ }}) where
ElimModal True p io false iprop(|={E}=> P) P (WP e @ s ; E {{ Φ }}) (WP e @ s ; E {{ Φ }}) where
elim_modal := by
iintro %_ ⟨H, G⟩
icases BI.intuitionisticallyIf_elim $$ H with H
Expand All @@ -648,11 +649,11 @@ instance (priority := default + 10) elimModalFupdWp p :

@[rocq_alias elim_modal_bupd_wp]
instance elimModalBupdWp p :
ElimModal True p false iprop(|==> P) P (WP e @ s ; E {{ Φ }}) (WP e @ s ; E {{ Φ }}) where
ElimModal True p io false iprop(|==> P) P (WP e @ s ; E {{ Φ }}) (WP e @ s ; E {{ Φ }}) where
elim_modal := by
rintro ⟨⟩
refine BI.sep_mono (BI.intuitionisticallyIf_mono (BIUpdateFUpdate.fupd_of_bupd (E := E))) .rfl |>.trans ?_
apply elimModalFupdWp _ |>.elim_modal ⟨⟩
exact elimModalFupdWp _ |>.elim_modal ⟨⟩ (io := io)

/-- Error message instance for non-mask-changing view shifts. Also uses a slightly
different error: we cannot apply `fupd_mask_subseteq` if `e` is not atomic, so
Expand All @@ -661,12 +662,12 @@ we tell the user to first add a leading `fupd` and then change the mask of that.
instance elimModalFupdWp_wrongMask :
ElimModal (PMError "Goal and eliminated modality must have the same mask.
Use `iapply fupd_wp; imod (fupd_mask_subseteq E₂)` to adjust the mask of your goal to `E₂`")
p false iprop(|={E₂}=> P) iprop(False) (WP e @ s ; E₁ {{ Φ }}) iprop(False) where
p io false iprop(|={E₂}=> P) iprop(False) (WP e @ s ; E₁ {{ Φ }}) iprop(False) where
elim_modal := nofun

@[rocq_alias elim_modal_fupd_wp_atomic]
instance elimModalFupdWpAtomic :
ElimModal (Language.Atomic ↑s e) p false iprop(|={E₁,E₂}=> P) P (WP e @ s ; E₁ {{ Φ }}) (WP e @ s ; E₂ {{ v, |={E₂,E₁}=> Φ v}}) where
ElimModal (Language.Atomic ↑s e) p io false iprop(|={E₁,E₂}=> P) P (WP e @ s ; E₁ {{ Φ }}) (WP e @ s ; E₂ {{ v, |={E₂,E₁}=> Φ v}}) where
elim_modal := by
rintro atomic; iintro ⟨H, G⟩
icases BI.intuitionisticallyIf_elim $$ H with H
Expand All @@ -678,7 +679,43 @@ instance elimModalFupdWpAtomic :
instance elimModalFupdWpAtomic_wrongMask :
ElimModal (PMError "Goal and eliminated modality must have the same mask.
Use `iapply fupd_wp; imod (fupd_mask_subseteq E₂)` to adjust the mask of your goal to `E₂`")
p false iprop(|={E₁,E₂}=> P) iprop(False) (WP e @ s ; E₁ {{ Φ }}) iprop(False) where
p io false iprop(|={E₁,E₂}=> P) iprop(False) (WP e @ s ; E₁ {{ Φ }}) iprop(False) where
elim_modal := nofun

@[rocq_alias elim_acc_wp_atomic]
instance (priority := low) elimAcc_wp_atomic {X} (E₁ E₂ : CoPset) α β (γ : X → Option (IProp GF)) :
ElimAcc (Language.Atomic ↑s e) (fupd E₁ E₂) (fupd E₂ E₁) α β γ
(WP e @ s ; E₁ {{ Φ }})
(fun x => WP e @ s ; E₂ {{ v, |={E₂}=> β x ∗ (γ x -∗? Φ v) }}) where
elim_acc := by
dsimp only [accessor, BIBase.wandM, Option.getD]
iintro %atomic Hinner >⟨%x, Hα, Hclose⟩
iapply wp_wand $$ [Hinner Hα]
· iapply Hinner $$ Hα
· iintro %v >⟨Hβ, HΦ⟩
ispecialize Hclose $$ Hβ
imod Hclose
imodintro
cases (γ x) with
| none => iexact HΦ
| some P => iapply HΦ $$ Hclose

@[rocq_alias elim_acc_wp_nonatomic]
instance elimAcc_wp_nonatomic {X} E (α β : X → IProp GF) (γ : X → Option (IProp GF)) :
ElimAcc True (fupd E E) (fupd E E) α β γ (WP e @ s ; E {{ Φ }})
(fun x => WP e @ s ; E {{ v, |={E}=> β x ∗ (γ x -∗? Φ v) }}) where
elim_acc := by
dsimp only [accessor, BIBase.wandM, Option.getD]
iintro %_ Hinner >⟨%x, Hα, Hclose⟩
iapply wp_fupd
iapply wp_wand $$ [Hinner Hα]
· iapply Hinner $$ Hα
· iintro %v >⟨Hβ, HΦ⟩
ispecialize Hclose $$ Hβ
imod Hclose
imodintro
cases (γ x) with
| none => iexact HΦ
| some P => iapply HΦ $$ Hclose

end ProofModeClasses
38 changes: 36 additions & 2 deletions Iris/Iris/ProofMode/Classes.lean
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module
public import Iris.BI
public meta import Iris.ProofMode.SynthInstance
public import Iris.ProofMode.Modalities
public import Iris.Std.Namespaces

@[expose] public section

Expand Down Expand Up @@ -205,8 +206,9 @@ export FromModal (from_modal)

/-- `ElimModal` turns `□?p P` into `□?p' P'` and `Q` into `Q'` under condition `φ`. -/
@[ipm_class, rocq_alias ElimModal]
class ElimModal {PROP} [BI PROP] (φ : outParam $ Prop) (p : Bool) (p' : outParam $ Bool) (P : PROP)
(P' : outParam $ PROP) (Q : PROP) (Q' : outParam $ PROP) where
class ElimModal {PROP} [BI PROP] (φ : outParam $ Prop) (p : Bool) (io : InOut)
(p' : semiOutParamIPM io Bool) (P : PROP)
(P' : semiOutParamIPM io PROP) (Q : PROP) (Q' : outParam $ PROP) where
elim_modal : φ → □?p P ∗ (□?p' P' -∗ Q') ⊢ Q
export ElimModal (elim_modal)

Expand Down Expand Up @@ -249,6 +251,38 @@ class CombineSepGives [BI PROP] (P Q : PROP) (R : outParam PROP) where
combine_sep_gives : P ∗ Q ⊢ <pers> R
export CombineSepGives (combine_sep_gives)

@[ipm_class, rocq_alias IntoInv]
class IntoInv [BI PROP] (P : PROP) (N : Namespace)

@[rocq_alias accessor]
def accessor [BI PROP] {X : Type} (M1 M2 : PROP → PROP) (α β : X → PROP)
(mγ : X → Option PROP) : PROP :=
M1 iprop(∃ x, α x ∗ (β x -∗ M2 (mγ x |>.getD emp)))

@[ipm_class, rocq_alias ElimAcc]
class ElimAcc [BI PROP] {X : Type} (ϕ : outParam Prop) (M1 M2 : PROP → PROP)
(α β : X → PROP) (mγ : X → Option PROP) (Q : PROP) (Q' : outParam <| X → PROP) where
elim_acc : ϕ → ((∀ x, α x -∗ Q' x) -∗ accessor M1 M2 α β mγ -∗ Q)

@[ipm_class, rocq_alias IntoAcc]
class IntoAcc [BI PROP] {X : outParam Type} (Pacc : PROP)
(ϕ : outParam Prop) (Pin : outParam <| PROP)
(M1 M2 : outParam <| PROP → PROP) (α β : outParam <| X → PROP)
(mγ : outParam <| X → Option PROP) where
into_acc : ϕ → Pacc -∗ Pin -∗ accessor M1 M2 α β mγ

set_option synthInstance.checkSynthOrder false in
/-- The type class used for the `iinv` tactic. -/
@[ipm_class, rocq_alias ElimInv]
class ElimInv [BI PROP] (φ : outParam Prop) (X : outParam Type)
(Pinv : PROP) (Pin : outParam PROP) (Pout : outParam <| X → PROP)
(close : Bool) (mPclose : outParam <| Option <| X → PROP)
(Q : PROP) (Q' : outParam <| X → PROP) where
elim_inv : φ → Pinv ∗ Pin ∗ (∀ x, (match mPclose with
| some Pclose => iprop(Pout x ∗ Pclose x -∗ Q' x)
| none => iprop(Pout x -∗ Q' x))) ⊢ Q
export ElimInv (elim_inv)

/-
`IntoIH φ P Q` describes how to turn a pure induction hypothesis `φ` into a proofmode
hypothesis `Q` under an intuitionistic BI context `□ P`.
Expand Down
14 changes: 14 additions & 0 deletions Iris/Iris/ProofMode/Expr.lean
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,20 @@ partial def Hyps.find? {u prop bi} (name : Name) :
| _, .hyp _ name' ivar _ ty _ => if name == name' then (ivar, ty) else none
| _, .sep _ _ _ _ lhs rhs => rhs.find? name <|> lhs.find? name

partial def Hyps.findM? [Monad m] {prop : Q(Type u)} {bi : Q(BI $prop)}
(p : Name → IVarId → Q(Bool) → Q($prop) → m Bool) :
∀ {e}, Hyps bi e → m (Option (Name × IVarId × Q(Bool) × Q($prop)))
| _, .emp _ => return none
| _, .hyp _ name ivar bp ty _ => do
if ← p name ivar bp ty then
return some (name, ivar, bp, ty)
else
return none
| _, .sep _ _ _ _ lhs rhs => do
match ← rhs.findM? p with
| some res => return some res
| none => lhs.findM? p

partial def Hyps.getDecl? {u prop bi} (ivar : IVarId) {s}:
@Hyps u prop bi s → Option (Name × IVarId × Q(Bool) × Q($prop))
| .emp _ => none
Expand Down
Loading