clutch.prelude.iris_ext
From iris.bi Require Export bi lib.fixpoint_mono.
From iris.proofmode Require Import base proofmode.
From iris.base_logic.lib Require Export fancy_updates wsat.
From clutch.prelude Require Import classical.
Import uPred.
Section fupd.
Local Existing Instances invGpreS_wsat invGpreS_lc.
(* TODO: remove when Iris is updated (this is on upstream main now) *)
Lemma fupd_soundness_no_lc_unfold `{!invGpreS Σ} m E :
⊢ |==> ∃ `(Hws: invGS_gen HasNoLc Σ) (ω : coPset → iProp Σ),
£ m ∗ ω E ∗ □ (∀ E1 E2 P, (|={E1, E2}=> P) -∗ ω E1 ==∗ ◇ (ω E2 ∗ P)).
Proof.
iMod wsat_alloc as (Hw) "[Hw HE]".
(* We don't actually want any credits, but we need the lcGS. *)
iMod (later_credits.le_upd.lc_alloc m) as (Hc) "[_ Hlc]".
set (Hi := InvG HasNoLc _ Hw Hc).
iExists Hi, (λ E, wsat ∗ ownE E)%I.
rewrite (union_difference_L E ⊤); [|set_solver].
rewrite ownE_op; [|set_solver].
iDestruct "HE" as "[HE _]". iFrame.
iIntros "!>!>" (E1 E2 P) "HP HwE".
rewrite fancy_updates.uPred_fupd_unseal
/fancy_updates.uPred_fupd_def -assoc /=.
by iApply ("HP" with "HwE").
Qed.
End fupd.
(* TODO: upstream? *)
Section fupd_plainly_derived.
Context {PROP : bi}.
Context `{!Sbi PROP, !BiFUpd PROP, !BiFUpdSbi PROP, !BiFUpdSbi PROP, !BiAffine PROP}.
Lemma step_fupdN_fupd_swap {E : coPset} (P: PROP) (n: nat):
(|={E}▷=>^n |={E}=> P) ⊢ |={E}=> |={E}▷=>^n P.
Proof.
induction n => //=.
iIntros "H". iMod "H". iModIntro. iModIntro. iNext. iMod "H".
by iApply IHn.
Qed.
Lemma step_fupdN_Sn (P : PROP) E n :
(|={E}▷=>^(S n) P) ⊣⊢ |={E}▷=> |={E}▷=>^n P.
Proof. done. Qed.
Lemma step_fupdN_Sn_r (P : PROP) n E :
(|={E}▷=>^(S n) P) ⊣⊢ |={E}▷=>^n |={E}▷=> P.
Proof.
replace (S n) with (n + 1) by lia.
rewrite step_fupdN_add //.
Qed.
Lemma step_fupd_mono Eo Ei (P Q : PROP) :
(P ⊢ Q) → (|={Eo}[Ei]▷=> P) ⊢ (|={Eo}[Ei]▷=> Q).
Proof. intros HPQ. by apply fupd_mono, later_mono, fupd_mono. Qed.
Lemma step_fupd_except_0 E1 E2 (P : PROP) : (|={E1}[E2]▷=> ◇ P) ⊢ |={E1}[E2]▷=> P.
Proof. rewrite fupd_except_0 //. Qed.
Lemma step_fupdN_except_0 E1 E2 (P : PROP) n :
(|={E1}[E2]▷=>^(S n) ◇ P) ⊢ |={E1}[E2]▷=>^(S n) P.
Proof.
induction n as [|n IH]; [apply step_fupd_except_0|].
replace (S (S n)) with (1 + S n)%nat by lia.
rewrite 2!step_fupdN_add. by apply step_fupd_mono.
Qed.
Lemma step_fupdN_plain_forall E {A} (Φ : A → PROP) `{!∀ x, Plain (Φ x)} n :
(|={E}▷=>^n ∀ x, Φ x) ⊣⊢ (∀ x, |={E}▷=>^n Φ x).
Proof .
intros. apply (anti_symm _).
{ apply forall_intro=> x. apply step_fupdN_mono. eauto. }
destruct n; [done|].
trans (∀ x, |={E}=> ▷^(S n) ◇ Φ x)%I.
{ apply forall_mono=> x.
opose proof (@step_fupdN_plain PROP BiFUpd0 Sbi0).
by rewrite step_fupdN_plain. }
rewrite -fupd_plain_forall'.
rewrite -step_fupdN_except_0 /= -step_fupdN_intro //.
apply fupd_elim.
rewrite -later_forall -laterN_forall -except_0_forall.
apply step_fupd_intro. done.
Qed.
Lemma fupd_step_fupdN_plain_forall E {A} (Φ : A → PROP) `{!∀ x, Plain (Φ x)} n :
(|={E}=> |={E}▷=>^n ∀ x, Φ x) ⊣⊢ (∀ x, |={E}=> |={E}▷=>^n Φ x).
Proof .
intros. apply (anti_symm _).
{ apply forall_intro=> x. eapply fupd_mono, step_fupdN_mono. eauto. }
destruct n.
{ rewrite fupd_plain_forall //. }
rewrite step_fupdN_plain_forall -fupd_intro.
apply forall_mono => a.
by iIntros "> H".
Qed.
Global Instance step_fupdN_ne k E1 E2:
NonExpansive (λ P : PROP, |={E2}[E1]▷=>^k P)%I.
Proof.
induction k; simpl; solve_proper.
Qed.
Lemma step_fupd_and (P Q : PROP) E :
(|={E}▷=> P ∧ Q) ⊢ (|={E}▷=> P) ∧ (|={E}▷=> Q).
Proof.
rewrite fupd_and.
iIntros "H".
iSplit; iMod "H".
- do 2 iModIntro. iDestruct "H" as "[$ _]".
- do 2 iModIntro. iDestruct "H" as "[_ $]".
Qed.
Lemma step_fupdN_and (P Q : PROP) E n :
(|={E}▷=>^n P ∧ Q) ⊢ (|={E}▷=>^n P) ∧ (|={E}▷=>^n Q).
Proof.
induction n; [done|].
(* rewrite step_fupdN_Sn_r. *)
iIntros "H".
rewrite 2!step_fupdN_Sn.
iSplit; iMod "H".
- do 2 iModIntro. iMod "H". iModIntro.
iApply and_elim_l. by iApply IHn.
- do 2 iModIntro. iMod "H". iModIntro.
iApply and_elim_r. by iApply IHn.
Qed.
End fupd_plainly_derived.
Section step_fupdN.
Context {PROP : bi} `{FU: BiFUpd PROP}.
Lemma step_fupdN_mask_comm n E1 E2 E3 E4 (P: PROP):
E1 ⊆ E2 → E4 ⊆ E3 →
((|={E1, E2}=>|={E2}[E3]▷=>^n P) ⊢ |={E1}[E4]▷=>^n |={E1, E2}=> P)%I.
Proof.
iIntros (Hsub1 Hsub2) "H". iInduction n as [|n] "IH"; auto; simpl.
iMod "H". iMod "H". iMod (fupd_mask_subseteq E4) as "Hclose"; auto.
iModIntro. iNext. iMod "Hclose". iMod "H".
iMod (fupd_mask_subseteq E1) as "Hclose'"; auto.
iModIntro. iApply "IH". iMod "Hclose'". by iModIntro.
Qed.
Lemma step_fupdN_mask_comm' n E1 E2 (P: PROP):
E2 ⊆ E1 →
((|={E1}[E1]▷=>^n |={E1, E2}=> P) ⊢ |={E1, E2}=> |={E2}[E2]▷=>^n P)%I.
Proof.
iIntros (Hsub) "H". iInduction n as [|n] "IH"; auto; simpl.
iMod "H". iMod (fupd_mask_subseteq E2) as "Hclose"; auto.
do 2 iModIntro. iNext. iMod "Hclose". iMod "H". by iApply "IH".
Qed.
End step_fupdN.
Section class_instance_updates.
Context {PROP : bi}.
Context `{!Sbi PROP}.
Global Instance from_forall_step_fupdN
`{!BiFUpd PROP, !BiFUpdSbi PROP, !BiFUpdSbi PROP, !BiAffine PROP} E {A} P (Φ : A → PROP) name n :
FromForall P Φ name → (∀ x, Plain (Φ x)) →
FromForall (|={E}▷=>^n P) (λ a, |={E}▷=>^n (Φ a))%I name.
Proof.
rewrite /FromForall=>? ?.
rewrite -step_fupdN_plain_forall. by apply step_fupdN_mono.
Qed.
Global Instance from_forall_fupd_step_fupdN
`{!BiFUpd PROP, !BiFUpdSbi PROP, !BiFUpdSbi PROP, !BiAffine PROP} E {A} P (Φ : A → PROP) name n :
FromForall P Φ name → (∀ x, Plain (Φ x)) →
FromForall (|={E}=> |={E}▷=>^n P) (λ a, |={E}=> |={E}▷=>^n (Φ a))%I name.
Proof.
rewrite /FromForall=>? ?.
rewrite -fupd_step_fupdN_plain_forall. by apply fupd_mono, step_fupdN_mono.
Qed.
End class_instance_updates.
Section bi_least_fixpoint.
Lemma least_fixpoint_ne_outer {PROP : bi} {A : ofe}
(F1 : (A → PROP) → (A → PROP)) (F2 : (A → PROP) → (A → PROP)) n :
(∀ Φ x, F1 Φ x ≡{n}≡ F2 Φ x) → ∀ x1 x2,
x1 ≡{n}≡ x2 → bi_least_fixpoint F1 x1 ≡{n}≡ bi_least_fixpoint F2 x2.
Proof.
intros HF x1 x2 Hx. rewrite /bi_least_fixpoint /=.
do 3 f_equiv; last solve_proper. repeat f_equiv. apply HF.
Qed.
End bi_least_fixpoint.
Section timeless.
Global Instance if_timeless {PROP:bi} (b:bool) f g: Timeless (PROP :=PROP) f -> Timeless g -> Timeless (if b then f else g).
Proof. by destruct b. Qed.
End timeless.
Section choice.
Context {Σ:gFunctors}.
Lemma iris_choice {A B:Type} (P:A -> B -> iProp Σ):
(∀ a, ∃ b, P a b) ⊢ (∃ f, ∀ a, P a (f a)).
Proof.
econstructor.
unseal.
intros ??? H. simpl.
pose proof (Choice _ _ _ H) as [f ?].
by exists f.
Qed.
Lemma dependent_choice' {A:Type} (R : A -> A -> Prop):
(∀ x, ∃ y, R x y) -> (∀ x, ∃ f, f 0 = x ∧ ∀ n, R (f n) (f (S n))).
Proof.
pose proof (dependent_choice (R:=R)) as H.
intros H' x.
epose proof (H _ x) as [??].
naive_solver.
Unshelve.
intros x'.
pose proof (H' x') as H'.
exists (epsilon H').
by pose proof (epsilon_correct _ H').
Qed.
Lemma iris_dependent_choice {A:Type} (R : A -> A -> iProp Σ):
(∀ x, ∃ y, R x y) ⊢ (∀ x, ∃ f, ⌜f 0 = x⌝ ∧ ∀ n, R (f n) (f (S n))).
Proof.
econstructor.
unseal.
intros ??? H. simpl.
pose proof (dependent_choice' _ H).
done.
Qed.
End choice.
Lemma big_sepL2_Forall2 {PROP : bi} {A B} P (xs : list A) (ys : list B) :
((([∗ list] x; y ∈ xs; ys, ⌜P x y⌝ : PROP) ⊢ ⌜Forall2 P xs ys⌝ : PROP)%I).
Proof.
iRevert (ys). iInduction xs as [|x xs'] ; iIntros (ys) "h".
1: iDestruct (big_sepL2_length with "h") as "%len" ; destruct ys => //.
destruct ys. 1: iDestruct (big_sepL2_length with "h") as "%len" => //.
rewrite big_sepL2_cons.
iDestruct "h" as "[hx h]".
rewrite Forall2_cons_iff. iSplitL "hx" => //.
iApply "IHxs'". done.
Qed.