diff --git a/theories/channel/proto.v b/theories/channel/proto.v index 92c4c0041d3c88e7b542315014ac3a0f209ab8c9..c12d5478f96068437a8d1084bde7db047e4bc23f 100644 --- a/theories/channel/proto.v +++ b/theories/channel/proto.v @@ -245,38 +245,53 @@ Definition iProto_dual_if {Σ V} (d : bool) (p : iProto Σ V) : iProto Σ V := Arguments iProto_dual_if {_ _} _ _%proto. Global Instance: Params (@iProto_dual_if) 3 := {}. -(** * Protocol entailment *) -Definition iProto_le_pre {Σ V} - (rec : iProto Σ V → iProto Σ V → iProp Σ) (p1 p2 : iProto Σ V) : iProp Σ := - (p1 ≡ END ∗ p2 ≡ END) ∨ - ∃ a1 a2 m1 m2, - (p1 ≡ <a1> m1) ∗ (p2 ≡ <a2> m2) ∗ - match a1, a2 with - | Recv, Recv => ∀ v p1', - iMsg_car m1 v (Next p1') -∗ ∃ p2', ▷ rec p1' p2' ∗ iMsg_car m2 v (Next p2') - | Send, Send => ∀ v p2', - iMsg_car m2 v (Next p2') -∗ ∃ p1', ▷ rec p1' p2' ∗ iMsg_car m1 v (Next p1') - | Recv, Send => ∀ v1 v2 p1' p2', - iMsg_car m1 v1 (Next p1') -∗ iMsg_car m2 v2 (Next p2') -∗ ∃ pt, - ▷ rec p1' (<!> MSG v2; pt) ∗ ▷ rec (<?> MSG v1; pt) p2' - | Send, Recv => False - end. -Global Instance iProto_le_pre_ne {Σ V} (rec : iProto Σ V → iProto Σ V → iProp Σ) : - NonExpansive2 (iProto_le_pre rec). +Definition iProto_consistent_pre {Σ V} (rec : iProto Σ V → iProto Σ V → iProp Σ) + (pl pr : iProto Σ V) : iProp Σ := + (∀ a1 a2 m1 m2, + (pl ≡ <a1> m1) -∗ (pr ≡ <a2> m2) -∗ + match a1,a2 with + | Send,Recv => ∀ v p1, iMsg_car m1 v (Next p1) -∗ + ∃ p2, iMsg_car m2 v (Next p2) ∗ ▷ (rec p1 p2) + | Recv,Send => ∀ v p2, iMsg_car m2 v (Next p2) -∗ + ∃ p1, iMsg_car m1 v (Next p1) ∗ ▷ (rec p1 p2) + | _, _ => True + end). + +Global Instance iProto_consistent_pre_ne {Σ V} + (rec : iProto Σ V -n> iProto Σ V -n> iPropO Σ) : + NonExpansive2 (iProto_consistent_pre (λ p1 p2, rec p1 p2)). Proof. solve_proper. Qed. -Program Definition iProto_le_pre' {Σ V} - (rec : iProto Σ V -n> iProto Σ V -n> iPropO Σ) : - iProto Σ V -n> iProto Σ V -n> iPropO Σ := λne p1 p2, - iProto_le_pre (λ p1' p2', rec p1' p2') p1 p2. +Program Definition iProto_consistent_pre' {Σ V} + (rec : iProto Σ V -n> iProto Σ V -n> iPropO Σ) : + iProto Σ V -n> iProto Σ V -n> iPropO Σ := + λne p1 p2, iProto_consistent_pre (λ p1 p2, rec p1 p2) p1 p2. Solve Obligations with solve_proper. -Local Instance iProto_le_pre_contractive {Σ V} : Contractive (@iProto_le_pre' Σ V). + +Local Instance iProto_consistent_pre_contractive {Σ V} : Contractive (@iProto_consistent_pre' Σ V). Proof. - intros n rec1 rec2 Hrec p1 p2. rewrite /iProto_le_pre' /iProto_le_pre /=. - by repeat (f_contractive || f_equiv). + intros n rec1 rec2 Hrec pl pr. rewrite /iProto_consistent_pre' /iProto_consistent_pre /=. + repeat (f_contractive || f_equiv). done. done. +Qed. + +Definition iProto_consistent {Σ V} (pl pr : iProto Σ V) : iProp Σ := + fixpoint iProto_consistent_pre' pl pr. + +Arguments iProto_consistent {_ _} _%proto _%proto. +Global Instance: Params (@iProto_consistent) 2 := {}. + +Global Instance iProto_consistent_ne {Σ V} : NonExpansive2 (@iProto_consistent Σ V). +Proof. solve_proper. Qed. +Global Instance iProto_consistent_proper {Σ V} : Proper ((≡) ==> (≡) ==> (⊣⊢)) (@iProto_consistent Σ V). +Proof. solve_proper. Qed. + +Lemma iProto_consistent_unfold {Σ V} (pl pr : iProto Σ V) : + iProto_consistent pl pr ≡ (iProto_consistent_pre iProto_consistent) pl pr. +Proof. + apply: (fixpoint_unfold iProto_consistent_pre'). Qed. Definition iProto_le {Σ V} (p1 p2 : iProto Σ V) : iProp Σ := - fixpoint iProto_le_pre' p1 p2. + ∀ p3, iProto_consistent p1 p3 -∗ iProto_consistent p2 p3. Arguments iProto_le {_ _} _%proto _%proto. Global Instance: Params (@iProto_le) 2 := {}. Notation "p ⊑ q" := (iProto_le p q) : bi_scope. @@ -291,8 +306,6 @@ Fixpoint iProto_app_recvs {Σ V} (vs : list V) (p : iProto Σ V) : iProto Σ V : | [] => p | v :: vs => <?> MSG v; iProto_app_recvs vs p end. -Definition iProto_interp {Σ V} (vsl vsr : list V) (pl pr : iProto Σ V) : iProp Σ := - ∃ p, iProto_app_recvs vsr p ⊑ pl ∗ iProto_app_recvs vsl (iProto_dual p) ⊑ pr. Record proto_name := ProtName { proto_l_name : gname; proto_r_name : gname }. Global Instance proto_name_inhabited : Inhabited proto_name := @@ -325,11 +338,11 @@ Definition iProto_own_auth `{!protoG Σ V} (γ : proto_name) (s : side) own (side_elim s proto_l_name proto_r_name γ) (●E (Next p)). Definition iProto_ctx `{protoG Σ V} - (γ : proto_name) (vsl vsr : list V) : iProp Σ := + (γ : proto_name) : iProp Σ := ∃ pl pr, iProto_own_auth γ Left pl ∗ iProto_own_auth γ Right pr ∗ - ▷ iProto_interp vsl vsr pl pr. + ▷ iProto_consistent pl pr. (** * The connective for ownership of channel ends *) Definition iProto_own `{!protoG Σ V} @@ -604,413 +617,531 @@ Section proto. iRewrite "Hp12". iIntros "!>". iRewrite "Hp1'". by iRewrite ("IH" $! p1d p2). Qed. - (** ** Protocol entailment **) - Lemma iProto_le_unfold p1 p2 : iProto_le p1 p2 ≡ iProto_le_pre iProto_le p1 p2. - Proof. apply: (fixpoint_unfold iProto_le_pre'). Qed. - - Lemma iProto_le_end : ⊢ END ⊑ (END : iProto Σ V). - Proof. rewrite iProto_le_unfold. iLeft. auto 10. Qed. - - Lemma iProto_le_send m1 m2 : - (∀ v p2', iMsg_car m2 v (Next p2') -∗ ∃ p1', - ▷ (p1' ⊑ p2') ∗ iMsg_car m1 v (Next p1')) -∗ - (<!> m1) ⊑ (<!> m2). - Proof. rewrite iProto_le_unfold. iIntros "H". iRight. auto 10. Qed. - Lemma iProto_le_recv m1 m2 : - (∀ v p1', iMsg_car m1 v (Next p1') -∗ ∃ p2', - ▷ (p1' ⊑ p2') ∗ iMsg_car m2 v (Next p2')) -∗ - (<?> m1) ⊑ (<?> m2). - Proof. rewrite iProto_le_unfold. iIntros "H". iRight. auto 10. Qed. - Lemma iProto_le_swap m1 m2 : - (∀ v1 v2 p1' p2', - iMsg_car m1 v1 (Next p1') -∗ iMsg_car m2 v2 (Next p2') -∗ ∃ pt, - ▷ (p1' ⊑ <!> MSG v2; pt) ∗ ▷ ((<?> MSG v1; pt) ⊑ p2')) -∗ - (<?> m1) ⊑ (<!> m2). - Proof. rewrite iProto_le_unfold. iIntros "H". iRight. auto 10. Qed. - - Lemma iProto_le_end_inv_l p : p ⊑ END -∗ (p ≡ END). - Proof. - rewrite iProto_le_unfold. iIntros "[[Hp _]|H] //". - iDestruct "H" as (a1 a2 m1 m2) "(_ & Heq & _)". - by iDestruct (iProto_end_message_equivI with "Heq") as %[]. - Qed. - - Lemma iProto_le_end_inv_r p : END ⊑ p -∗ (p ≡ END). - Proof. - rewrite iProto_le_unfold. iIntros "[[_ Hp]|H] //". - iDestruct "H" as (a1 a2 m1 m2) "(Heq & _ & _)". - iDestruct (iProto_end_message_equivI with "Heq") as %[]. - Qed. - - Lemma iProto_le_send_inv p1 m2 : - p1 ⊑ (<!> m2) -∗ ∃ a1 m1, - (p1 ≡ <a1> m1) ∗ - match a1 with - | Send => ∀ v p2', - iMsg_car m2 v (Next p2') -∗ ∃ p1', - ▷ (p1' ⊑ p2') ∗ iMsg_car m1 v (Next p1') - | Recv => ∀ v1 v2 p1' p2', - iMsg_car m1 v1 (Next p1') -∗ iMsg_car m2 v2 (Next p2') -∗ ∃ pt, - ▷ (p1' ⊑ <!> MSG v2; pt) ∗ ▷ ((<?> MSG v1; pt) ⊑ p2') - end. - Proof. - rewrite iProto_le_unfold. iIntros "[[_ Heq]|H]". - { iDestruct (iProto_message_end_equivI with "Heq") as %[]. } - iDestruct "H" as (a1 a2 m1 m2') "(Hp1 & Hp2 & H)". - iExists _, _; iSplit; [done|]. destruct a1, a2. + Lemma iProto_consistent_flip p1 p2 : + iProto_consistent p2 p1 -∗ + iProto_consistent p1 p2. + Proof. + iLöb as "IH" forall (p1 p2). + iIntros "Hprot". + rewrite iProto_consistent_unfold /iProto_consistent_pre. + rewrite iProto_consistent_unfold /iProto_consistent_pre. + iIntros (a1 a2 m1 m2) "Hm1 Hm2". + iDestruct ("Hprot" with "Hm2 Hm1") as "Hprot". + destruct a1, a2; [done| | |done]. + - iIntros (v p1') "Hm1". + iDestruct ("Hprot" with "Hm1") as (p2') "[Hprot Hrec]". + iExists p2'. iFrame. by iApply "IH". - iIntros (v p2') "Hm2". - iDestruct (iProto_message_equivI with "Hp2") as (_) "{Hp2} #Hm". - iApply "H". by iRewrite -("Hm" $! v (Next p2')). - - done. - - iIntros (v1 v2 p1' p2') "Hm1 Hm2". - iDestruct (iProto_message_equivI with "Hp2") as (_) "{Hp2} #Hm". - iApply ("H" with "Hm1"). by iRewrite -("Hm" $! v2 (Next p2')). - - iDestruct (iProto_message_equivI with "Hp2") as ([=]) "_". - Qed. - Lemma iProto_le_send_send_inv m1 m2 v p2' : - (<!> m1) ⊑ (<!> m2) -∗ - iMsg_car m2 v (Next p2') -∗ ∃ p1', ▷ (p1' ⊑ p2') ∗ iMsg_car m1 v (Next p1'). - Proof. - iIntros "H Hm2". iDestruct (iProto_le_send_inv with "H") as (a m1') "[Hm1 H]". - iDestruct (iProto_message_equivI with "Hm1") as (<-) "Hm1". - iDestruct ("H" with "Hm2") as (p1') "[Hle Hm]". - iRewrite -("Hm1" $! v (Next p1')) in "Hm". auto with iFrame. - Qed. - Lemma iProto_le_recv_send_inv m1 m2 v1 v2 p1' p2' : - (<?> m1) ⊑ (<!> m2) -∗ - iMsg_car m1 v1 (Next p1') -∗ iMsg_car m2 v2 (Next p2') -∗ ∃ pt, - ▷ (p1' ⊑ <!> MSG v2; pt) ∗ ▷ ((<?> MSG v1; pt) ⊑ p2'). - Proof. - iIntros "H Hm1 Hm2". iDestruct (iProto_le_send_inv with "H") as (a m1') "[Hm H]". - iDestruct (iProto_message_equivI with "Hm") as (<-) "{Hm} #Hm". - iApply ("H" with "[Hm1] Hm2"). by iRewrite -("Hm" $! v1 (Next p1')). - Qed. - - Lemma iProto_le_recv_inv p1 m2 : - p1 ⊑ (<?> m2) -∗ ∃ m1, - (p1 ≡ <?> m1) ∗ - ∀ v p1', iMsg_car m1 v (Next p1') -∗ ∃ p2', - ▷ (p1' ⊑ p2') ∗ iMsg_car m2 v (Next p2'). - Proof. - rewrite iProto_le_unfold. iIntros "[[_ Heq]|H]". - { iDestruct (iProto_message_end_equivI with "Heq") as %[]. } - iDestruct "H" as (a1 a2 m1 m2') "(Hp1 & Hp2 & H)". - iExists m1. - iDestruct (iProto_message_equivI with "Hp2") as (<-) "{Hp2} #Hm2". - destruct a1; [done|]. iSplit; [done|]. - iIntros (v p1') "Hm". iDestruct ("H" with "Hm") as (p2') "[Hle Hm]". - iExists p2'. iIntros "{$Hle}". by iRewrite ("Hm2" $! v (Next p2')). - Qed. - Lemma iProto_le_recv_recv_inv m1 m2 v p1' : - (<?> m1) ⊑ (<?> m2) -∗ - iMsg_car m1 v (Next p1') -∗ ∃ p2', ▷ (p1' ⊑ p2') ∗ iMsg_car m2 v (Next p2'). - Proof. - iIntros "H Hm2". iDestruct (iProto_le_recv_inv with "H") as (m1') "[Hm1 H]". - iApply "H". iDestruct (iProto_message_equivI with "Hm1") as (_) "Hm1". - by iRewrite -("Hm1" $! v (Next p1')). + iDestruct ("Hprot" with "Hm2") as (p1') "[Hprot Hrec]". + iExists p1'. iFrame. by iApply "IH". + Qed. + + Lemma iProto_consistent_step m1 m2 v p1 : + iProto_consistent (<!> m1) (<?> m2) -∗ + iMsg_car m1 v (Next p1) -∗ + ∃ p2, iMsg_car m2 v (Next p2) ∗ ▷ iProto_consistent p1 p2. + Proof. + iIntros "Hprot Hm1". + rewrite iProto_consistent_unfold /iProto_consistent_pre. + iDestruct ("Hprot" with "[//] [//] Hm1") as (p2) "[Hm2 Hprot]". + iExists p2. iFrame. + Qed. + + Lemma iProto_consistent_dual p : + ⊢ iProto_consistent p (iProto_dual p). + Proof. + iLöb as "IH" forall (p). + rewrite iProto_consistent_unfold. + iIntros (a1 a2 m1 m2) "#Hmeq1 #Hmeq2". + destruct a1, a2; [done| | |done]. + - iIntros (v p') "Hm1". + iRewrite "Hmeq1" in "Hmeq2". + rewrite iProto_dual_message. simpl. + rewrite iProto_message_equivI. + iDestruct "Hmeq2" as (_) "Hmeq2". + iSpecialize ("Hmeq2" $! v (Next (iProto_dual p'))). + iExists (iProto_dual p'). + iRewrite -"Hmeq2". + iSplitL; [|iNext; by iApply "IH"]. + simpl. iExists p'. iFrame. done. + - iIntros (v p') "Hm2". + iRewrite "Hmeq1" in "Hmeq2". + rewrite iProto_dual_message. simpl. + rewrite iProto_message_equivI. + iDestruct "Hmeq2" as (_) "Hmeq2". + iSpecialize ("Hmeq2" $! v (Next p')). + iRewrite -"Hmeq2" in "Hm2". + simpl. + iDestruct "Hm2" as (p'') "[Hm2 Hmeq']". + iExists p''. iFrame. + iNext. iRewrite "Hmeq'". + iApply "IH". + Qed. + + Lemma iProto_consistent_le_l pl pl' pr : + iProto_consistent pl pr -∗ pl ⊑ pl' -∗ iProto_consistent pl' pr. + Proof. iIntros "Hprot Hle". by iApply "Hle". Qed. + Lemma iProto_consistent_le_r pl pr pr' : + iProto_consistent pl pr -∗ pr ⊑ pr' -∗ iProto_consistent pl pr'. + Proof. + iIntros "H Hle". iApply iProto_consistent_flip. + iApply "Hle". by iApply iProto_consistent_flip. Qed. Lemma iProto_le_refl p : ⊢ p ⊑ p. - Proof. - iLöb as "IH" forall (p). destruct (iProto_case p) as [->|([]&m&->)]. - - iApply iProto_le_end. - - iApply iProto_le_send. auto 10 with iFrame. - - iApply iProto_le_recv. auto 10 with iFrame. - Qed. - - Lemma iProto_le_trans p1 p2 p3 : p1 ⊑ p2 -∗ p2 ⊑ p3 -∗ p1 ⊑ p3. - Proof. - iIntros "H1 H2". iLöb as "IH" forall (p1 p2 p3). - destruct (iProto_case p3) as [->|([]&m3&->)]. - - iDestruct (iProto_le_end_inv_l with "H2") as "H2". by iRewrite "H2" in "H1". - - iDestruct (iProto_le_send_inv with "H2") as (a2 m2) "[Hp2 H2]". - iRewrite "Hp2" in "H1"; clear p2. destruct a2. - + iDestruct (iProto_le_send_inv with "H1") as (a1 m1) "[Hp1 H1]". - iRewrite "Hp1"; clear p1. destruct a1. - * iApply iProto_le_send. iIntros (v p3') "Hm3". - iDestruct ("H2" with "Hm3") as (p2') "[Hle Hm2]". - iDestruct ("H1" with "Hm2") as (p1') "[Hle' Hm1]". - iExists p1'. iIntros "{$Hm1} !>". by iApply ("IH" with "Hle'"). - * iApply iProto_le_swap. iIntros (v1 v3 p1' p3') "Hm1 Hm3". - iDestruct ("H2" with "Hm3") as (p2') "[Hle Hm2]". - iDestruct ("H1" with "Hm1 Hm2") as (pt) "[Hp1' Hp2']". - iExists pt. iIntros "{$Hp1'} !>". by iApply ("IH" with "Hp2'"). - + iDestruct (iProto_le_recv_inv with "H1") as (m1) "[Hp1 H1]". - iRewrite "Hp1"; clear p1. iApply iProto_le_swap. - iIntros (v1 v3 p1' p3') "Hm1 Hm3". - iDestruct ("H1" with "Hm1") as (p2') "[Hle Hm2]". - iDestruct ("H2" with "Hm2 Hm3") as (pt) "[Hp2' Hp3']". - iExists pt. iIntros "{$Hp3'} !>". by iApply ("IH" with "Hle"). - - iDestruct (iProto_le_recv_inv with "H2") as (m2) "[Hp2 H3]". - iRewrite "Hp2" in "H1". - iDestruct (iProto_le_recv_inv with "H1") as (m1) "[Hp1 H2]". - iRewrite "Hp1". iApply iProto_le_recv. iIntros (v p1') "Hm1". - iDestruct ("H2" with "Hm1") as (p2') "[Hle Hm2]". - iDestruct ("H3" with "Hm2") as (p3') "[Hle' Hm3]". - iExists p3'. iIntros "{$Hm3} !>". by iApply ("IH" with "Hle"). - Qed. - - Lemma iProto_le_payload_elim_l a m v P p : - (P -∗ (<?> MSG v; p) ⊑ (<a> m)) ⊢ - (<?> MSG v {{ P }}; p) ⊑ (<a> m). - Proof. - rewrite iMsg_base_eq. iIntros "H". destruct a. - - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= (#?&#?&HP) Hm2 /=". - iApply (iProto_le_recv_send_inv with "(H HP)"); simpl; auto. - - iApply iProto_le_recv. iIntros (v' p') "(->&Hp&HP)". - iApply (iProto_le_recv_recv_inv with "(H HP)"); simpl; auto. - Qed. - Lemma iProto_le_payload_elim_r a m v P p : - (P -∗ (<a> m) ⊑ (<!> MSG v; p)) ⊢ - (<a> m) ⊑ (<!> MSG v {{ P }}; p). - Proof. - rewrite iMsg_base_eq. iIntros "H". destruct a. - - iApply iProto_le_send. iIntros (v' p') "(->&Hp&HP)". - iApply (iProto_le_send_send_inv with "(H HP)"); simpl; auto. - - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1 (->&#?&HP) /=". - iApply (iProto_le_recv_send_inv with "(H HP) Hm1"); simpl; auto. - Qed. - Lemma iProto_le_payload_intro_l v P p : - P -∗ (<!> MSG v {{ P }}; p) ⊑ (<!> MSG v; p). - Proof. - rewrite iMsg_base_eq. - iIntros "HP". iApply iProto_le_send. iIntros (v' p') "(->&Hp&_) /=". - iExists p'. iSplitR; [iApply iProto_le_refl|]. auto. - Qed. - Lemma iProto_le_payload_intro_r v P p : - P -∗ (<?> MSG v; p) ⊑ (<?> MSG v {{ P }}; p). - Proof. - rewrite iMsg_base_eq. - iIntros "HP". iApply iProto_le_recv. iIntros (v' p') "(->&Hp&_) /=". - iExists p'. iSplitR; [iApply iProto_le_refl|]. auto. - Qed. - - Lemma iProto_le_exist_elim_l {A} (m1 : A → iMsg Σ V) a m2 : - (∀ x, (<?> m1 x) ⊑ (<a> m2)) ⊢ - (<? x> m1 x) ⊑ (<a> m2). - Proof. - rewrite iMsg_exist_eq. iIntros "H". destruct a. - - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1 Hm2 /=". - iDestruct "Hm1" as (x) "Hm1". - iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). - - iApply iProto_le_recv. iIntros (v p1') "/=". iDestruct 1 as (x) "Hm". - by iApply (iProto_le_recv_recv_inv with "H"). - Qed. - - Lemma iProto_le_exist_elim_l_inhabited `{!Inhabited A} (m : A → iMsg Σ V) p : - (∀ x, (<?> m x) ⊑ p) ⊢ - (<? x> m x) ⊑ p. - Proof. - rewrite iMsg_exist_eq. iIntros "H". - destruct (iProto_case p) as [Heq | [a [m' Heq]]]. - - unshelve iSpecialize ("H" $!inhabitant); first by apply _. - rewrite Heq. - iDestruct (iProto_le_end_inv_l with "H") as "H". - rewrite iProto_end_eq iProto_message_eq. - iDestruct (proto_message_end_equivI with "H") as "[]". - - iEval (rewrite Heq). destruct a. - + iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1 Hm2 /=". - iDestruct "Hm1" as (x) "Hm1". - iSpecialize ("H" $! x). rewrite Heq. - iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). - + iApply iProto_le_recv. iIntros (v p1') "/=". iDestruct 1 as (x) "Hm". - iSpecialize ("H" $! x). rewrite Heq. - by iApply (iProto_le_recv_recv_inv with "H"). - Qed. - - Lemma iProto_le_exist_elim_r {A} a m1 (m2 : A → iMsg Σ V) : - (∀ x, (<a> m1) ⊑ (<!> m2 x)) ⊢ - (<a> m1) ⊑ (<! x> m2 x). - Proof. - rewrite iMsg_exist_eq. iIntros "H". destruct a. - - iApply iProto_le_send. iIntros (v p2'). iDestruct 1 as (x) "Hm". - by iApply (iProto_le_send_send_inv with "H"). - - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1". - iDestruct 1 as (x) "Hm2". - iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). - Qed. - Lemma iProto_le_exist_elim_r_inhabited `{Hinh : Inhabited A} p (m : A → iMsg Σ V) : - (∀ x, p ⊑ (<!> m x)) ⊢ - p ⊑ (<! x> m x). - Proof. - rewrite iMsg_exist_eq. iIntros "H". - destruct (iProto_case p) as [Heq | [a [m' Heq]]]. - - unshelve iSpecialize ("H" $!inhabitant); first by apply _. - rewrite Heq. - iDestruct (iProto_le_end_inv_r with "H") as "H". - rewrite iProto_end_eq iProto_message_eq. - iDestruct (proto_message_end_equivI with "H") as "[]". - - iEval (rewrite Heq). destruct a. - + iApply iProto_le_send. iIntros (v p2'). iDestruct 1 as (x) "Hm". - iSpecialize ("H" $! x). rewrite Heq. - by iApply (iProto_le_send_send_inv with "H"). - + iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1". - iDestruct 1 as (x) "Hm2". - iSpecialize ("H" $! x). rewrite Heq. - iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). - Qed. - Lemma iProto_le_exist_intro_l {A} (m : A → iMsg Σ V) a : - ⊢ (<! x> m x) ⊑ (<!> m a). - Proof. - rewrite iMsg_exist_eq. iApply iProto_le_send. iIntros (v p') "Hm /=". - iExists p'. iSplitR; last by auto. iApply iProto_le_refl. - Qed. - Lemma iProto_le_exist_intro_r {A} (m : A → iMsg Σ V) a : - ⊢ (<?> m a) ⊑ (<? x> m x). - Proof. - rewrite iMsg_exist_eq. iApply iProto_le_recv. iIntros (v p') "Hm /=". - iExists p'. iSplitR; last by auto. iApply iProto_le_refl. - Qed. - - Lemma iProto_le_texist_elim_l {TT : tele} (m1 : TT → iMsg Σ V) a m2 : - (∀ x, (<?> m1 x) ⊑ (<a> m2)) ⊢ - (<?.. x> m1 x) ⊑ (<a> m2). - Proof. - iIntros "H". iInduction TT as [|T TT] "IH"; simpl; [done|]. - iApply iProto_le_exist_elim_l; iIntros (x). - iApply "IH". iIntros (xs). iApply "H". - Qed. - Lemma iProto_le_texist_elim_r {TT : tele} a m1 (m2 : TT → iMsg Σ V) : - (∀ x, (<a> m1) ⊑ (<!> m2 x)) -∗ - (<a> m1) ⊑ (<!.. x> m2 x). - Proof. - iIntros "H". iInduction TT as [|T TT] "IH"; simpl; [done|]. - iApply iProto_le_exist_elim_r; iIntros (x). - iApply "IH". iIntros (xs). iApply "H". - Qed. - - Lemma iProto_le_texist_intro_l {TT : tele} (m : TT → iMsg Σ V) x : - ⊢ (<!.. x> m x) ⊑ (<!> m x). - Proof. - induction x as [|T TT x xs IH] using tele_arg_ind; simpl. - { iApply iProto_le_refl. } - iApply iProto_le_trans; [by iApply iProto_le_exist_intro_l|]. iApply IH. - Qed. - Lemma iProto_le_texist_intro_r {TT : tele} (m : TT → iMsg Σ V) x : - ⊢ (<?> m x) ⊑ (<?.. x> m x). - Proof. - induction x as [|T TT x xs IH] using tele_arg_ind; simpl. - { iApply iProto_le_refl. } - iApply iProto_le_trans; [|by iApply iProto_le_exist_intro_r]. iApply IH. - Qed. + Proof. iIntros (p') "$". Qed. - Lemma iProto_le_base a v P p1 p2 : - ▷ (p1 ⊑ p2) ⊢ - (<a> MSG v {{ P }}; p1) ⊑ (<a> MSG v {{ P }}; p2). - Proof. - rewrite iMsg_base_eq. iIntros "H". destruct a. - - iApply iProto_le_send. iIntros (v' p') "(->&Hp&$)". - iExists p1. iSplit; [|by auto]. iIntros "!>". by iRewrite -"Hp". - - iApply iProto_le_recv. iIntros (v' p') "(->&Hp&$)". - iExists p2. iSplit; [|by auto]. iIntros "!>". by iRewrite -"Hp". - Qed. - - Lemma iProto_le_base_swap v1 v2 P1 P2 p : - ⊢ (<?> MSG v1 {{ P1 }}; <!> MSG v2 {{ P2 }}; p) - ⊑ (<!> MSG v2 {{ P2 }}; <?> MSG v1 {{ P1 }}; p). - Proof. - rewrite {1 3}iMsg_base_eq. iApply iProto_le_swap. - iIntros (v1' v2' p1' p2') "/= (->&#Hp1&HP1) (->&#Hp2&HP2)". iExists p. - iSplitL "HP2". - - iIntros "!>". iRewrite -"Hp1". by iApply iProto_le_payload_intro_l. - - iIntros "!>". iRewrite -"Hp2". by iApply iProto_le_payload_intro_r. - Qed. - - Lemma iProto_le_dual p1 p2 : p2 ⊑ p1 -∗ iProto_dual p1 ⊑ iProto_dual p2. - Proof. - iIntros "H". iLöb as "IH" forall (p1 p2). - destruct (iProto_case p1) as [->|([]&m1&->)]. - - iDestruct (iProto_le_end_inv_l with "H") as "H". - iRewrite "H". iApply iProto_le_refl. - - iDestruct (iProto_le_send_inv with "H") as (a2 m2) "[Hp2 H]". - iRewrite "Hp2"; clear p2. iEval (rewrite !iProto_dual_message). - destruct a2; simpl. - + iApply iProto_le_recv. iIntros (v p1d). - iDestruct 1 as (p1') "[Hm1 #Hp1d]". - iDestruct ("H" with "Hm1") as (p2') "[H Hm2]". - iDestruct ("IH" with "H") as "H". iExists (iProto_dual p2'). - iSplitL "H"; [iIntros "!>"; by iRewrite "Hp1d"|]. simpl; auto. - + iApply iProto_le_swap. iIntros (v1 v2 p1d p2d). - iDestruct 1 as (p1') "[Hm1 #Hp1d]". iDestruct 1 as (p2') "[Hm2 #Hp2d]". - iDestruct ("H" with "Hm2 Hm1") as (pt) "[H1 H2]". - iDestruct ("IH" with "H1") as "H1". iDestruct ("IH" with "H2") as "H2 {IH}". - rewrite !iProto_dual_message /=. iExists (iProto_dual pt). iSplitL "H2". - * iIntros "!>". iRewrite "Hp1d". by rewrite -iMsg_dual_base. - * iIntros "!>". iRewrite "Hp2d". by rewrite -iMsg_dual_base. - - iDestruct (iProto_le_recv_inv with "H") as (m2) "[Hp2 H]". - iRewrite "Hp2"; clear p2. iEval (rewrite !iProto_dual_message /=). - iApply iProto_le_send. iIntros (v p2d). - iDestruct 1 as (p2') "[Hm2 #Hp2d]". - iDestruct ("H" with "Hm2") as (p1') "[H Hm1]". - iDestruct ("IH" with "H") as "H". iExists (iProto_dual p1'). - iSplitL "H"; [iIntros "!>"; by iRewrite "Hp2d"|]. simpl; auto. - Qed. - - Lemma iProto_le_amber_internal (p1 p2 : iProto Σ V → iProto Σ V) - `{Contractive p1, Contractive p2}: - □ (∀ rec1 rec2, ▷ (rec1 ⊑ rec2) → p1 rec1 ⊑ p2 rec2) ⊢ - fixpoint p1 ⊑ fixpoint p2. - Proof. - iIntros "#H". iLöb as "IH". - iEval (rewrite (fixpoint_unfold p1)). - iEval (rewrite (fixpoint_unfold p2)). - iApply "H". iApply "IH". - Qed. - Lemma iProto_le_amber_external (p1 p2 : iProto Σ V → iProto Σ V) - `{Contractive p1, Contractive p2}: - (∀ rec1 rec2, (⊢ rec1 ⊑ rec2) → ⊢ p1 rec1 ⊑ p2 rec2) → - ⊢ fixpoint p1 ⊑ fixpoint p2. - Proof. - intros IH. apply fixpoint_ind. - - by intros p1' p2' -> ?. - - exists (fixpoint p2). iApply iProto_le_refl. - - intros p' ?. rewrite (fixpoint_unfold p2). by apply IH. - - apply bi.limit_preserving_entails; [done|solve_proper]. - Qed. - - Lemma iProto_le_dual_l p1 p2 : iProto_dual p2 ⊑ p1 ⊢ iProto_dual p1 ⊑ p2. - Proof. - iIntros "H". iEval (rewrite -(involutive iProto_dual p2)). - by iApply iProto_le_dual. - Qed. - Lemma iProto_le_dual_r p1 p2 : p2 ⊑ iProto_dual p1 ⊢ p1 ⊑ iProto_dual p2. - Proof. - iIntros "H". iEval (rewrite -(involutive iProto_dual p1)). - by iApply iProto_le_dual. - Qed. + Lemma iProto_le_end : ⊢ END ⊑ (END : iProto Σ V). + Proof. iApply iProto_le_refl. Qed. + + (* Lemma iProto_le_send m1 m2 : *) + (* (∀ v p2', iMsg_car m2 v (Next p2') -∗ ∃ p1', *) + (* ▷ (p1' ⊑ p2') ∗ iMsg_car m1 v (Next p1')) -∗ *) + (* (<!> m1) ⊑ (<!> m2). *) + (* Proof. *) + (* iLöb as "IH" forall (m1 m2). *) + (* iIntros "Hle". *) + (* repeat (unfold iProto_le at 3). *) + (* iIntros (p) "Hprot". *) + (* repeat rewrite iProto_consistent_unfold; unfold iProto_consistent_pre. *) + (* iSplit; [iDestruct "Hprot" as "[Hprot _]"|iDestruct "Hprot" as "[_ Hprot]"]. *) + (* { iIntros (a m) "H". *) + (* iDestruct (iProto_message_equivI with "H") as (Heq) "{H} #Hmeq"; subst. *) + (* iIntros (v p') "Hm". *) + (* iSpecialize ("Hprot" with "[//]"). *) + (* iSpecialize ("Hmeq" $! v (Next p')). iRewrite -"Hmeq" in "Hm". *) + (* iSpecialize ("Hle" $! _ _ with "Hm"). iDestruct "Hle" as (p'') "[Hle Hm]". *) + (* iApply "Hle". iApply "Hprot". iApply "Hm". } *) + (* { iIntros (a m) "H". *) + (* iSpecialize ("Hprot" $! _ _ with "H"). *) + (* destruct a. *) + (* - iIntros (v p') "Hm". *) + (* iApply ("IH" with "[Hle]"). *) + (* { iNext. iIntros (v' p'') "Hm". *) + (* iSpecialize ("Hle" with "Hm"). *) + (* iDestruct "Hle" as (p''') "[Hle Hm]". *) + (* iExists p'''. iSplitR "Hm"; [iApply "Hle" | iApply "Hm"]. } *) + (* iApply "Hprot". iApply "Hm". *) + (* - iIntros (v vs Heq); subst. *) + (* iSpecialize ("Hprot" $! _ _ eq_refl). *) + (* iDestruct "Hprot" as (p') "[Hm Hprot]". *) + (* iExists (p'). iFrame "Hm". *) + (* iApply ("IH" with "[Hle] [Hprot]"); [|iApply "Hprot"]. *) + (* iNext. iIntros (v' p'') "Hm". *) + (* iSpecialize ("Hle" with "Hm"). iDestruct "Hle" as (p''') "[Hle Hm]". *) + (* iExists p'''; iSplitR "Hm"; [iApply "Hle" |iApply "Hm"]. } *) + (* Qed. *) + + (* Lemma iProto_le_recv m1 m2 : *) + (* (∀ v p1', iMsg_car m1 v (Next p1') -∗ ∃ p2', *) + (* ▷ (p1' ⊑ p2') ∗ iMsg_car m2 v (Next p2')) -∗ *) + (* (<?> m1) ⊑ (<?> m2). *) + (* Proof. *) + (* iIntros "H" (vsl vsr p) "Hprot". *) + (* iLöb as "IH" forall (vsl vsr m2 p). *) + (* iEval (rewrite iProto_consistent_unfold). *) + (* rewrite /iProto_consistent_pre. *) + (* rewrite iProto_consistent_unfold /iProto_consistent_pre. *) + (* iSplit; last first. *) + (* { *) + (* iDestruct "Hprot" as "[_ Hprot]". *) + (* iIntros ([] m) "Heq". *) + (* { iIntros (v vs) "Hm". *) + (* iDestruct ("Hprot" with "Heq Hm") as "Hprot". *) + (* iIntros "!>". *) + (* by iApply ("IH" with "H"). } *) + (* { iIntros (v vs) "Hm". *) + (* iDestruct ("Hprot" with "Heq Hm") as (p') "[Hm Hprot]". *) + (* iExists p'. iFrame. *) + (* iIntros "!>". *) + (* by iApply ("IH" with "H"). } *) + (* } *) + (* destruct vsr. *) + (* { iIntros (a m) "Heq". rewrite iProto_message_equivI. *) + (* iDestruct "Heq" as (<-) "Heq". *) + (* iIntros (v vs Heq). done. } *) + (* iIntros (a m) "Heq". rewrite iProto_message_equivI. *) + (* iDestruct "Heq" as (<-) "Heq". *) + (* iIntros (w vs Heq). *) + (* assert (v = w) as <- by set_solver. *) + (* assert (vsr = vs) as <- by set_solver. *) + (* iDestruct "Hprot" as "[Hprot _]". *) + (* iDestruct ("Hprot" with "[//] [//]") as (p') "[Hm Hprot]". *) + (* iDestruct ("H" with "Hm") as (p'') "[Hle H]". *) + (* iExists p''. *) + (* iSpecialize ("Heq" $! v (Next p'')). iRewrite -"Heq". *) + (* iFrame. iIntros "!>". *) + (* iApply (iProto_consistent_le_l with "Hprot Hle"). *) + (* Qed. *) + + (* Lemma iProto_le_base a v P p1 p2 : *) + (* ▷ (p1 ⊑ p2) -∗ *) + (* (<a> MSG v {{ P }}; p1) ⊑ (<a> MSG v {{ P }}; p2). *) + (* Proof. *) + (* rewrite iMsg_base_eq. iIntros "H". destruct a. *) + (* - iApply iProto_le_send. iIntros (v' p') "(->&Hp&$)". *) + (* iExists p1. iSplit; [|by auto]. iIntros "!>". by iRewrite -"Hp". *) + (* - iApply iProto_le_recv. iIntros (v' p') "(->&Hp&$)". *) + (* iExists p2. iSplit; [|by auto]. iIntros "!>". by iRewrite -"Hp". *) + (* Qed. *) + + (* Lemma iProto_le_end_inv_l p : p ⊑ END -∗ (p ≡ END). *) + (* Proof. *) + (* rewrite iProto_le_unfold. iIntros "[[Hp _]|H] //". *) + (* iDestruct "H" as (a1 a2 m1 m2) "(_ & Heq & _)". *) + (* by iDestruct (iProto_end_message_equivI with "Heq") as %[]. *) + (* Qed. *) + + (* Lemma iProto_le_end_inv_r p : END ⊑ p -∗ (p ≡ END). *) + (* Proof. *) + (* rewrite iProto_le_unfold. iIntros "[[_ Hp]|H] //". *) + (* iDestruct "H" as (a1 a2 m1 m2) "(Heq & _ & _)". *) + (* iDestruct (iProto_end_message_equivI with "Heq") as %[]. *) + (* Qed. *) + + (* Lemma iProto_le_send_inv p1 m2 : *) + (* p1 ⊑ (<!> m2) -∗ ∃ a1 m1, *) + (* (p1 ≡ <a1> m1) ∗ *) + (* match a1 with *) + (* | Send => ∀ v p2', *) + (* iMsg_car m2 v (Next p2') -∗ ∃ p1', *) + (* ▷ (p1' ⊑ p2') ∗ iMsg_car m1 v (Next p1') *) + (* | Recv => ∀ v1 v2 p1' p2', *) + (* iMsg_car m1 v1 (Next p1') -∗ iMsg_car m2 v2 (Next p2') -∗ ∃ pt, *) + (* ▷ (p1' ⊑ <!> MSG v2; pt) ∗ ▷ ((<?> MSG v1; pt) ⊑ p2') *) + (* end. *) + (* Proof. *) + (* rewrite iProto_le_unfold. iIntros "[[_ Heq]|H]". *) + (* { iDestruct (iProto_message_end_equivI with "Heq") as %[]. } *) + (* iDestruct "H" as (a1 a2 m1 m2') "(Hp1 & Hp2 & H)". *) + (* iExists _, _; iSplit; [done|]. destruct a1, a2. *) + (* - iIntros (v p2') "Hm2". *) + (* iDestruct (iProto_message_equivI with "Hp2") as (_) "{Hp2} #Hm". *) + (* iApply "H". by iRewrite -("Hm" $! v (Next p2')). *) + (* - done. *) + (* - iIntros (v1 v2 p1' p2') "Hm1 Hm2". *) + (* iDestruct (iProto_message_equivI with "Hp2") as (_) "{Hp2} #Hm". *) + (* iApply ("H" with "Hm1"). by iRewrite -("Hm" $! v2 (Next p2')). *) + (* - iDestruct (iProto_message_equivI with "Hp2") as ([=]) "_". *) + (* Qed. *) + (* Lemma iProto_le_send_send_inv m1 m2 v p2' : *) + (* (<!> m1) ⊑ (<!> m2) -∗ *) + (* iMsg_car m2 v (Next p2') -∗ ∃ p1', ▷ (p1' ⊑ p2') ∗ iMsg_car m1 v (Next p1'). *) + (* Proof. *) + (* iIntros "H Hm2". iDestruct (iProto_le_send_inv with "H") as (a m1') "[Hm1 H]". *) + (* iDestruct (iProto_message_equivI with "Hm1") as (<-) "Hm1". *) + (* iDestruct ("H" with "Hm2") as (p1') "[Hle Hm]". *) + (* iRewrite -("Hm1" $! v (Next p1')) in "Hm". auto with iFrame. *) + (* Qed. *) + (* Lemma iProto_le_recv_send_inv m1 m2 v1 v2 p1' p2' : *) + (* (<?> m1) ⊑ (<!> m2) -∗ *) + (* iMsg_car m1 v1 (Next p1') -∗ iMsg_car m2 v2 (Next p2') -∗ ∃ pt, *) + (* ▷ (p1' ⊑ <!> MSG v2; pt) ∗ ▷ ((<?> MSG v1; pt) ⊑ p2'). *) + (* Proof. *) + (* iIntros "H Hm1 Hm2". iDestruct (iProto_le_send_inv with "H") as (a m1') "[Hm H]". *) + (* iDestruct (iProto_message_equivI with "Hm") as (<-) "{Hm} #Hm". *) + (* iApply ("H" with "[Hm1] Hm2"). by iRewrite -("Hm" $! v1 (Next p1')). *) + (* Qed. *) + + (* Lemma iProto_le_recv_inv p1 m2 : *) + (* p1 ⊑ (<?> m2) -∗ ∃ m1, *) + (* (p1 ≡ <?> m1) ∗ *) + (* ∀ v p1', iMsg_car m1 v (Next p1') -∗ ∃ p2', *) + (* ▷ (p1' ⊑ p2') ∗ iMsg_car m2 v (Next p2'). *) + (* Proof. *) + (* rewrite iProto_le_unfold. iIntros "[[_ Heq]|H]". *) + (* { iDestruct (iProto_message_end_equivI with "Heq") as %[]. } *) + (* iDestruct "H" as (a1 a2 m1 m2') "(Hp1 & Hp2 & H)". *) + (* iExists m1. *) + (* iDestruct (iProto_message_equivI with "Hp2") as (<-) "{Hp2} #Hm2". *) + (* destruct a1; [done|]. iSplit; [done|]. *) + (* iIntros (v p1') "Hm". iDestruct ("H" with "Hm") as (p2') "[Hle Hm]". *) + (* iExists p2'. iIntros "{$Hle}". by iRewrite ("Hm2" $! v (Next p2')). *) + (* Qed. *) + (* Lemma iProto_le_recv_recv_inv m1 m2 v p1' : *) + (* (<?> m1) ⊑ (<?> m2) -∗ *) + (* iMsg_car m1 v (Next p1') -∗ ∃ p2', ▷ (p1' ⊑ p2') ∗ iMsg_car m2 v (Next p2'). *) + (* Proof. *) + (* iIntros "H Hm2". iDestruct (iProto_le_recv_inv with "H") as (m1') "[Hm1 H]". *) + (* iApply "H". iDestruct (iProto_message_equivI with "Hm1") as (_) "Hm1". *) + (* by iRewrite -("Hm1" $! v (Next p1')). *) + (* Qed. *) + + (* Lemma iProto_le_refl p : ⊢ p ⊑ p. *) + (* Proof. *) + (* iLöb as "IH" forall (p). destruct (iProto_case p) as [->|([]&m&->)]. *) + (* - iApply iProto_le_end. *) + (* - iApply iProto_le_send. auto 10 with iFrame. *) + (* - iApply iProto_le_recv. auto 10 with iFrame. *) + (* Qed. *) - Lemma iProto_le_app p1 p2 p3 p4 : - p1 ⊑ p2 -∗ p3 ⊑ p4 -∗ p1 <++> p3 ⊑ p2 <++> p4. + Lemma iProto_le_trans p1 p2 p3 : p1 ⊑ p2 -∗ p2 ⊑ p3 -∗ p1 ⊑ p3. Proof. - iIntros "H1 H2". iLöb as "IH" forall (p1 p2 p3 p4). - destruct (iProto_case p2) as [->|([]&m2&->)]. - - iDestruct (iProto_le_end_inv_l with "H1") as "H1". - iRewrite "H1". by rewrite !left_id. - - iDestruct (iProto_le_send_inv with "H1") as (a1 m1) "[Hp1 H1]". - iRewrite "Hp1"; clear p1. rewrite !iProto_app_message. destruct a1; simpl. - + iApply iProto_le_send. iIntros (v p24). - iDestruct 1 as (p2') "[Hm2 #Hp24]". - iDestruct ("H1" with "Hm2") as (p1') "[H1 Hm1]". - iExists (p1' <++> p3). iSplitR "Hm1"; [|by simpl; eauto]. - iIntros "!>". iRewrite "Hp24". by iApply ("IH" with "H1"). - + iApply iProto_le_swap. iIntros (v1 v2 p13 p24). - iDestruct 1 as (p1') "[Hm1 #Hp13]". iDestruct 1 as (p2') "[Hm2 #Hp24]". - iSpecialize ("H1" with "Hm1 Hm2"). - iDestruct "H1" as (pt) "[H1 H1']". - iExists (pt <++> p3). iSplitL "H1". - * iIntros "!>". iRewrite "Hp13". - rewrite /= -iMsg_app_base -iProto_app_message. - iApply ("IH" with "H1"). iApply iProto_le_refl. - * iIntros "!>". iRewrite "Hp24". - rewrite /= -iMsg_app_base -iProto_app_message. - iApply ("IH" with "H1' H2"). - - iDestruct (iProto_le_recv_inv with "H1") as (m1) "[Hp1 H1]". - iRewrite "Hp1"; clear p1. rewrite !iProto_app_message. iApply iProto_le_recv. - iIntros (v p13). iDestruct 1 as (p1') "[Hm1 #Hp13]". - iDestruct ("H1" with "Hm1") as (p2'') "[H1 Hm2]". - iExists (p2'' <++> p4). iSplitR "Hm2"; [|by simpl; eauto]. - iIntros "!>". iRewrite "Hp13". by iApply ("IH" with "H1"). - Qed. + iIntros "H1 H2" (p) "Hprot". + iApply "H2". iApply "H1". done. + Qed. + + (* Lemma iProto_le_payload_elim_l a m v P p : *) + (* (P -∗ (<?> MSG v; p) ⊑ (<a> m)) -∗ *) + (* (<?> MSG v {{ P }}; p) ⊑ (<a> m). *) + (* Proof. *) + (* rewrite iMsg_base_eq. iIntros "H". destruct a. *) + (* - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= (#?&#?&HP) Hm2 /=". *) + (* iApply (iProto_le_recv_send_inv with "(H HP)"); simpl; auto. *) + (* - iApply iProto_le_recv. iIntros (v' p') "(->&Hp&HP)". *) + (* iApply (iProto_le_recv_recv_inv with "(H HP)"); simpl; auto. *) + (* Qed. *) + (* Lemma iProto_le_payload_elim_r a m v P p : *) + (* (P -∗ (<a> m) ⊑ (<!> MSG v; p)) -∗ *) + (* (<a> m) ⊑ (<!> MSG v {{ P }}; p). *) + (* Proof. *) + (* rewrite iMsg_base_eq. iIntros "H". destruct a. *) + (* - iApply iProto_le_send. iIntros (v' p') "(->&Hp&HP)". *) + (* iApply (iProto_le_send_send_inv with "(H HP)"); simpl; auto. *) + (* - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1 (->&#?&HP) /=". *) + (* iApply (iProto_le_recv_send_inv with "(H HP) Hm1"); simpl; auto. *) + (* Qed. *) + (* Lemma iProto_le_payload_intro_l v P p : *) + (* P -∗ (<!> MSG v {{ P }}; p) ⊑ (<!> MSG v; p). *) + (* Proof. *) + (* rewrite iMsg_base_eq. *) + (* iIntros "HP". iApply iProto_le_send. iIntros (v' p') "(->&Hp&_) /=". *) + (* iExists p'. iSplitR; [iApply iProto_le_refl|]. auto. *) + (* Qed. *) + (* Lemma iProto_le_payload_intro_r v P p : *) + (* P -∗ (<?> MSG v; p) ⊑ (<?> MSG v {{ P }}; p). *) + (* Proof. *) + (* rewrite iMsg_base_eq. *) + (* iIntros "HP". iApply iProto_le_recv. iIntros (v' p') "(->&Hp&_) /=". *) + (* iExists p'. iSplitR; [iApply iProto_le_refl|]. auto. *) + (* Qed. *) + + (* Lemma iProto_le_exist_elim_l {A} (m1 : A → iMsg Σ V) a m2 : *) + (* (∀ x, (<?> m1 x) ⊑ (<a> m2)) -∗ *) + (* (<? x> m1 x) ⊑ (<a> m2). *) + (* Proof. *) + (* rewrite iMsg_exist_eq. iIntros "H". destruct a. *) + (* - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1 Hm2 /=". *) + (* iDestruct "Hm1" as (x) "Hm1". *) + (* iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). *) + (* - iApply iProto_le_recv. iIntros (v p1') "/=". iDestruct 1 as (x) "Hm". *) + (* by iApply (iProto_le_recv_recv_inv with "H"). *) + (* Qed. *) + + (* Lemma iProto_le_exist_elim_l_inhabited `{!Inhabited A} (m : A → iMsg Σ V) p : *) + (* (∀ x, (<?> m x) ⊑ p) -∗ *) + (* (<? x> m x) ⊑ p. *) + (* Proof. *) + (* rewrite iMsg_exist_eq. iIntros "H". *) + (* destruct (iProto_case p) as [Heq | [a [m' Heq]]]. *) + (* - unshelve iSpecialize ("H" $!inhabitant); first by apply _. *) + (* rewrite Heq. *) + (* iDestruct (iProto_le_end_inv_l with "H") as "H". *) + (* rewrite iProto_end_eq iProto_message_eq. *) + (* iDestruct (proto_message_end_equivI with "H") as "[]". *) + (* - iEval (rewrite Heq). destruct a. *) + (* + iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1 Hm2 /=". *) + (* iDestruct "Hm1" as (x) "Hm1". *) + (* iSpecialize ("H" $! x). rewrite Heq. *) + (* iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). *) + (* + iApply iProto_le_recv. iIntros (v p1') "/=". iDestruct 1 as (x) "Hm". *) + (* iSpecialize ("H" $! x). rewrite Heq. *) + (* by iApply (iProto_le_recv_recv_inv with "H"). *) + (* Qed. *) + + (* Lemma iProto_le_exist_elim_r {A} a m1 (m2 : A → iMsg Σ V) : *) + (* (∀ x, (<a> m1) ⊑ (<!> m2 x)) -∗ *) + (* (<a> m1) ⊑ (<! x> m2 x). *) + (* Proof. *) + (* rewrite iMsg_exist_eq. iIntros "H". destruct a. *) + (* - iApply iProto_le_send. iIntros (v p2'). iDestruct 1 as (x) "Hm". *) + (* by iApply (iProto_le_send_send_inv with "H"). *) + (* - iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1". *) + (* iDestruct 1 as (x) "Hm2". *) + (* iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). *) + (* Qed. *) + (* Lemma iProto_le_exist_elim_r_inhabited `{Hinh : Inhabited A} p (m : A → iMsg Σ V) : *) + (* (∀ x, p ⊑ (<!> m x)) -∗ *) + (* p ⊑ (<! x> m x). *) + (* Proof. *) + (* rewrite iMsg_exist_eq. iIntros "H". *) + (* destruct (iProto_case p) as [Heq | [a [m' Heq]]]. *) + (* - unshelve iSpecialize ("H" $!inhabitant); first by apply _. *) + (* rewrite Heq. *) + (* iDestruct (iProto_le_end_inv_r with "H") as "H". *) + (* rewrite iProto_end_eq iProto_message_eq. *) + (* iDestruct (proto_message_end_equivI with "H") as "[]". *) + (* - iEval (rewrite Heq). destruct a. *) + (* + iApply iProto_le_send. iIntros (v p2'). iDestruct 1 as (x) "Hm". *) + (* iSpecialize ("H" $! x). rewrite Heq. *) + (* by iApply (iProto_le_send_send_inv with "H"). *) + (* + iApply iProto_le_swap. iIntros (v1 v2 p1' p2') "/= Hm1". *) + (* iDestruct 1 as (x) "Hm2". *) + (* iSpecialize ("H" $! x). rewrite Heq. *) + (* iApply (iProto_le_recv_send_inv with "H Hm1 Hm2"). *) + (* Qed. *) + (* Lemma iProto_le_exist_intro_l {A} (m : A → iMsg Σ V) a : *) + (* ⊢ (<! x> m x) ⊑ (<!> m a). *) + (* Proof. *) + (* rewrite iMsg_exist_eq. iApply iProto_le_send. iIntros (v p') "Hm /=". *) + (* iExists p'. iSplitR; last by auto. iApply iProto_le_refl. *) + (* Qed. *) + (* Lemma iProto_le_exist_intro_r {A} (m : A → iMsg Σ V) a : *) + (* ⊢ (<?> m a) ⊑ (<? x> m x). *) + (* Proof. *) + (* rewrite iMsg_exist_eq. iApply iProto_le_recv. iIntros (v p') "Hm /=". *) + (* iExists p'. iSplitR; last by auto. iApply iProto_le_refl. *) + (* Qed. *) + + (* Lemma iProto_le_texist_elim_l {TT : tele} (m1 : TT → iMsg Σ V) a m2 : *) + (* (∀ x, (<?> m1 x) ⊑ (<a> m2)) -∗ *) + (* (<?.. x> m1 x) ⊑ (<a> m2). *) + (* Proof. *) + (* iIntros "H". iInduction TT as [|T TT] "IH"; simpl; [done|]. *) + (* iApply iProto_le_exist_elim_l; iIntros (x). *) + (* iApply "IH". iIntros (xs). iApply "H". *) + (* Qed. *) + (* Lemma iProto_le_texist_elim_r {TT : tele} a m1 (m2 : TT → iMsg Σ V) : *) + (* (∀ x, (<a> m1) ⊑ (<!> m2 x)) -∗ *) + (* (<a> m1) ⊑ (<!.. x> m2 x). *) + (* Proof. *) + (* iIntros "H". iInduction TT as [|T TT] "IH"; simpl; [done|]. *) + (* iApply iProto_le_exist_elim_r; iIntros (x). *) + (* iApply "IH". iIntros (xs). iApply "H". *) + (* Qed. *) + + (* Lemma iProto_le_texist_intro_l {TT : tele} (m : TT → iMsg Σ V) x : *) + (* ⊢ (<!.. x> m x) ⊑ (<!> m x). *) + (* Proof. *) + (* induction x as [|T TT x xs IH] using tele_arg_ind; simpl. *) + (* { iApply iProto_le_refl. } *) + (* iApply iProto_le_trans; [by iApply iProto_le_exist_intro_l|]. iApply IH. *) + (* Qed. *) + (* Lemma iProto_le_texist_intro_r {TT : tele} (m : TT → iMsg Σ V) x : *) + (* ⊢ (<?> m x) ⊑ (<?.. x> m x). *) + (* Proof. *) + (* induction x as [|T TT x xs IH] using tele_arg_ind; simpl. *) + (* { iApply iProto_le_refl. } *) + (* iApply iProto_le_trans; [|by iApply iProto_le_exist_intro_r]. iApply IH. *) + (* Qed. *) + + (* Lemma iProto_le_base a v P p1 p2 : *) + (* ▷ (p1 ⊑ p2) -∗ *) + (* (<a> MSG v {{ P }}; p1) ⊑ (<a> MSG v {{ P }}; p2). *) + (* Proof. *) + (* rewrite iMsg_base_eq. iIntros "H". destruct a. *) + (* - iApply iProto_le_send. iIntros (v' p') "(->&Hp&$)". *) + (* iExists p1. iSplit; [|by auto]. iIntros "!>". by iRewrite -"Hp". *) + (* - iApply iProto_le_recv. iIntros (v' p') "(->&Hp&$)". *) + (* iExists p2. iSplit; [|by auto]. iIntros "!>". by iRewrite -"Hp". *) + (* Qed. *) + + (* Lemma iProto_le_base_swap v1 v2 P1 P2 p : *) + (* ⊢ (<?> MSG v1 {{ P1 }}; <!> MSG v2 {{ P2 }}; p) *) + (* ⊑ (<!> MSG v2 {{ P2 }}; <?> MSG v1 {{ P1 }}; p). *) + (* Proof. *) + (* rewrite {1 3}iMsg_base_eq. iApply iProto_le_swap. *) + (* iIntros (v1' v2' p1' p2') "/= (->&#Hp1&HP1) (->&#Hp2&HP2)". iExists p. *) + (* iSplitL "HP2". *) + (* - iIntros "!>". iRewrite -"Hp1". by iApply iProto_le_payload_intro_l. *) + (* - iIntros "!>". iRewrite -"Hp2". by iApply iProto_le_payload_intro_r. *) + (* Qed. *) + + (* Lemma iProto_le_dual p1 p2 : p2 ⊑ p1 -∗ iProto_dual p1 ⊑ iProto_dual p2. *) + (* Proof. *) + (* iIntros "H". iLöb as "IH" forall (p1 p2). *) + (* destruct (iProto_case p1) as [->|([]&m1&->)]. *) + (* - iDestruct (iProto_le_end_inv_l with "H") as "H". *) + (* iRewrite "H". iApply iProto_le_refl. *) + (* - iDestruct (iProto_le_send_inv with "H") as (a2 m2) "[Hp2 H]". *) + (* iRewrite "Hp2"; clear p2. iEval (rewrite !iProto_dual_message). *) + (* destruct a2; simpl. *) + (* + iApply iProto_le_recv. iIntros (v p1d). *) + (* iDestruct 1 as (p1') "[Hm1 #Hp1d]". *) + (* iDestruct ("H" with "Hm1") as (p2') "[H Hm2]". *) + (* iDestruct ("IH" with "H") as "H". iExists (iProto_dual p2'). *) + (* iSplitL "H"; [iIntros "!>"; by iRewrite "Hp1d"|]. simpl; auto. *) + (* + iApply iProto_le_swap. iIntros (v1 v2 p1d p2d). *) + (* iDestruct 1 as (p1') "[Hm1 #Hp1d]". iDestruct 1 as (p2') "[Hm2 #Hp2d]". *) + (* iDestruct ("H" with "Hm2 Hm1") as (pt) "[H1 H2]". *) + (* iDestruct ("IH" with "H1") as "H1". iDestruct ("IH" with "H2") as "H2 {IH}". *) + (* rewrite !iProto_dual_message /=. iExists (iProto_dual pt). iSplitL "H2". *) + (* * iIntros "!>". iRewrite "Hp1d". by rewrite -iMsg_dual_base. *) + (* * iIntros "!>". iRewrite "Hp2d". by rewrite -iMsg_dual_base. *) + (* - iDestruct (iProto_le_recv_inv with "H") as (m2) "[Hp2 H]". *) + (* iRewrite "Hp2"; clear p2. iEval (rewrite !iProto_dual_message /=). *) + (* iApply iProto_le_send. iIntros (v p2d). *) + (* iDestruct 1 as (p2') "[Hm2 #Hp2d]". *) + (* iDestruct ("H" with "Hm2") as (p1') "[H Hm1]". *) + (* iDestruct ("IH" with "H") as "H". iExists (iProto_dual p1'). *) + (* iSplitL "H"; [iIntros "!>"; by iRewrite "Hp2d"|]. simpl; auto. *) + (* Qed. *) + + (* Lemma iProto_le_amber_internal (p1 p2 : iProto Σ V → iProto Σ V) *) + (* `{Contractive p1, Contractive p2}: *) + (* □ (∀ rec1 rec2, ▷ (rec1 ⊑ rec2) → p1 rec1 ⊑ p2 rec2) -∗ *) + (* fixpoint p1 ⊑ fixpoint p2. *) + (* Proof. *) + (* iIntros "#H". iLöb as "IH". *) + (* iEval (rewrite (fixpoint_unfold p1)). *) + (* iEval (rewrite (fixpoint_unfold p2)). *) + (* iApply "H". iApply "IH". *) + (* Qed. *) + (* Lemma iProto_le_amber_external (p1 p2 : iProto Σ V → iProto Σ V) *) + (* `{Contractive p1, Contractive p2}: *) + (* (∀ rec1 rec2, (⊢ rec1 ⊑ rec2) → ⊢ p1 rec1 ⊑ p2 rec2) → *) + (* ⊢ fixpoint p1 ⊑ fixpoint p2. *) + (* Proof. *) + (* intros IH. apply fixpoint_ind. *) + (* - by intros p1' p2' -> ?. *) + (* - exists (fixpoint p2). iApply iProto_le_refl. *) + (* - intros p' ?. rewrite (fixpoint_unfold p2). by apply IH. *) + (* - apply bi.limit_preserving_entails; [done|solve_proper]. *) + (* Qed. *) + + (* Lemma iProto_le_dual_l p1 p2 : iProto_dual p2 ⊑ p1 -∗ iProto_dual p1 ⊑ p2. *) + (* Proof. *) + (* iIntros "H". iEval (rewrite -(involutive iProto_dual p2)). *) + (* by iApply iProto_le_dual. *) + (* Qed. *) + (* Lemma iProto_le_dual_r p1 p2 : p2 ⊑ iProto_dual p1 -∗ p1 ⊑ iProto_dual p2. *) + (* Proof. *) + (* iIntros "H". iEval (rewrite -(involutive iProto_dual p1)). *) + (* by iApply iProto_le_dual. *) + (* Qed. *) + + (* Lemma iProto_le_app p1 p2 p3 p4 : *) + (* p1 ⊑ p2 -∗ p3 ⊑ p4 -∗ p1 <++> p3 ⊑ p2 <++> p4. *) + (* Proof. *) + (* iIntros "H1 H2". iLöb as "IH" forall (p1 p2 p3 p4). *) + (* destruct (iProto_case p2) as [->|([]&m2&->)]. *) + (* - iDestruct (iProto_le_end_inv_l with "H1") as "H1". *) + (* iRewrite "H1". by rewrite !left_id. *) + (* - iDestruct (iProto_le_send_inv with "H1") as (a1 m1) "[Hp1 H1]". *) + (* iRewrite "Hp1"; clear p1. rewrite !iProto_app_message. destruct a1; simpl. *) + (* + iApply iProto_le_send. iIntros (v p24). *) + (* iDestruct 1 as (p2') "[Hm2 #Hp24]". *) + (* iDestruct ("H1" with "Hm2") as (p1') "[H1 Hm1]". *) + (* iExists (p1' <++> p3). iSplitR "Hm1"; [|by simpl; eauto]. *) + (* iIntros "!>". iRewrite "Hp24". by iApply ("IH" with "H1"). *) + (* + iApply iProto_le_swap. iIntros (v1 v2 p13 p24). *) + (* iDestruct 1 as (p1') "[Hm1 #Hp13]". iDestruct 1 as (p2') "[Hm2 #Hp24]". *) + (* iSpecialize ("H1" with "Hm1 Hm2"). *) + (* iDestruct "H1" as (pt) "[H1 H1']". *) + (* iExists (pt <++> p3). iSplitL "H1". *) + (* * iIntros "!>". iRewrite "Hp13". *) + (* rewrite /= -iMsg_app_base -iProto_app_message. *) + (* iApply ("IH" with "H1"). iApply iProto_le_refl. *) + (* * iIntros "!>". iRewrite "Hp24". *) + (* rewrite /= -iMsg_app_base -iProto_app_message. *) + (* iApply ("IH" with "H1' H2"). *) + (* - iDestruct (iProto_le_recv_inv with "H1") as (m1) "[Hp1 H1]". *) + (* iRewrite "Hp1"; clear p1. rewrite !iProto_app_message. iApply iProto_le_recv. *) + (* iIntros (v p13). iDestruct 1 as (p1') "[Hm1 #Hp13]". *) + (* iDestruct ("H1" with "Hm1") as (p2'') "[H1 Hm2]". *) + (* iExists (p2'' <++> p4). iSplitR "Hm2"; [|by simpl; eauto]. *) + (* iIntros "!>". iRewrite "Hp13". by iApply ("IH" with "H1"). *) + (* Qed. *) (** ** Lemmas about the auxiliary definitions and invariants *) Global Instance iProto_app_recvs_ne vs : @@ -1019,12 +1150,6 @@ Section proto. Global Instance iProto_app_recvs_proper vs : Proper ((≡) ==> (≡)) (iProto_app_recvs (Σ:=Σ) (V:=V) vs). Proof. induction vs; solve_proper. Qed. - Global Instance iProto_interp_ne vsl vsr : - NonExpansive2 (iProto_interp (Σ:=Σ) (V:=V) vsl vsr). - Proof. solve_proper. Qed. - Global Instance iProto_interp_proper vsl vsr : - Proper ((≡) ==> (≡) ==> (≡)) (iProto_interp (Σ:=Σ) (V:=V) vsl vsr). - Proof. apply (ne_proper_2 _). Qed. Global Instance iProto_own_frag_ne γ s : NonExpansive (iProto_own_frag γ s). Proof. solve_proper. Qed. @@ -1032,8 +1157,8 @@ Section proto. Lemma iProto_own_auth_agree γ s p p' : iProto_own_auth γ s p -∗ iProto_own_frag γ s p' -∗ ▷ (p ≡ p'). Proof. - iIntros "H● H◯". iCombine "H● H◯" gives "H✓". - iDestruct (excl_auth_agreeI with "H✓") as "{H✓} H✓". + iIntros "H● H◯". iDestruct (own_valid_2 with "H● H◯") as "H✓". + iDestruct (excl_auth_agreeI with "H✓") as "H✓". iApply (later_equivI_1 with "H✓"). Qed. @@ -1046,67 +1171,6 @@ Section proto. by rewrite own_op. Qed. - Lemma iProto_interp_nil p : ⊢ iProto_interp [] [] p (iProto_dual p). - Proof. iExists p; simpl. iSplitL; iApply iProto_le_refl. Qed. - - Lemma iProto_interp_flip vsl vsr pl pr : - iProto_interp vsl vsr pl pr -∗ iProto_interp vsr vsl pr pl. - Proof. - iDestruct 1 as (p) "[Hp Hdp]". iExists (iProto_dual p). - rewrite (involutive iProto_dual). iFrame. - Qed. - - Lemma iProto_interp_le_l vsl vsr pl pl' pr : - iProto_interp vsl vsr pl pr -∗ pl ⊑ pl' -∗ iProto_interp vsl vsr pl' pr. - Proof. - iDestruct 1 as (p) "[Hp Hdp]". iIntros "Hle". iExists p. - iFrame "Hdp". by iApply (iProto_le_trans with "Hp"). - Qed. - Lemma iProto_interp_le_r vsl vsr pl pr pr' : - iProto_interp vsl vsr pl pr -∗ pr ⊑ pr' -∗ iProto_interp vsl vsr pl pr'. - Proof. - iIntros "H Hle". iApply iProto_interp_flip. - iApply (iProto_interp_le_l with "[H] Hle"). by iApply iProto_interp_flip. - Qed. - - Lemma iProto_interp_send vl ml vsl vsr pr pl' : - iProto_interp vsl vsr (<!> ml) pr -∗ - iMsg_car ml vl (Next pl') -∗ - ▷^(length vsr) iProto_interp (vsl ++ [vl]) vsr pl' pr. - Proof. - iDestruct 1 as (p) "[Hp Hdp] /="; iIntros "Hml". - iDestruct (iProto_le_trans _ _ (<!> MSG vl; pl') with "Hp [Hml]") as "Hp". - { iApply iProto_le_send. rewrite iMsg_base_eq. iIntros (v' p') "(->&Hp&_) /=". - iExists p'. iSplitR; [iApply iProto_le_refl|]. by iRewrite -"Hp". } - iInduction vsr as [|vr vsr] "IH" forall (pl'); simpl. - { iExists pl'; simpl. iSplitR; [iApply iProto_le_refl|]. - iApply (iProto_le_trans with "[Hp] Hdp"). - iInduction vsl as [|vl' vsl] "IH"; simpl. - { iApply iProto_le_dual_r. rewrite iProto_dual_message iMsg_dual_base /=. - by rewrite involutive. } - iApply iProto_le_base; iIntros "!>". by iApply "IH". } - iDestruct (iProto_le_recv_send_inv _ _ vr vl - (iProto_app_recvs vsr p) pl' with "Hp [] []") as (p') "[H1 H2]"; - [rewrite iMsg_base_eq; by auto..|]. - iIntros "!>". iSpecialize ("IH" with "Hdp H1"). iIntros "!>". - iDestruct "IH" as (p'') "[Hp'' Hdp'']". iExists p''. iFrame "Hdp''". - iApply (iProto_le_trans with "[Hp''] H2"); simpl. by iApply iProto_le_base. - Qed. - - Lemma iProto_interp_recv vl vsl vsr pl mr : - iProto_interp (vl :: vsl) vsr pl (<?> mr) -∗ - ∃ pr, iMsg_car mr vl (Next pr) ∗ ▷ iProto_interp vsl vsr pl pr. - Proof. - iDestruct 1 as (p) "[Hp Hdp] /=". - iDestruct (iProto_le_recv_inv with "Hdp") as (m) "[#Hm Hpr]". - iDestruct (iProto_message_equivI with "Hm") as (_) "{Hm} #Hm". - iDestruct ("Hpr" $! vl (iProto_app_recvs vsl (iProto_dual p)) with "[]") - as (pr'') "[Hler Hpr]". - { iRewrite -("Hm" $! vl (Next (iProto_app_recvs vsl (iProto_dual p)))). - rewrite iMsg_base_eq; auto. } - iExists pr''. iIntros "{$Hpr} !>". iExists p. iFrame. - Qed. - Global Instance iProto_own_ne γ s : NonExpansive (iProto_own γ s). Proof. solve_proper. Qed. Global Instance iProto_own_proper γ s : Proper ((≡) ==> (≡)) (iProto_own γ s). @@ -1121,8 +1185,7 @@ Section proto. Lemma iProto_init p : ⊢ |==> ∃ γ, - iProto_ctx γ [] [] ∗ - iProto_own γ Left p ∗ iProto_own γ Right (iProto_dual p). + iProto_ctx γ ∗ iProto_own γ Left p ∗ iProto_own γ Right (iProto_dual p). Proof. iMod (own_alloc (●E (Next p) ⋅ ◯E (Next p))) as (lγ) "[H●l H◯l]". { by apply excl_auth_valid. } @@ -1130,166 +1193,154 @@ Section proto. ◯E (Next (iProto_dual p)))) as (rγ) "[H●r H◯r]". { by apply excl_auth_valid. } pose (ProtName lγ rγ) as γ. iModIntro. iExists γ. iSplitL "H●l H●r". - { iExists p, (iProto_dual p). iFrame. iApply iProto_interp_nil. } + { iExists p, (iProto_dual p). iFrame. iApply iProto_consistent_dual. } iSplitL "H◯l"; iExists _; iFrame; iApply iProto_le_refl. Qed. - Lemma iProto_send_l γ m vsr vsl vl p : - iProto_ctx γ vsl vsr -∗ - iProto_own γ Left (<!> m) -∗ - iMsg_car m vl (Next p) ==∗ - ▷^(length vsr) iProto_ctx γ (vsl ++ [vl]) vsr ∗ - iProto_own γ Left p. - Proof. - iDestruct 1 as (pl pr) "(H●l & H●r & Hinterp)". - iDestruct 1 as (pl') "[Hle H◯]". iIntros "Hm". - iDestruct (iProto_own_auth_agree with "H●l H◯") as "#Hp". - iAssert (▷ (pl ⊑ <!> m))%I - with "[Hle]" as "{Hp} Hle"; first (iNext; by iRewrite "Hp"). - iDestruct (iProto_interp_le_l with "Hinterp Hle") as "Hinterp". - iDestruct (iProto_interp_send with "Hinterp [Hm //]") as "Hinterp". - iMod (iProto_own_auth_update _ _ _ _ p with "H●l H◯") as "[H●l H◯]". - iIntros "!>". iSplitR "H◯". - - iIntros "!>". iExists p, pr. iFrame. - - iExists p. iFrame. iApply iProto_le_refl. - Qed. - - Lemma iProto_send_r γ m vsr vsl vr p : - iProto_ctx γ vsl vsr -∗ - iProto_own γ Right (<!> m) -∗ - iMsg_car m vr (Next p) ==∗ - ▷^(length vsl) iProto_ctx γ vsl (vsr ++ [vr]) ∗ - iProto_own γ Right p. - Proof. - iDestruct 1 as (pl pr) "(H●l & H●r & Hinterp)". - iDestruct 1 as (pr') "[Hle H◯]". iIntros "Hm". - iDestruct (iProto_own_auth_agree with "H●r H◯") as "#Hp". - iAssert (▷ (pr ⊑ <!> m))%I - with "[Hle]" as "{Hp} Hle"; first (iNext; by iRewrite "Hp"). - iDestruct (iProto_interp_flip with "Hinterp") as "Hinterp". - iDestruct (iProto_interp_le_l with "Hinterp Hle") as "Hinterp". - iDestruct (iProto_interp_send with "Hinterp [Hm //]") as "Hinterp". - iMod (iProto_own_auth_update _ _ _ _ p with "H●r H◯") as "[H●r H◯]". - iIntros "!>". iSplitR "H◯". - - iIntros "!>". iExists pl, p. iFrame. by iApply iProto_interp_flip. - - iExists p. iFrame. iApply iProto_le_refl. - Qed. - - Lemma iProto_recv_l γ m vr vsr vsl : - iProto_ctx γ vsl (vr :: vsr) -∗ - iProto_own γ Left (<?> m) ==∗ - ▷ ∃ p, - iProto_ctx γ vsl vsr ∗ - iProto_own γ Left p ∗ - iMsg_car m vr (Next p). - Proof. - iDestruct 1 as (pl pr) "(H●l & H●r & Hinterp)". - iDestruct 1 as (p) "[Hle H◯]". - iDestruct (iProto_own_auth_agree with "H●l H◯") as "#Hp". - iDestruct (iProto_interp_le_l with "Hinterp [Hle]") as "Hinterp". - { iIntros "!>". by iRewrite "Hp". } - iDestruct (iProto_interp_flip with "Hinterp") as "Hinterp". - iDestruct (iProto_interp_recv with "Hinterp") as (q) "[Hm Hinterp]". - iMod (iProto_own_auth_update _ _ _ _ q with "H●l H◯") as "[H●l H◯]". - iIntros "!> !> /=". iExists q. iFrame "Hm". iSplitR "H◯". - - iExists q, pr. iFrame. by iApply iProto_interp_flip. - - iExists q. iIntros "{$H◯} !>". iApply iProto_le_refl. - Qed. - - Lemma iProto_recv_r γ m vl vsr vsl : - iProto_ctx γ (vl :: vsl) vsr -∗ - iProto_own γ Right (<?> m) ==∗ - ▷ ∃ p, - iProto_ctx γ vsl vsr ∗ - iProto_own γ Right p ∗ - iMsg_car m vl (Next p). - Proof. - iDestruct 1 as (pl pr) "(H●l & H●r & Hinterp)". - iDestruct 1 as (p) "[Hle H◯]". - iDestruct (iProto_own_auth_agree with "H●r H◯") as "#Hp". - iDestruct (iProto_interp_le_r with "Hinterp [Hle]") as "Hinterp". - { iIntros "!>". by iRewrite "Hp". } - iDestruct (iProto_interp_recv with "Hinterp") as (q) "[Hm Hinterp]". - iMod (iProto_own_auth_update _ _ _ _ q with "H●r H◯") as "[H●r H◯]". - iIntros "!> !> /=". iExists q. iFrame "Hm". iSplitR "H◯". - - iExists pl, q. iFrame. - - iExists q. iIntros "{$H◯} !>". iApply iProto_le_refl. - Qed. - - (** The instances below make it possible to use the tactics [iIntros], - [iExist], [iSplitL]/[iSplitR], [iFrame] and [iModIntro] on [iProto_le] goals. *) - Global Instance iProto_le_from_forall_l {A} a (m1 : A → iMsg Σ V) m2 name : - AsIdentName m1 name → - FromForall (iProto_message Recv (iMsg_exist m1) ⊑ (<a> m2)) - (λ x, (<?> m1 x) ⊑ (<a> m2))%I name | 10. - Proof. intros _. apply iProto_le_exist_elim_l. Qed. - Global Instance iProto_le_from_forall_r {A} a m1 (m2 : A → iMsg Σ V) name : - AsIdentName m2 name → - FromForall ((<a> m1) ⊑ iProto_message Send (iMsg_exist m2)) - (λ x, (<a> m1) ⊑ (<!> m2 x))%I name | 11. - Proof. intros _. apply iProto_le_exist_elim_r. Qed. - - Global Instance iProto_le_from_wand_l a m v P p : - TCIf (TCEq P True%I) False TCTrue → - FromWand ((<?> MSG v {{ P }}; p) ⊑ (<a> m)) P ((<?> MSG v; p) ⊑ (<a> m)) | 10. - Proof. intros _. apply iProto_le_payload_elim_l. Qed. - Global Instance iProto_le_from_wand_r a m v P p : - FromWand ((<a> m) ⊑ (<!> MSG v {{ P }}; p)) P ((<a> m) ⊑ (<!> MSG v; p)) | 11. - Proof. apply iProto_le_payload_elim_r. Qed. - - Global Instance iProto_le_from_exist_l {A} (m : A → iMsg Σ V) p : - FromExist ((<! x> m x) ⊑ p) (λ a, (<!> m a) ⊑ p)%I | 10. - Proof. - rewrite /FromExist. iDestruct 1 as (x) "H". - iApply (iProto_le_trans with "[] H"). iApply iProto_le_exist_intro_l. - Qed. - Global Instance iProto_le_from_exist_r {A} (m : A → iMsg Σ V) p : - FromExist (p ⊑ <? x> m x) (λ a, p ⊑ (<?> m a))%I | 11. - Proof. - rewrite /FromExist. iDestruct 1 as (x) "H". - iApply (iProto_le_trans with "H"). iApply iProto_le_exist_intro_r. - Qed. - - Global Instance iProto_le_from_sep_l m v P p : - FromSep ((<!> MSG v {{ P }}; p) ⊑ (<!> m)) P ((<!> MSG v; p) ⊑ (<!> m)) | 10. - Proof. - rewrite /FromSep. iIntros "[HP H]". - iApply (iProto_le_trans with "[HP] H"). by iApply iProto_le_payload_intro_l. - Qed. - Global Instance iProto_le_from_sep_r m v P p : - FromSep ((<?> m) ⊑ (<?> MSG v {{ P }}; p)) P ((<?> m) ⊑ (<?> MSG v; p)) | 11. - Proof. - rewrite /FromSep. iIntros "[HP H]". - iApply (iProto_le_trans with "H"). by iApply iProto_le_payload_intro_r. - Qed. - - Global Instance iProto_le_frame_l q m v R P Q p : - Frame q R P Q → - Frame q R ((<!> MSG v {{ P }}; p) ⊑ (<!> m)) - ((<!> MSG v {{ Q }}; p) ⊑ (<!> m)) | 10. - Proof. - rewrite /Frame /=. iIntros (HP) "[HR H]". - iApply (iProto_le_trans with "[HR] H"). iApply iProto_le_payload_elim_r. - iIntros "HQ". iApply iProto_le_payload_intro_l. iApply HP; iFrame. - Qed. - Global Instance iProto_le_frame_r q m v R P Q p : - Frame q R P Q → - Frame q R ((<?> m) ⊑ (<?> MSG v {{ P }}; p)) - ((<?> m) ⊑ (<?> MSG v {{ Q }}; p)) | 11. - Proof. - rewrite /Frame /=. iIntros (HP) "[HR H]". - iApply (iProto_le_trans with "H"). iApply iProto_le_payload_elim_l. - iIntros "HQ". iApply iProto_le_payload_intro_r. iApply HP; iFrame. - Qed. - - Global Instance iProto_le_from_modal a v p1 p2 : - FromModal True (modality_instances.modality_laterN 1) (p1 ⊑ p2) - ((<a> MSG v; p1) ⊑ (<a> MSG v; p2)) (p1 ⊑ p2). - Proof. intros _. apply iProto_le_base. Qed. + Definition side_dual s := + match s with + | Left => Right + | Right => Left + end. + + Lemma iProto_step_l γ m1 m2 p1 v : + iProto_ctx γ -∗ iProto_own γ Left (<!> m1) -∗ iProto_own γ Right (<?> m2) -∗ + iMsg_car m1 v (Next p1) ==∗ + ▷ ∃ p2, iMsg_car m2 v (Next p2) ∗ ▷ iProto_ctx γ ∗ + iProto_own γ Left p1 ∗ iProto_own γ Right p2. + Proof. + iDestruct 1 as (pl pr) "(H●l & H●r & Hconsistent)". + iDestruct 1 as (pl') "[Hlel H◯l]". + iDestruct 1 as (pr') "[Hler H◯r]". + iIntros "Hm". + iDestruct (iProto_own_auth_agree with "H●l H◯l") as "#Hpl". + iDestruct (iProto_own_auth_agree with "H●r H◯r") as "#Hpr". + iAssert (▷ (pl ⊑ <!> m1))%I + with "[Hlel]" as "{Hpl} Hlel"; first (iNext; by iRewrite "Hpl"). + iAssert (▷ (pr ⊑ <?> m2))%I + with "[Hler]" as "{Hpr} Hler"; first (iNext; by iRewrite "Hpr"). + iDestruct (iProto_consistent_le_l with "Hconsistent Hlel") as "Hconsistent". + iDestruct (iProto_consistent_le_r with "Hconsistent Hler") as "Hconsistent". + iDestruct (iProto_consistent_step with "Hconsistent [Hm //]") as + (p2) "[Hm2 Hconsistent]". + iMod (iProto_own_auth_update _ _ _ _ p1 with "H●l H◯l") as "[H●l H◯l]". + iMod (iProto_own_auth_update _ _ _ _ p2 with "H●r H◯r") as "[H●r H◯r]". + iIntros "!>!>". + iExists p2. iFrame. + iSplitL "Hconsistent H●l H●r". + - iExists _, _. iFrame. + - iSplitL "H◯l". + + iExists _. iFrame. iApply iProto_le_refl. + + iExists _. iFrame. iApply iProto_le_refl. + Qed. + + Lemma iProto_step_r γ m1 m2 p2 v : + iProto_ctx γ -∗ iProto_own γ Left (<?> m1) -∗ iProto_own γ Right (<!> m2) -∗ + iMsg_car m2 v (Next p2) ==∗ + ▷ ∃ p1, iMsg_car m1 v (Next p1) ∗ ▷ iProto_ctx γ ∗ + iProto_own γ Left p1 ∗ iProto_own γ Right p2. + Proof. + iDestruct 1 as (pl pr) "(H●l & H●r & Hconsistent)". + iDestruct 1 as (pl') "[Hlel H◯l]". + iDestruct 1 as (pr') "[Hler H◯r]". + iIntros "Hm". + iDestruct (iProto_own_auth_agree with "H●l H◯l") as "#Hpl". + iDestruct (iProto_own_auth_agree with "H●r H◯r") as "#Hpr". + iAssert (▷ (pl ⊑ <?> m1))%I + with "[Hlel]" as "{Hpl} Hlel"; first (iNext; by iRewrite "Hpl"). + iAssert (▷ (pr ⊑ <!> m2))%I + with "[Hler]" as "{Hpr} Hler"; first (iNext; by iRewrite "Hpr"). + iDestruct (iProto_consistent_le_l with "Hconsistent Hlel") as "Hconsistent". + iDestruct (iProto_consistent_le_r with "Hconsistent Hler") as "Hconsistent". + iDestruct (iProto_consistent_flip with "Hconsistent") as + "Hconsistent". + iDestruct (iProto_consistent_step with "Hconsistent [Hm //]") as + (p1) "[Hm1 Hconsistent]". + iMod (iProto_own_auth_update _ _ _ _ p1 with "H●l H◯l") as "[H●l H◯l]". + iMod (iProto_own_auth_update _ _ _ _ p2 with "H●r H◯r") as "[H●r H◯r]". + iIntros "!>!>". + iExists p1. iFrame. + iSplitL "Hconsistent H●l H●r". + - iExists _, _. iFrame. iApply iProto_consistent_flip. iFrame. + - iSplitL "H◯l". + + iExists _. iFrame. iApply iProto_le_refl. + + iExists _. iFrame. iApply iProto_le_refl. + Qed. + + (* (** The instances below make it possible to use the tactics [iIntros], *) + (* [iExist], [iSplitL]/[iSplitR], [iFrame] and [iModIntro] on [iProto_le] goals. *) *) + (* Global Instance iProto_le_from_forall_l {A} a (m1 : A → iMsg Σ V) m2 name : *) + (* AsIdentName m1 name → *) + (* FromForall (iProto_message Recv (iMsg_exist m1) ⊑ (<a> m2)) *) + (* (λ x, (<?> m1 x) ⊑ (<a> m2))%I name | 10. *) + (* Proof. intros _. apply iProto_le_exist_elim_l. Qed. *) + (* Global Instance iProto_le_from_forall_r {A} a m1 (m2 : A → iMsg Σ V) name : *) + (* AsIdentName m2 name → *) + (* FromForall ((<a> m1) ⊑ iProto_message Send (iMsg_exist m2)) *) + (* (λ x, (<a> m1) ⊑ (<!> m2 x))%I name | 11. *) + (* Proof. intros _. apply iProto_le_exist_elim_r. Qed. *) + + (* Global Instance iProto_le_from_wand_l a m v P p : *) + (* TCIf (TCEq P True%I) False TCTrue → *) + (* FromWand ((<?> MSG v {{ P }}; p) ⊑ (<a> m)) P ((<?> MSG v; p) ⊑ (<a> m)) | 10. *) + (* Proof. intros _. apply iProto_le_payload_elim_l. Qed. *) + (* Global Instance iProto_le_from_wand_r a m v P p : *) + (* FromWand ((<a> m) ⊑ (<!> MSG v {{ P }}; p)) P ((<a> m) ⊑ (<!> MSG v; p)) | 11. *) + (* Proof. apply iProto_le_payload_elim_r. Qed. *) + + (* Global Instance iProto_le_from_exist_l {A} (m : A → iMsg Σ V) p : *) + (* FromExist ((<! x> m x) ⊑ p) (λ a, (<!> m a) ⊑ p)%I | 10. *) + (* Proof. *) + (* rewrite /FromExist. iDestruct 1 as (x) "H". *) + (* iApply (iProto_le_trans with "[] H"). iApply iProto_le_exist_intro_l. *) + (* Qed. *) + (* Global Instance iProto_le_from_exist_r {A} (m : A → iMsg Σ V) p : *) + (* FromExist (p ⊑ <? x> m x) (λ a, p ⊑ (<?> m a))%I | 11. *) + (* Proof. *) + (* rewrite /FromExist. iDestruct 1 as (x) "H". *) + (* iApply (iProto_le_trans with "H"). iApply iProto_le_exist_intro_r. *) + (* Qed. *) + + (* Global Instance iProto_le_from_sep_l m v P p : *) + (* FromSep ((<!> MSG v {{ P }}; p) ⊑ (<!> m)) P ((<!> MSG v; p) ⊑ (<!> m)) | 10. *) + (* Proof. *) + (* rewrite /FromSep. iIntros "[HP H]". *) + (* iApply (iProto_le_trans with "[HP] H"). by iApply iProto_le_payload_intro_l. *) + (* Qed. *) + (* Global Instance iProto_le_from_sep_r m v P p : *) + (* FromSep ((<?> m) ⊑ (<?> MSG v {{ P }}; p)) P ((<?> m) ⊑ (<?> MSG v; p)) | 11. *) + (* Proof. *) + (* rewrite /FromSep. iIntros "[HP H]". *) + (* iApply (iProto_le_trans with "H"). by iApply iProto_le_payload_intro_r. *) + (* Qed. *) + + (* Global Instance iProto_le_frame_l q m v R P Q p : *) + (* Frame q R P Q → *) + (* Frame q R ((<!> MSG v {{ P }}; p) ⊑ (<!> m)) *) + (* ((<!> MSG v {{ Q }}; p) ⊑ (<!> m)) | 10. *) + (* Proof. *) + (* rewrite /Frame /=. iIntros (HP) "[HR H]". *) + (* iApply (iProto_le_trans with "[HR] H"). iApply iProto_le_payload_elim_r. *) + (* iIntros "HQ". iApply iProto_le_payload_intro_l. iApply HP; iFrame. *) + (* Qed. *) + (* Global Instance iProto_le_frame_r q m v R P Q p : *) + (* Frame q R P Q → *) + (* Frame q R ((<?> m) ⊑ (<?> MSG v {{ P }}; p)) *) + (* ((<?> m) ⊑ (<?> MSG v {{ Q }}; p)) | 11. *) + (* Proof. *) + (* rewrite /Frame /=. iIntros (HP) "[HR H]". *) + (* iApply (iProto_le_trans with "H"). iApply iProto_le_payload_elim_l. *) + (* iIntros "HQ". iApply iProto_le_payload_intro_r. iApply HP; iFrame. *) + (* Qed. *) + + (* Global Instance iProto_le_from_modal a v p1 p2 : *) + (* FromModal True (modality_instances.modality_laterN 1) (p1 ⊑ p2) *) + (* ((<a> MSG v; p1) ⊑ (<a> MSG v; p2)) (p1 ⊑ p2). *) + (* Proof. intros _. apply iProto_le_base. Qed. *) End proto. -Global Typeclasses Opaque iProto_ctx iProto_own. +Typeclasses Opaque iProto_ctx iProto_own. Global Hint Extern 0 (environments.envs_entails _ (?x ⊑ ?y)) => first [is_evar x; fail 1 | is_evar y; fail 1|iApply iProto_le_refl] : core.