From 80ce5d255abea16884988dd0ffa6e7974252ba59 Mon Sep 17 00:00:00 2001
From: Ralf Jung <jung@mpi-sws.org>
Date: Thu, 9 Mar 2017 17:39:27 +0100
Subject: [PATCH] Rc::clone

Also tune the simpl behavior of ty_own a little to be less eager with unfolding
---
 opam.pins                                  |  2 +-
 theories/typing/function.v                 |  2 +-
 theories/typing/lib/cell.v                 |  2 +-
 theories/typing/lib/rc.v                   | 88 +++++++++++++++++++---
 theories/typing/lib/refcell/ref_code.v     |  2 +-
 theories/typing/lib/refcell/refcell_code.v |  4 +-
 theories/typing/lib/refcell/refmut_code.v  |  2 +-
 theories/typing/lib/rwlock/rwlock_code.v   |  4 +-
 theories/typing/product_split.v            |  2 +-
 theories/typing/sum.v                      |  4 +-
 theories/typing/type.v                     |  4 +-
 theories/typing/type_sum.v                 |  4 +-
 12 files changed, 94 insertions(+), 26 deletions(-)

diff --git a/opam.pins b/opam.pins
index e9084293..0af3bc66 100644
--- a/opam.pins
+++ b/opam.pins
@@ -1 +1 @@
-coq-iris https://gitlab.mpi-sws.org/FP/iris-coq 21fbbdde77c9e8b5d9cf2ad908c0921528ca02f2
+coq-iris https://gitlab.mpi-sws.org/FP/iris-coq 5874f41e10c229d0b7df07a1e4e58f5e61a1af0a
diff --git a/theories/typing/function.v b/theories/typing/function.v
index 2182ff1a..8750b714 100644
--- a/theories/typing/function.v
+++ b/theories/typing/function.v
@@ -55,7 +55,7 @@ Section fn.
             type_dist2 n') fn.
   Proof.
     intros fp1 fp2 Hfp. apply ty_of_st_type_ne. destruct n'; first done.
-    constructor; simpl.
+    constructor; unfold ty_own; simpl.
     (* TODO: 'f_equiv' is slow here because reflexivity is slow. *)
     (* The clean way to do this would be to have a metric on type contexts. Oh well. *)
     intros tid vl. unfold typed_body.
diff --git a/theories/typing/lib/cell.v b/theories/typing/lib/cell.v
index 6a729cc5..f67534e7 100644
--- a/theories/typing/lib/cell.v
+++ b/theories/typing/lib/cell.v
@@ -49,7 +49,7 @@ Section cell.
   Global Instance cell_copy :
     Copy ty → Copy (cell ty).
   Proof.
-    intros ty Hcopy. split; first by intros; simpl; apply _.
+    intros ty Hcopy. split; first by intros; simpl; unfold ty_own; apply _.
     iIntros (κ tid E F l q ??) "#LFT #Hshr Htl Htok". iExists 1%Qp. simpl in *.
     (* Size 0 needs a special case as we can't keep the thread-local invariant open. *)
     destruct (ty_size ty) as [|sz] eqn:Hsz; simpl in *.
diff --git a/theories/typing/lib/rc.v b/theories/typing/lib/rc.v
index f6b8962f..b0cb325a 100644
--- a/theories/typing/lib/rc.v
+++ b/theories/typing/lib/rc.v
@@ -1,3 +1,4 @@
+From Coq.QArith Require Import Qcanon.
 From iris.proofmode Require Import tactics.
 From iris.algebra Require Import auth csum frac agree.
 From iris.base_logic Require Import big_op.
@@ -45,10 +46,10 @@ Section rc.
        ty_shr κ tid l :=
          ∃ (l' : loc), &frac{κ} (λ q, l↦∗{q} [ #l']) ∗
            □ ∀ F q, ⌜↑shrN ∪ lftE ⊆ F⌝ -∗ q.[κ]
