Commit 9524aefb authored by Robbert Krebbers's avatar Robbert Krebbers

Add an ordering to protocols and allow protocol ownership to be weakened.

This idea is taken from the paper "Towards a session logic for
communication protocols" by Cracium et al.
parent 0eb2c8f4
Pipeline #21203 passed with stage
in 5 minutes and 11 seconds
......@@ -196,7 +196,24 @@ Infix "<++>" := iProto_app (at level 60) : proto_scope.
Definition proto_eq_next {Σ} (p : iProto Σ) : laterO (iProto Σ) -n> iPropO Σ :=
OfeMor (sbi_internal_eq (Next p)).
Fixpoint proto_interp `{!proto_chanG Σ} (vs : list val) (p1 p2 : iProto Σ) : iProp Σ :=
Program Definition iProto_le_aux {Σ} (rec : iProto Σ -n> iProto Σ -n> iPropO Σ) :
iProto Σ -n> iProto Σ -n> iPropO Σ := λne p1 p2,
((p1 proto_end p2 proto_end)
( pc1 pc2,
p1 proto_message Send pc1 p2 proto_message Send pc2
v p2', pc2 v (proto_eq_next p2') -
p1', rec p1' p2' pc1 v (proto_eq_next p1'))
( pc1 pc2,
p1 proto_message Receive pc1 p2 proto_message Receive pc2
v p1', pc1 v (proto_eq_next p1') -
p2', rec p1' p2' pc2 v (proto_eq_next p2')))%I.
Solve Obligations with solve_proper.
Local Instance iProto_le_aux_contractive {Σ} : Contractive (@iProto_le_aux Σ).
Proof. solve_contractive. Qed.
Definition iProto_le {Σ} (p1 p2 : iProto Σ) : iPropO Σ :=
fixpoint iProto_le_aux p1 p2.
Fixpoint proto_interp {Σ} (vs : list val) (p1 p2 : iProto Σ) : iProp Σ :=
match vs with
| [] => iProto_dual p1 p2
| v :: vs => pc p2',
......@@ -204,7 +221,7 @@ Fixpoint proto_interp `{!proto_chanG Σ} (vs : list val) (p1 p2 : iProto Σ) : i
pc v (proto_eq_next p2')
proto_interp vs p1 p2'
end%I.
Arguments proto_interp {_ _} _ _%proto _%proto : simpl nomatch.
Arguments proto_interp {_} _ _%proto _%proto : simpl nomatch.
Record proto_name := ProtName {
proto_c_name : chan_name;
......@@ -212,7 +229,7 @@ Record proto_name := ProtName {
proto_r_name : gname
}.
Definition to_proto_auth_excl `{!proto_chanG Σ} (p : iProto Σ) :=
Definition to_proto_auth_excl {Σ} (p : iProto Σ) :=
to_auth_excl (Next (proto_map id iProp_fold iProp_unfold p)).
Definition proto_own_frag `{!proto_chanG Σ} (γ : proto_name) (s : side)
......@@ -237,9 +254,12 @@ Definition protoN := nroot .@ "proto".
(** * The connective for ownership of channel ends *)
Definition mapsto_proto_def `{!proto_chanG Σ, !heapG Σ}
(c : val) (p : iProto Σ) : iProp Σ :=
( s (c1 c2 : val) γ,
( s (c1 c2 : val) γ p',
c = side_elim s c1 c2
proto_own_frag γ s p is_chan protoN (proto_c_name γ) c1 c2 inv protoN (proto_inv γ))%I.
iProto_le p' p
proto_own_frag γ s p'
is_chan protoN (proto_c_name γ) c1 c2
inv protoN (proto_inv γ))%I.
Definition mapsto_proto_aux : seal (@mapsto_proto_def). by eexists. Qed.
Definition mapsto_proto {Σ pΣ hΣ} := mapsto_proto_aux.(unseal) Σ pΣ hΣ.
Definition mapsto_proto_eq : @mapsto_proto = @mapsto_proto_def := mapsto_proto_aux.(seal_eq).
......@@ -379,13 +399,143 @@ Section proto.
iProto_dual (p1 <++> p2) (iProto_dual p1 <++> iProto_dual p2)%proto.
Proof. by rewrite /iProto_dual /iProto_app proto_map_app. Qed.
(** ** Protocol entailment **)
Global Instance iProto_le_ne : NonExpansive2 (@iProto_le Σ).
Proof. solve_proper. Qed.
Global Instance iProto_le_proper : Proper (() ==> () ==> ()) (@iProto_le Σ).
Proof. solve_proper. Qed.
Lemma iProto_le_unfold p1 p2 :
iProto_le p1 p2 iProto_le_aux (fixpoint iProto_le_aux) p1 p2.
Proof. apply: (fixpoint_unfold iProto_le_aux). Qed.
Lemma iProto_le_refl p : iProto_le p p.
Proof.
iLöb as "IH" forall (p). destruct (proto_case p) as [->|([]&pc&->)].
- rewrite iProto_le_unfold. iLeft; by auto.
- rewrite iProto_le_unfold. iRight; iLeft. iExists _, _; do 2 (iSplit; [done|]).
iIntros (v p') "Hpc". iExists p'. iFrame "Hpc". iNext. iApply "IH".
- rewrite iProto_le_unfold. iRight; iRight. iExists _, _; do 2 (iSplit; [done|]).
iIntros (v p') "Hpc". iExists p'. iFrame "Hpc". iNext. iApply "IH".
Qed.
Lemma iProto_le_end_inv p : iProto_le p proto_end - p proto_end.
Proof.
rewrite iProto_le_unfold. iIntros "[[Hp _]|H] //".
iDestruct "H" as "[H|H]"; iDestruct "H" as (pc1 pc2) "(_ & Heq & _)";
by rewrite proto_end_message_equivI.
Qed.
Lemma iProto_le_send_inv p1 pc2 :
iProto_le p1 (proto_message Send pc2) - pc1,
p1 proto_message Send pc1
v p2', pc2 v (proto_eq_next p2') -
p1', iProto_le p1' p2' pc1 v (proto_eq_next p1').
Proof.
rewrite iProto_le_unfold. iIntros "[[_ Heq]|[H|H]]".
- by rewrite proto_message_end_equivI.
- iDestruct "H" as (pc1 pc2') "(Hp1 & Heq & H)".
iDestruct (proto_message_equivI with "Heq") as "[_ #Heq]".
iExists pc1. iIntros "{$Hp1}" (v p2') "Hpc".
iSpecialize ("Heq" $! v). iDestruct (bi.ofe_morO_equivI with "Heq") as "Heq'".
iRewrite ("Heq'" $! (proto_eq_next p2')) in "Hpc". by iApply "H".
- iDestruct "H" as (pc1 pc2') "(_ & Heq & _)".
by iDestruct (proto_message_equivI with "Heq") as "[% ?]".
Qed.
Lemma iProto_le_recv_inv p1 pc2 :
iProto_le p1 (proto_message Receive pc2) - pc1,
p1 proto_message Receive pc1
v p1', pc1 v (proto_eq_next p1') -
p2', iProto_le p1' p2' pc2 v (proto_eq_next p2').
Proof.
rewrite iProto_le_unfold. iIntros "[[_ Heq]|[H|H]]".
- by rewrite proto_message_end_equivI.
- iDestruct "H" as (pc1 pc2') "(_ & Heq & _)".
by iDestruct (proto_message_equivI with "Heq") as "[% ?]".
- iDestruct "H" as (pc1 pc2') "(Hp1 & Heq & H)".
iDestruct (proto_message_equivI with "Heq") as "[_ #Heq]".
iExists pc1. iIntros "{$Hp1}" (v p1') "Hpc".
iSpecialize ("Heq" $! v). iDestruct (bi.ofe_morO_equivI with "Heq") as "Heq'".
iDestruct ("H" with "Hpc") as (p2') "[Hle Hpc]".
iExists p2'. iFrame "Hle". by iRewrite ("Heq'" $! (proto_eq_next p2')).
Qed.
Lemma iProto_le_trans p1 p2 p3 :
iProto_le p1 p2 - iProto_le p2 p3 - iProto_le p1 p3.
Proof.
iIntros "H1 H2". iLöb as "IH" forall (p1 p2 p3).
destruct (proto_case p3) as [->|([]&pc3&->)].
- rewrite iProto_le_end_inv. by iRewrite "H2" in "H1".
- iDestruct (iProto_le_send_inv with "H2") as (pc2) "[Hp2 H3]".
iRewrite "Hp2" in "H1".
iDestruct (iProto_le_send_inv with "H1") as (pc1) "[Hp1 H2]".
iRewrite "Hp1". rewrite iProto_le_unfold; iRight; iLeft.
iExists _, _; do 2 (iSplit; [done|]).
iIntros (v p3') "Hpc".
iDestruct ("H3" with "Hpc") as (p2') "[Hle Hpc]".
iDestruct ("H2" with "Hpc") as (p1') "[Hle' Hpc]".
iExists p1'. iIntros "{$Hpc} !>". by iApply ("IH" with "Hle'").
- iDestruct (iProto_le_recv_inv with "H2") as (pc2) "[Hp2 H3]".
iRewrite "Hp2" in "H1".
iDestruct (iProto_le_recv_inv with "H1") as (pc1) "[Hp1 H2]".
iRewrite "Hp1". rewrite iProto_le_unfold; iRight; iRight.
iExists _, _; do 2 (iSplit; [done|]).
iIntros (v p1') "Hpc".
iDestruct ("H2" with "Hpc") as (p2') "[Hle Hpc]".
iDestruct ("H3" with "Hpc") as (p3') "[Hle' Hpc]".
iExists p3'. iIntros "{$Hpc} !>". by iApply ("IH" with "Hle").
Qed.
Lemma iProto_send_le {TT1 TT2} (pc1 : TT1 val * iProp Σ * iProto Σ)
(pc2 : TT2 val * iProp Σ * iProto Σ) :
(.. x2 : TT2, .. x1 : TT1,
(pc1 x1).1.1 = (pc2 x2).1.1
((pc2 x2).1.2 - (pc1 x1).1.2)
iProto_le (pc1 x1).2 (pc2 x2).2) -
iProto_le (iProto_message Send pc1) (iProto_message Send pc2).
Proof.
iIntros "H". rewrite iProto_le_unfold iProto_message_eq. iRight; iLeft.
iExists _, _; do 2 (iSplit; [done|]).
iIntros (v p2') "/=". iDestruct 1 as (x2 ->) "[Hpc2 #Heq]".
iDestruct ("H" $! x2) as (x1 ?) "[Hpc Hle]". iExists (pc1 x1).2. iSplitL "Hle".
{ iNext. change (fixpoint iProto_le_aux ?p1 ?p2) with (iProto_le p1 p2).
by iRewrite "Heq". }
iExists x1. iSplit; [done|]. iSplit; [by iApply "Hpc"|done].
Qed.
Lemma iProto_recv_le {TT1 TT2} (pc1 : TT1 val * iProp Σ * iProto Σ)
(pc2 : TT2 val * iProp Σ * iProto Σ) :
(.. x1 : TT1, .. x2 : TT2,
(pc1 x1).1.1 = (pc2 x2).1.1
((pc1 x1).1.2 - (pc2 x2).1.2)
iProto_le (pc1 x1).2 (pc2 x2).2) -
iProto_le (iProto_message Receive pc1) (iProto_message Receive pc2).
Proof.
iIntros "H". rewrite iProto_le_unfold iProto_message_eq. iRight; iRight.
iExists _, _; do 2 (iSplit; [done|]).
iIntros (v p1') "/=". iDestruct 1 as (x1 ->) "[Hpc1 #Heq]".
iDestruct ("H" $! x1) as (x2 ?) "[Hpc Hle]". iExists (pc2 x2).2. iSplitL "Hle".
{ iNext. change (fixpoint iProto_le_aux ?p1 ?p2) with (iProto_le p1 p2).
by iRewrite "Heq". }
iExists x2. iSplit; [done|]. iSplit; [by iApply "Hpc"|done].
Qed.
Lemma iProto_mapsto_le c p1 p2 : c p1 - iProto_le p1 p2 - c p2.
Proof.
rewrite mapsto_proto_eq. iDestruct 1 as (s c1 c2 γ p1' ->) "[Hle H]".
iIntros "Hle'". iExists s, c1, c2, γ, p1'. iSplit; first done. iFrame "H".
by iApply (iProto_le_trans with "Hle").
Qed.
(** ** Auxiliary definitions and invariants *)
Global Instance proto_interp_ne : NonExpansive2 (proto_interp vs).
Global Instance proto_interp_ne : NonExpansive2 (proto_interp (Σ:=Σ) vs).
Proof. induction vs; solve_proper. Qed.
Global Instance proto_interp_proper vs : Proper (() ==> () ==> ()) (proto_interp vs).
Global Instance proto_interp_proper vs :
Proper (() ==> () ==> ()) (proto_interp (Σ:=Σ) vs).
Proof. apply (ne_proper_2 _). Qed.
Global Instance to_proto_auth_excl_ne : NonExpansive to_proto_auth_excl.
Global Instance to_proto_auth_excl_ne : NonExpansive (to_proto_auth_excl (Σ:=Σ)).
Proof. solve_proper. Qed.
Global Instance proto_own_ne γ s : NonExpansive (proto_own_frag γ s).
Proof. solve_proper. Qed.
......@@ -484,8 +634,10 @@ Section proto.
iMod (inv_alloc protoN _ (proto_inv pγ) with "[-Hlstf Hrstf Hcctx]") as "#Hinv".
{ iNext. rewrite /proto_inv. eauto 10 with iFrame. }
iModIntro. rewrite mapsto_proto_eq. iSplitL "Hlstf".
- iExists Left, c1, c2, pγ; iFrame; auto.
- iExists Right, c1, c2, pγ; iFrame; auto.
- iExists Left, c1, c2, pγ, p.
iFrame "Hlstf Hinv Hcctx". iSplit; [done|]. iApply iProto_le_refl.
- iExists Right, c1, c2, pγ, (iProto_dual p).
iFrame "Hrstf Hinv Hcctx". iSplit; [done|]. iApply iProto_le_refl.
Qed.
(** ** Accessor style lemmas *)
......@@ -501,47 +653,49 @@ Section proto.
c (pc x).2.
Proof.
iIntros (?). rewrite {1}mapsto_proto_eq iProto_message_eq.
iDestruct 1 as (s c1 c2 γ ->) "[Hstf #[Hcctx Hinv]]".
iDestruct 1 as (s c1 c2 γ p ->) "(Hle & Hst & #[Hcctx Hinv])".
iExists s, c1, c2, γ. iSplit; first done. iFrame "Hcctx".
iInv protoN as (l r pl pr) "(>Hclf & >Hcrf & Hstla & Hstra & Hinv')" "Hclose".
iInv protoN as (l r pl pr) "(>Hcl & >Hcr & Hstla & Hstra & Hinv')" "Hclose".
(* TODO: refactor to avoid twice nearly the same proof *)
iModIntro. destruct s.
- iExists _.
iIntros "{$Hclf} !>" (x) "HP Hclf".
iRename "Hstf" into "Hstlf".
iDestruct (proto_own_auth_agree with "Hstla Hstlf") as "#Heq".
iMod (proto_own_auth_update _ _ _ _ (pc x).2
with "Hstla Hstlf") as "[Hstla Hstlf]".
iMod ("Hclose" with "[-Hstlf]") as "_".
{ iNext. iExists _,_,_,_. iFrame "Hcrf Hstra Hstla Hclf". iLeft.
iIntros "{$Hcl} !>" (x) "HP Hcl".
iDestruct (iProto_le_send_inv with "Hle") as (pc') "[Hp H] /=".
iRewrite "Hp" in "Hst"; clear p.
iDestruct ("H" with "[HP]") as (p1') "[Hle HP]".
{ iExists _. iFrame "HP". by iSplit. }
iDestruct (proto_own_auth_agree with "Hstla Hst") as "#Heq".
iMod (proto_own_auth_update _ _ _ _ p1' with "Hstla Hst") as "[Hstla Hst]".
iMod ("Hclose" with "[-Hst Hle]") as "_".
{ iNext. iExists _,_,_,_. iFrame "Hcr Hstra Hstla Hcl". iLeft.
iRewrite "Heq" in "Hinv'".
iDestruct "Hinv'" as "[[-> Heval]|[-> Heval]]".
{ iSplit=> //. iApply (proto_interp_send with "Heval [HP]"); simpl.
iExists x. by iFrame. }
{ iSplit=> //. by iApply (proto_interp_send with "Heval [HP]"). }
destruct r as [|vr r]; last first.
{ iDestruct (proto_interp_False with "Heval") as %[]. }
iSplit; first done; simpl. iRewrite (proto_interp_nil with "Heval").
iApply (proto_interp_send _ [] with "[//] [HP]").
iExists x. by iFrame. }
iModIntro. rewrite mapsto_proto_eq. iExists Left, c1, c2, γ. iFrame; auto.
iApply (proto_interp_send _ [] with "[//] HP"). }
iModIntro. rewrite mapsto_proto_eq. iExists Left, c1, c2, γ, p1'.
by iFrame "Hcctx Hinv Hst Hle".
- iExists _.
iIntros "{$Hcrf} !>" (x) "HP Hcrf".
iRename "Hstf" into "Hstrf".
iDestruct (proto_own_auth_agree with "Hstra Hstrf") as "#Heq".
iMod (proto_own_auth_update _ _ _ _ (pc x).2
with "Hstra Hstrf") as "[Hstra Hstrf]".
iMod ("Hclose" with "[-Hstrf]") as "_".
{ iNext. iExists _, _, _, _. iFrame "Hcrf Hstra Hstla Hclf". iRight.
iIntros "{$Hcr} !>" (x) "HP Hcr".
iDestruct (iProto_le_send_inv with "Hle") as (pc') "[Hp H] /=".
iRewrite "Hp" in "Hst"; clear p.
iDestruct ("H" with "[HP]") as (p1') "[Hle HP]".
{ iExists _. iFrame "HP". by iSplit. }
iDestruct (proto_own_auth_agree with "Hstra Hst") as "#Heq".
iMod (proto_own_auth_update _ _ _ _ p1' with "Hstra Hst") as "[Hstra Hst]".
iMod ("Hclose" with "[-Hst Hle]") as "_".
{ iNext. iExists _, _, _, _. iFrame "Hcl Hstra Hstla Hcr". iRight.
iRewrite "Heq" in "Hinv'".
iDestruct "Hinv'" as "[[-> Heval]|[-> Heval]]"; last first.
{ iSplit=> //. iApply (proto_interp_send with "Heval [HP]"); simpl.
iExists x. by iFrame. }
{ iSplit=> //. by iApply (proto_interp_send with "Heval [HP]"). }
destruct l as [|vl l]; last first.
{ iDestruct (proto_interp_False with "Heval") as %[]. }
iSplit; first done; simpl. iRewrite (proto_interp_nil with "Heval").
iApply (proto_interp_send _ [] with "[//] [HP]").
iExists x. by iFrame. }
iModIntro. rewrite mapsto_proto_eq. iExists Right, c1, c2, γ. iFrame; auto.
iApply (proto_interp_send _ [] with "[//] HP"). }
iModIntro. rewrite mapsto_proto_eq. iExists Right, c1, c2, γ, p1'.
by iFrame "Hcctx Hinv Hst Hle".
Qed.
Lemma proto_recv_acc {TT} E c (pc : TT val * iProp Σ * iProto Σ) :
......@@ -558,60 +712,65 @@ Section proto.
v = (pc x).1.1 c (pc x).2 (pc x).1.2)).
Proof.
iIntros (?). rewrite {1}mapsto_proto_eq iProto_message_eq.
iDestruct 1 as (s c1 c2 γ ->) "[Hstf #[Hcctx Hinv]]".
iDestruct 1 as (s c1 c2 γ p ->) "(Hle & Hst & #[Hcctx Hinv])".
iDestruct (iProto_le_recv_inv with "Hle") as (pc') "[Hp Hle]".
iExists (side_elim s Right Left), c1, c2, γ. iSplit; first by destruct s.
iFrame "Hcctx".
iInv protoN as (l r pl pr) "(>Hclf & >Hcrf & Hstla & Hstra & Hinv')" "Hclose".
iInv protoN as (l r pl pr) "(>Hcl & >Hcr & Hstla & Hstra & Hinv')" "Hclose".
iExists (side_elim s r l). iModIntro.
(* TODO: refactor to avoid twice nearly the same proof *)
destruct s; simpl.
- iIntros "{$Hcrf} !>".
iRename "Hstf" into "Hstlf".
iDestruct (proto_own_auth_agree with "Hstla Hstlf") as "#Heq".
- iIntros "{$Hcr} !>". iRewrite "Hp" in "Hst". clear p.
iDestruct (proto_own_auth_agree with "Hstla Hst") as "#Heq".
iSplit.
+ iIntros "Hown".
iMod ("Hclose" with "[-Hstlf]") as "_".
+ iIntros "Hcr".
iMod ("Hclose" with "[-Hst Hle]") as "_".
{ iNext. iExists l, r, _, _. iFrame. }
iModIntro. rewrite mapsto_proto_eq.
iExists Left, c1, c2, γ. by iFrame "Hcctx ∗ Hinv".
+ iIntros (v vs ->) "Hown".
iExists Left, c1, c2, γ, (proto_message Receive pc').
iFrame "Hcctx Hinv Hst". iSplit; first done.
rewrite iProto_le_unfold. iModIntro. iRight; auto 10.
+ iIntros (v vs ->) "Hcr".
iDestruct "Hinv'" as "[[>% _]|[> -> Heval]]"; first done.
iAssert ( proto_interp (v :: vs) pr (iProto_message_def Receive pc))%I
iAssert ( proto_interp (v :: vs) pr (proto_message Receive pc'))%I
with "[Heval]" as "Heval".
{ iNext. by iRewrite "Heq" in "Heval". }
iDestruct (proto_interp_recv with "Heval") as (q) "[Hf Heval]".
iMod (proto_own_auth_update _ _ _ _ q with "Hstla Hstlf") as "[Hstla Hstlf]".
iMod ("Hclose" with "[-Hstlf Hf]") as %_.
{ iExists _, _,_ ,_. eauto 10 with iFrame. }
iDestruct (proto_interp_recv with "Heval") as (q) "[Hpc Heval]".
iMod (proto_own_auth_update _ _ _ _ q with "Hstla Hst") as "[Hstla Hst]".
iMod ("Hclose" with "[-Hst Hpc Hle]") as %_.
{ iExists _, _,_ ,_; iFrame; eauto. }
iIntros "!> !> /=".
iDestruct "Hf" as (x) "(Hv & HP & #Hf) /=".
iDestruct ("Hle" with "Hpc") as (q') "[Hle H]".
iDestruct "H" as (x) "(Hv & HP & #Hf) /=".
iNext. iExists x. iFrame "Hv HP". iRewrite -"Hf".
rewrite mapsto_proto_eq. iExists Left, c1, c2, γ. iFrame; auto.
- iIntros "{$Hclf} !>".
iRename "Hstf" into "Hstrf".
iDestruct (proto_own_auth_agree with "Hstra Hstrf") as "#Heq".
rewrite mapsto_proto_eq. iExists Left, c1, c2, γ, q. iFrame; auto.
- iIntros "{$Hcl} !>". iRewrite "Hp" in "Hst". clear p.
iDestruct (proto_own_auth_agree with "Hstra Hst") as "#Heq".
iSplit.
+ iIntros "Hown".
iMod ("Hclose" with "[-Hstrf]") as "_".
+ iIntros "Hcl".
iMod ("Hclose" with "[-Hst Hle]") as "_".
{ iNext. iExists l, r, _, _. iFrame. }
iModIntro. rewrite mapsto_proto_eq.
iExists Right, c1, c2, γ. by iFrame "Hcctx ∗ Hinv".
+ iIntros (v vs ->) "Hown".
iExists Right, c1, c2, γ, (proto_message Receive pc').
iFrame "Hcctx Hinv Hst". iSplit; first done.
rewrite iProto_le_unfold. iModIntro. iRight; auto 10.
+ iIntros (v vs ->) "Hcl".
iDestruct "Hinv'" as "[[>-> Heval]|[>% _]]"; last done.
iAssert ( proto_interp (v :: vs) pl (iProto_message_def Receive pc))%I
iAssert ( proto_interp (v :: vs) pl (proto_message Receive pc'))%I
with "[Heval]" as "Heval".
{ iNext. by iRewrite "Heq" in "Heval". }
iDestruct (proto_interp_recv with "Heval") as (q) "[Hf Heval]".
iMod (proto_own_auth_update _ _ _ _ q with "Hstra Hstrf") as "[Hstra Hstrf]".
iMod ("Hclose" with "[-Hstrf Hf]") as %_.
iDestruct (proto_interp_recv with "Heval") as (q) "[Hpc Heval]".
iMod (proto_own_auth_update _ _ _ _ q with "Hstra Hst") as "[Hstra Hst]".
iMod ("Hclose" with "[-Hst Hpc Hle]") as %_.
{ iExists _, _, _, _. eauto 10 with iFrame. }
iIntros "!> !>".
iDestruct "Hf" as (x) "(Hv & HP & Hf) /=".
iIntros "!> !> /=".
iDestruct ("Hle" with "Hpc") as (q') "[Hle H]".
iDestruct "H" as (x) "(Hv & HP & Hf) /=".
iNext. iExists x. iFrame "Hv HP". iRewrite -"Hf".
rewrite mapsto_proto_eq. iExists Right, c1, c2, γ. iFrame; auto.
rewrite mapsto_proto_eq. iExists Right, c1, c2, γ, q. iFrame; auto.
Qed.
(** ** Specifications of [send] and [receive] *)
(** ** Specifications of [send] and [recv] *)
Lemma new_chan_proto_spec :
{{{ True }}}
new_chan #()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment