From a79135019153031d9d3e6bd4fb518bbf4faf1e72 Mon Sep 17 00:00:00 2001
From: Ralf Jung <jung@mpi-sws.org>
Date: Wed, 6 Sep 2023 21:56:13 +0200
Subject: [PATCH] =?UTF-8?q?add=20another=20=E2=96=B7=20paradox=20by=20Yusu?=
 =?UTF-8?q?ke?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 iris/bi/lib/counterexamples.v | 144 ++++++++++++++++++++++++++++++++++
 1 file changed, 144 insertions(+)

diff --git a/iris/bi/lib/counterexamples.v b/iris/bi/lib/counterexamples.v
index baa171d5c..3afac3af7 100644
--- a/iris/bi/lib/counterexamples.v
+++ b/iris/bi/lib/counterexamples.v
@@ -259,6 +259,150 @@ Module inv. Section inv.
   Qed.
 End inv. End inv.
 
+(** This is another proof showing that we need the â–· when opening invariants.
+Unlike the two paradoxes above, this proof does not rely on impredicative
+quantification -- at least, not directly. Instead it exploits the impredicative
+quantification that is implicit in [fupd]. Unlike the previous paradox,
+the [finish] token needs to be persistent for this paradox to work.
+
+This paradox is due to Yusuke Matsushita. *)
+Module inv2. Section inv2.
+  Context {PROP : bi} `{!BiAffine PROP}.
+  Implicit Types P : PROP.
+
+  (** Assumptions *)
+  (** We have the update modality (two classes: empty/full mask) *)
+  Inductive mask := M0 | M1.
+  Context (fupd : mask → PROP → PROP).
+  Hypothesis fupd_intro : ∀ E P, P ⊢ fupd E P.
+  Hypothesis fupd_mono : ∀ E P Q, (P ⊢ Q) → fupd E P ⊢ fupd E Q.
+  Hypothesis fupd_fupd : ∀ E P, fupd E (fupd E P) ⊢ fupd E P.
+  Hypothesis fupd_frame_l : ∀ E P Q, P ∗ fupd E Q ⊢ fupd E (P ∗ Q).
+  Hypothesis fupd_mask_mono : ∀ P, fupd M0 P ⊢ fupd M1 P.
+
+  (** We have invariants *)
+  Context (name : Type) (inv : name → PROP → PROP).
+  Global Arguments inv _ _%I.
+  Hypothesis inv_persistent : ∀ i P, Persistent (inv i P).
+  Hypothesis inv_alloc : ∀ P, P ⊢ fupd M1 (∃ i, inv i P).
+  Hypothesis inv_fupd :
+    ∀ i P Q R, (P ∗ Q ⊢ fupd M0 (P ∗ R)) → (inv i P ∗ Q ⊢ fupd M1 R).
+
+  (* We have tokens for a little "two-state STS": [start] -> [finish].
+     state. [start] also asserts the exact state; it is only ever owned by the
+     invariant.  [finished] is persistent. *)
+  (* Posssible implementations of these axioms:
+     * Using the STS monoid of a two-state STS, where [start] is the
+       authoritative saying the state is exactly [start], and [finish]
+       is the "we are at least in state [finish]" typically owned by threads.
+     * Ex () +_## ()
+  *)
+  Context (gname : Type).
+  Context (start finished : gname → PROP).
+
+  Hypothesis sts_alloc : ⊢ fupd M0 (∃ γ, start γ).
+  Hypotheses start_finish : ∀ γ, start γ ⊢ fupd M0 (finished γ).
+
+  Hypothesis finished_not_start : ∀ γ, start γ ∗ finished γ ⊢ False.
+
+  Hypothesis finished_persistent : ∀ γ, Persistent (finished γ).
+
+  (** We assume that we cannot update to false. *)
+  Hypothesis consistency : ¬ (⊢ fupd M1 False).
+
+  (** Some general lemmas and proof mode compatibility. *)
+  Lemma inv_fupd' i P R : inv i P ∗ (P -∗ fupd M0 (P ∗ fupd M1 R)) ⊢ fupd M1 R.
+  Proof.
+    iIntros "(#HiP & HP)". iApply fupd_fupd. iApply inv_fupd; last first.
+    { iSplit; first done. iExact "HP". }
+    iIntros "(HP & HPw)". by iApply "HPw".
+  Qed.
+
+  Global Instance fupd_mono' E : Proper ((⊢) ==> (⊢)) (fupd E).
+  Proof. intros P Q ?. by apply fupd_mono. Qed.
+  Global Instance fupd_proper E : Proper ((⊣⊢) ==> (⊣⊢)) (fupd E).
+  Proof.
+    intros P Q; rewrite !bi.equiv_entails=> -[??]; split; by apply fupd_mono.
+  Qed.
+
+  Lemma fupd_frame_r E P Q : fupd E P ∗ Q ⊢ fupd E (P ∗ Q).
+  Proof. by rewrite comm fupd_frame_l comm. Qed.
+
+  Global Instance elim_fupd_fupd p E P Q :
+    ElimModal True p false (fupd E P) P (fupd E Q) (fupd E Q).
+  Proof.
+    by rewrite /ElimModal bi.intuitionistically_if_elim
+      fupd_frame_r bi.wand_elim_r fupd_fupd.
+  Qed.
+
+  Global Instance elim_fupd0_fupd1 p P Q :
+    ElimModal True p false (fupd M0 P) P (fupd M1 Q) (fupd M1 Q).
+  Proof.
+    by rewrite /ElimModal bi.intuitionistically_if_elim
+      fupd_frame_r bi.wand_elim_r fupd_mask_mono fupd_fupd.
+  Qed.
+
+  Global Instance exists_split_fupd0 {A} E P (Φ : A → PROP) :
+    FromExist P Φ → FromExist (fupd E P) (λ a, fupd E (Φ a)).
+  Proof.
+    rewrite /FromExist=>HP. apply bi.exist_elim=> a.
+    apply fupd_mono. by rewrite -HP -(bi.exist_intro a).
+  Qed.
+
+  (** Now to the actual counterexample. *)
+  (** A version of ⊥ behind a persistent update. *)
+  Definition B : PROP := â–¡ fupd M1 False.
+  (** A delayed-initialization invariant storing [B]. *)
+  Definition P (γ : gname) : PROP := start γ ∨ B.
+  Definition I (i : name) (γ : gname) : PROP := inv i (P γ).
+
+  (** If we can ever finish initializing the invariant, we have a
+  contradiction. *)
+  Lemma finished_contradiction γ i :
+    finished γ ∗ I i γ -∗ B.
+  Proof.
+    iIntros "[#Hfin #HI] !>".
+    iApply (inv_fupd' i). iSplit; first done.
+    iIntros "[Hstart|#Hfalse]".
+    { iDestruct (finished_not_start with "[$Hfin $Hstart]") as %[]. }
+    iApply fupd_intro. iSplitR; last done.
+    by iRight.
+  Qed.
+
+  (** If we can even just create the invariant, we can finish initializing it
+  using the above lemma, and then get the contradiction. *)
+  Lemma invariant_contradiction γ i :
+    I i γ -∗ B.
+  Proof.
+    iIntros "#HI !>".
+    iApply (inv_fupd' i). iSplit; first done.
+    iIntros "HP".
+    iAssert (fupd M0 B) with "[HP]" as ">#Hfalse".
+    { iDestruct "HP" as "[Hstart|#Hfalse]"; last by iApply fupd_intro.
+      iMod (start_finish with "Hstart"). iApply fupd_intro.
+      (** There's a magic moment here where we have the invariant open,
+          but inside [finished_contradiction] we will be proving
+          a [fupd M1] and so we can open the invariant *again*.
+          Really we are just building up a thunk that can be used
+          later when the invariant is closed again. But to build up that
+          thunk we can use resources that we just got out of the invariant,
+          before closing it again. *)
+      iApply finished_contradiction. eauto. }
+    iApply fupd_intro. iSplitR; last done.
+    by iRight.
+  Qed.
+
+  (** Of course, creating the invariant is trivial. *)
+  Lemma contradiction : False.
+  Proof using All.
+    apply consistency.
+    iMod sts_alloc as (γ) "Hstart".
+    iMod (inv_alloc (P γ) with "[Hstart]") as (i) "HI".
+    { by iLeft. }
+    iDestruct (invariant_contradiction with "HI") as "#>[]".
+  Qed.
+End inv2. End inv2.
+
 (** This proves that if we have linear impredicative invariants, we can still
 drop arbitrary resources (i.e., we can "defeat" linearity).
 We assume [cinv_alloc] without any bells or whistles.
-- 
GitLab