-             ={F, F∖↑shrN}▷=∗ q.[κ] ∗ ∃ γ ν q',
+             ={F, F∖↑shrN}▷=∗ q.[κ] ∗ ∃ γ ν q', κ ⊑ ν ∗
                 na_inv tid rc_invN (rc_inv tid ν γ l' ty) ∗
-                &na{κ, tid, rc_invN}(own γ (◯ Some (q', 1%positive))) ∗
-                ty.(ty_shr) κ tid (shift_loc l' 1)
+                &na{κ, tid, rc_shrN}(own γ (◯ Some (q', 1%positive))) ∗
+                ty.(ty_shr) ν tid (shift_loc l' 1)
     |}%I.
   Next Obligation. by iIntros (ty tid [|[[]|][]]) "H". Qed.
   Next Obligation.
@@ -60,10 +61,10 @@ Section rc.
       try by iMod (bor_persistent_tok with "LFT Hb Htok") as "[>[] _]".
     iFrame "Htok". iExists _. iFrame "#". rewrite bor_unfold_idx.
     iDestruct "Hb" as (i) "(#Hpb&Hpbown)".
-    set (C := (∃ _ _ _, _ ∗ &na{_,_,_} _ ∗ _)%I).
+    set (C := (∃ _ _ _, _ ∗ _ ∗ &na{_,_,_} _ ∗ _)%I).
     iMod (inv_alloc shrN _ (idx_bor_own 1 i ∨ C)%I
           with "[Hpbown]") as "#Hinv"; first by iLeft.
-    iIntros "!> !# * % Htok". iMod (inv_open with "Hinv") as "[INV Hclose]"; first set_solver.
+    iIntros "!> !# * % Htok". iMod (inv_open with "Hinv") as "[INV Hclose1]"; first set_solver.
     iDestruct "INV" as "[>Hbtok|#Hshr]".
     - iAssert (&{κ} _)%I with "[Hbtok]" as "Hb".
       { rewrite bor_unfold_idx. iExists _. by iFrame. }
@@ -98,10 +99,10 @@ Section rc.
         iDestruct (frac_bor_lft_incl with "LFT >[Hlft]") as "#Hlft".
         { iApply (bor_fracture with "LFT"); first solve_ndisj. by rewrite Qp_mult_1_r. }
         iMod (bor_na with "Hrc") as "$"; first solve_ndisj.
-        iApply ty_shr_mono; done. }
-      iMod ("Hclose" with "[]") as "_"; first by auto.
+        by iFrame "#". }
+      iMod ("Hclose1" with "[]") as "_"; first by auto.
       by iFrame "#∗".
-    - iMod ("Hclose" with "[]") as "_"; first by auto.
+    - iMod ("Hclose1" with "[]") as "_"; first by auto.
       iApply step_fupd_intro; first solve_ndisj. iNext. by iFrame.
   Qed.
   Next Obligation.
@@ -111,10 +112,10 @@ Section rc.
     iMod (lft_incl_acc with "Hincl Htok") as (q'') "[Htok Hclose]"; first solve_ndisj.
     iMod ("Hshr" with "[] Htok") as "Hshr2"; first done.
     iModIntro. iNext. iMod "Hshr2" as "[Htok HX]".
-    iMod ("Hclose" with "Htok") as "$". iDestruct "HX" as (???) "(? & ? & ?)".
+    iMod ("Hclose" with "Htok") as "$". iDestruct "HX" as (? ν ?) "(? & ? & ?& ?)".
     iExists _, _, _. iModIntro. iFrame. iSplit.
+    - by iApply lft_incl_trans.
     - by iApply na_bor_shorten.
-    - by iApply ty_shr_mono.
   Qed.
 End rc.
 
@@ -137,7 +138,7 @@ Section code.
       iIntros (_ ret arg). inv_vec arg=>x. simpl_subst.
     iApply type_new; [solve_typing..|]; iIntros (rcbox); simpl_subst.
     iApply type_new; [solve_typing..|]; iIntros (rc); simpl_subst.
-    iIntros (tid qE) "#LFT Hna HE HL Hk HT". simpl_subst.
+    iIntros (tid qE) "#LFT Hna HE HL Hk HT".
     rewrite (Nat2Z.id (S ty.(ty_size))) 2!tctx_interp_cons
             tctx_interp_singleton !tctx_hasty_val.
     iDestruct "HT" as "[Hrc [Hrcbox Hx]]". destruct x as [[|lx|]|]; try done.
@@ -164,4 +165,69 @@ Section code.
     iApply type_delete; [solve_typing..|].
     iApply (type_jump [ #_]); solve_typing.
   Qed.
+
+  Definition rc_clone : val :=
+    funrec: <> ["rc"] :=
+      let: "rc2" := new [ #1 ] in
+      let: "rc'" := !"rc" in
+      let: "rc''" := !"rc'" in
+      let: "count" := !("rc''" +ₗ #0) in
+      "rc''" +ₗ #0 <- "count" +#1;;
+      "rc2" <- "rc''";;
+      delete [ #1; "rc" ];; return: ["rc2"].
+
+  Lemma rc_clone_type ty :
+    typed_val rc_clone (fn(∀ α, [α]; &shr{α} rc ty) → rc ty).
+  Proof.
+    intros. iApply type_fn; [solve_typing..|]. iIntros "/= !#".
+      iIntros (α ret arg). inv_vec arg=>x. simpl_subst.
+    iApply type_new; [solve_typing..|]; iIntros (rc2); simpl_subst.
+    rewrite (Nat2Z.id 1). (* Having to do this is rather annoying... *) 
+    iApply type_deref; [solve_typing..|]; iIntros (rc'); simpl_subst.
+    iIntros (tid qE) "#LFT Hna HE HL Hk".
+    rewrite 2!tctx_interp_cons tctx_interp_singleton !tctx_hasty_val.
+    iIntros "[Hx [Hrc' Hrc2]]". rewrite [[x]]lock.
+    destruct rc' as [[|lrc|]|]; try done. iDestruct "Hrc'" as (l') "[#Hlrc #Hshr]".
+    destruct rc2 as [[|lrc2|]|]; try done. iDestruct "Hrc2" as "[Hrc2 Hrc2†]".
+    iDestruct "Hrc2" as (vl) "Hrc2". rewrite uninit_own.
+    iDestruct "Hrc2" as "[>Hrc2↦ >SZ]". destruct vl as [|]; iDestruct "SZ" as %[=].
+    destruct vl as [|]; last done. rewrite heap_mapsto_vec_singleton.
+    (* All right, we are done preparing our context. Let's get going. *)
+    rewrite {1}/elctx_interp big_sepL_singleton.
+    iDestruct "HE" as "[Hα1 Hα2]". wp_bind (!_)%E.
+    iSpecialize ("Hshr" with "[] Hα1"); last iApply (wp_fupd_step with "Hshr"); [done..|].
+    iMod (frac_bor_acc with "LFT Hlrc Hα2") as (q') "[Hlrc↦ Hclose]"; first solve_ndisj.
+    rewrite heap_mapsto_vec_singleton. iApply wp_fupd. wp_read.
+    iMod ("Hclose" with "[$Hlrc↦]") as "Hα2". iIntros "!> [Hα1 Hproto]".
+    iDestruct "Hproto" as (γ ν q'') "(#Hincl & #Hinv & #Hrctokb & #Hshr)". iModIntro.
+    wp_let. wp_op. rewrite shift_loc_0.
+    (* Finally, finally... opening the thread-local Rc protocol. *)
+    iMod (na_inv_open with "Hinv Hna") as "(Hrcproto & Hna & Hclose1)"; [solve_ndisj..|].
+    iMod (na_bor_acc with "LFT Hrctokb Hα1 Hna") as "(>Hrctok & Hna & Hclose2)"; [solve_ndisj..|].
+    iDestruct "Hrcproto" as (st) "[>Hrc● Hrcst]".
+    iDestruct (own_valid_2 with "Hrc● Hrctok") as %[[Hval|[_ [[qa c] [_ [-> _]]]]]%option_included _]%auth_valid_discrete_2; first done. (* Oh my, what a pattern... *)
+    iDestruct "Hrcst" as (qb) "(>Hl' & >Hl'† & >% & Hνtok & Hν†)".
+    wp_read. wp_let. wp_op. rewrite shift_loc_0. wp_op. wp_write. wp_write.
+    (* And closing it again. *)
+    iMod (own_update with "Hrc●") as "[Hrc● Hrctok2]".
+    { apply auth_update_alloc,
+      (op_local_update_discrete _ _ (Some ((qb/2)%Qp, 1%positive)))=>-[/= Hqa _].
+      split; simpl; last done. apply frac_valid'. rewrite -H comm_L -{2}(Qp_div_2 qb).
+      apply Qcplus_le_mono_l. rewrite -{1}(Qcplus_0_l (_ / _)%Qp).
+      apply Qcplus_le_mono_r, Qp_ge_0. }
+    rewrite right_id -Some_op pair_op. iDestruct "Hνtok" as "[Hνtok1 Hνtok2]".
+    iMod ("Hclose2" with "[$Hrctok] Hna") as "[Hα1 Hna]".
+    iMod ("Hclose1" with "[Hrc● Hl' Hl'† Hνtok2 Hν† $Hna]") as "Hna".
+    { iExists _. iFrame "Hrc●". iExists _. rewrite Z.add_comm. iFrame.
+      iNext. iPureIntro. rewrite [_ ⋅ _]comm frac_op' -assoc Qp_div_2. done. }
+    (* Finish up the proof. *)
+    iApply (type_type _ _ _ [ x ◁ box (&shr{α} rc ty); #lrc2 ◁ box (rc ty)]%TC
+        with "[] LFT Hna [Hα1 Hα2] HL Hk [-]"); last first.
+    { rewrite tctx_interp_cons tctx_interp_singleton tctx_hasty_val tctx_hasty_val' //.
+      unlock. iFrame "Hx". iFrame "Hrc2†". iExists _. erewrite heap_mapsto_vec_singleton.
+      iFrame "Hrc2↦". iNext. iRight. iExists _, ν, _. iFrame "#∗". }
+    { rewrite /elctx_interp big_sepL_singleton. iFrame. }
+    iApply type_delete; [solve_typing..|].
+    iApply (type_jump [ #_ ]); solve_typing.
+  Qed.
 End code.
diff --git a/theories/typing/lib/refcell/ref_code.v b/theories/typing/lib/refcell/ref_code.v
index a7ee9b1f..952f950e 100644
--- a/theories/typing/lib/refcell/ref_code.v
+++ b/theories/typing/lib/refcell/ref_code.v
@@ -81,7 +81,7 @@ Section ref_functions.
          (op_local_update_discrete _ _ (reading_st (q''/2)%Qp ν))=>-[Hagv _].
       split; [|split; last done].
       - by rewrite /= agree_idemp.
-      - change ((q''/2+q')%Qp ≤ 1%Qp)%Qc. rewrite -Hq'q'' comm -{2}(Qp_div_2 q'').
+      - apply frac_valid'. rewrite -Hq'q'' comm -{2}(Qp_div_2 q'').
         apply Qcplus_le_mono_l. rewrite -{1}(Qcplus_0_l (q''/2)%Qp).
         apply Qcplus_le_mono_r, Qp_ge_0. }
     wp_apply wp_new; [done..|]. iIntros (lr ?) "(%&?&Hlr)".
diff --git a/theories/typing/lib/refcell/refcell_code.v b/theories/typing/lib/refcell/refcell_code.v
index c5b433be..93bb78de 100644
--- a/theories/typing/lib/refcell/refcell_code.v
+++ b/theories/typing/lib/refcell/refcell_code.v
@@ -42,7 +42,7 @@ Section refcell_functions.
     { rewrite tctx_interp_cons tctx_interp_singleton !tctx_hasty_val' //=. iFrame.
       iSplitL "Hx↦".
       - iExists _. rewrite uninit_own. auto.
-      - iExists (_::_). rewrite heap_mapsto_vec_cons. iFrame. auto. }
+      - iExists (_::_). rewrite heap_mapsto_vec_cons. iFrame. simpl. iFrame. auto. }
     iApply type_delete; [solve_typing..|].
     iApply (type_jump [ #_]); solve_typing.
   Qed.
@@ -186,7 +186,7 @@ Section refcell_functions.
             (op_local_update_discrete _ _ (reading_st (q'/2)%Qp ν))=>-[Hagv _].
             split; [|split].
             - by rewrite /= -Hag agree_idemp.
-            - change ((q'/2+q)%Qp ≤ 1%Qp)%Qc. rewrite -Hqq' comm -{2}(Qp_div_2 q').
+            - apply frac_valid'. rewrite -Hqq' comm -{2}(Qp_div_2 q').
               apply Qcplus_le_mono_l. rewrite -{1}(Qcplus_0_l (q'/2)%Qp).
               apply Qcplus_le_mono_r, Qp_ge_0.
             - done. }
diff --git a/theories/typing/lib/refcell/refmut_code.v b/theories/typing/lib/refcell/refmut_code.v
index c5039c18..5602f7fb 100644
--- a/theories/typing/lib/refcell/refmut_code.v
+++ b/theories/typing/lib/refcell/refmut_code.v
@@ -210,7 +210,7 @@ Section refmut_functions.
       iDestruct "Href" as ([|[[|lv'|]|] [|]]) "[H↦ Href]"; auto.
       iExists [ #lv'; #lrc].
       rewrite (heap_mapsto_vec_cons _ _ _ [_]) !heap_mapsto_vec_singleton. iFrame.
-      iExists ν. rewrite EQ1. eauto 10 with iFrame. }
+      iExists ν. rewrite /= EQ1. eauto 20 with iFrame. }
     { rewrite /elctx_interp !big_sepL_cons /= -lft_tok_sep. iFrame. }
     iApply type_deref; [solve_typing..|]. iIntros (x'). simpl_subst.
     iApply type_deref; [solve_typing..|]. iIntros (f'). simpl_subst.
diff --git a/theories/typing/lib/rwlock/rwlock_code.v b/theories/typing/lib/rwlock/rwlock_code.v
index 18b83f25..8a036dc7 100644
--- a/theories/typing/lib/rwlock/rwlock_code.v
+++ b/theories/typing/lib/rwlock/rwlock_code.v
@@ -42,7 +42,7 @@ Section rwlock_functions.
     { rewrite tctx_interp_cons tctx_interp_singleton !tctx_hasty_val' //=. iFrame.
       iSplitL "Hx↦".
       - iExists _. rewrite uninit_own. auto.
-      - iExists (_::_). rewrite heap_mapsto_vec_cons. iFrame. auto. }
+      - iExists (_::_). rewrite heap_mapsto_vec_cons. iFrame. simpl. iFrame. auto. }
     iApply type_delete; [solve_typing..|].
     iApply (type_jump [ #_]); solve_typing.
   Qed.
@@ -193,7 +193,7 @@ Section rwlock_functions.
               (op_local_update_discrete _ _ (reading_st (q'/2)%Qp ν))=>-[Hagv _].
               split; [split|].
               - by rewrite /= Hag agree_idemp.
-              - change ((q'/2+q)%Qp ≤ 1%Qp)%Qc. rewrite -Hqq' comm -{2}(Qp_div_2 q').
+              - apply frac_valid'. rewrite -Hqq' comm -{2}(Qp_div_2 q').
                 apply Qcplus_le_mono_l. rewrite -{1}(Qcplus_0_l (q'/2)%Qp).
                 apply Qcplus_le_mono_r, Qp_ge_0.
               - done. }
diff --git a/theories/typing/product_split.v b/theories/typing/product_split.v
index 2d56f54e..47a6b6fa 100644
--- a/theories/typing/product_split.v
+++ b/theories/typing/product_split.v
@@ -116,7 +116,7 @@ Section product_split.
     iDestruct "H↦1" as (vl1) "[H↦1 H1]". iDestruct "H↦2" as (vl2) "[H↦2 H2]".
     iExists (vl1 ++ vl2). rewrite heap_mapsto_vec_app. iFrame.
     iDestruct (ty_size_eq with "H1") as "#>EQ". iDestruct "EQ" as %->.
-    auto 10 with iFrame.
+    rewrite {3}/ty_own /=. auto 10 with iFrame.
   Qed.
 
   Lemma tctx_split_own_prod E L n tyl p :
diff --git a/theories/typing/sum.v b/theories/typing/sum.v
index f36ed5ae..9f53f4c1 100644
--- a/theories/typing/sum.v
+++ b/theories/typing/sum.v
@@ -107,7 +107,7 @@ Section sum.
     { clear EQmax. induction EQ as [|???? EQ _ IH]=>-[|i] //=. }
     constructor; simpl.
     - by rewrite EQmax.
-    - intros tid vl. destruct n as [|n]=> //=. rewrite EQmax.
+    - intros tid vl. destruct n as [|n]=> //=. rewrite /ty_own /= EQmax.
       solve_proper_core ltac:(fun _ => exact:EQnth || f_type_equiv || f_equiv).
     - intros κ tid l. unfold is_pad. rewrite EQmax.
       solve_proper_core ltac:(fun _ => exact:EQnth || f_type_equiv || f_equiv).
@@ -125,7 +125,7 @@ Section sum.
     { clear EQmax. induction EQ as [|???? EQ _ IH]=>-[|i] //=. }
     constructor; simpl.
     - by rewrite EQmax.
-    - intros tid vl. rewrite EQmax.
+    - intros tid vl. rewrite /ty_own /= EQmax.
       solve_proper_core ltac:(fun _ => exact:EQnth || f_equiv).
     - intros κ tid l. unfold is_pad. rewrite EQmax.
       solve_proper_core ltac:(fun _ => exact:EQnth || (eapply ty_size_ne; try reflexivity) || f_equiv).
diff --git a/theories/typing/type.v b/theories/typing/type.v
index 94219da4..563a333e 100644
--- a/theories/typing/type.v
+++ b/theories/typing/type.v
@@ -51,6 +51,8 @@ Instance: Params (@ty_size) 2.
 Instance: Params (@ty_own) 2.
 Instance: Params (@ty_shr) 2.
 
+Arguments ty_own {_ _} !_ _ !_ /.
+
 Record simple_type `{typeG Σ} :=
   { st_own : thread_id → list val → iProp Σ;
     st_size_eq tid vl : st_own tid vl -∗ ⌜length vl = 1%nat⌝;
@@ -316,7 +318,7 @@ Section type_contractive.
   Proof.
     intros ???. constructor.
     - done.
-    - intros. destruct n; first done; simpl. by f_equiv.
+    - intros. destruct n; first done; simpl. f_equiv. f_equiv. done.
     - intros. solve_contractive.
   Qed.
 End type_contractive.
diff --git a/theories/typing/type_sum.v b/theories/typing/type_sum.v
index da864583..2df653e8 100644
--- a/theories/typing/type_sum.v
+++ b/theories/typing/type_sum.v
@@ -41,7 +41,7 @@ Section case.
         iFrame. iExists _. iFrame. rewrite uninit_own. auto.
     - rewrite -EQlen app_length -(Nat.add_1_l (_+_)) -!freeable_sz_split. iFrame.
       iExists (#i :: vl' ++ vl''). iNext. rewrite heap_mapsto_vec_cons heap_mapsto_vec_app.
-      iFrame. iExists i, vl', vl''. rewrite /= app_length nth_lookup EQty. auto.
+      iFrame. iExists i, vl', vl''. rewrite /= -EQlen app_length nth_lookup EQty /=. auto.
   Qed.
 
   Lemma type_case_own E L C T T' p n tyl el :
@@ -91,7 +91,7 @@ Section case.
     - iMod ("Hclose'" with "[] [H↦i H↦vl' H↦vl'' Hown]") as "[Hb Htok]";
         [by iIntros "!>$"| |].
       { iExists (#i::vl'++vl'').
-        rewrite heap_mapsto_vec_cons heap_mapsto_vec_app -EQlen. iFrame. iNext.
+        rewrite heap_mapsto_vec_cons heap_mapsto_vec_app /= -EQlen. iFrame. iNext.
         iExists i, vl', vl''. rewrite nth_lookup EQty. auto. }
       iMod ("Hclose" with "Htok") as "[HE HL]".
       iApply (Hety with "LFT Hna HE HL HC").
-- 
GitLab