diff --git a/_CoqProject b/_CoqProject index d979692da4e060d7c88887a350216f57fb45831c..e410b9bf41d57605a5eb7b95194e91440a6970c4 100644 --- a/_CoqProject +++ b/_CoqProject @@ -11,4 +11,6 @@ races.v tactics.v wp_tactics.v lifetime.v -types.v +type.v +type_incl.v +perm.v diff --git a/lang.v b/lang.v index d9c45f2acd2b17143802edf5a4f663200bdafef9..db34326b54db89d9f2e05272a65bc4f2ef9fe5a9 100644 --- a/lang.v +++ b/lang.v @@ -56,7 +56,6 @@ Inductive expr := | Case (e : expr) (el : list expr) | Fork (e : expr). -Bind Scope expr_scope with expr. Arguments App _%E _%E. Arguments Case _%E _%E. diff --git a/perm.v b/perm.v new file mode 100644 index 0000000000000000000000000000000000000000..c6c254bcef6628b85819c38f6ee7357a310bf79c --- /dev/null +++ b/perm.v @@ -0,0 +1,54 @@ +From iris.program_logic Require Import thread_local. +From lrust Require Export type. + +Delimit Scope perm_scope with P. +Bind Scope perm_scope with perm. + +Module Perm. + +Section perm. + + Context `{lifetimeG Σ}. + + (* TODO : define valuable expressions ν in order to define ν ◁ τ. *) + + Definition extract (κ : lifetime) (ρ : perm) : perm := + λ tid, (κ ∋ ρ tid)%I. + + Definition tok (κ : lifetime) (q : Qp) : perm := + λ _, ([κ]{q} ★ lft κ)%I. + + Definition incl (κ κ' : lifetime) : perm := + λ _, (κ ⊑ κ')%I. + + Definition exist {A : Type} (P : A -> perm) : @perm Σ := + λ tid, (∃ x, P x tid)%I. + + Definition sep (ρ1 ρ2 : perm) : @perm Σ := + λ tid, (ρ1 tid ★ ρ2 tid)%I. + + Definition top : @perm Σ := + λ _, True%I. + +End perm. + +End Perm. + +Import Perm. + +Notation "κ ∋ ρ" := (extract κ ρ) + (at level 75, right associativity) : perm_scope. + +Notation "[ κ ]{ q }" := (tok κ q) (format "[ κ ]{ q }") : perm_scope. + +Infix "⊑" := incl (at level 70) : perm_scope. + +Notation "∃ x .. y , P" := + (exist (λ x, .. (exist (λ y, P)) ..)) : perm_scope. + +Infix "★" := sep (at level 80, right associativity) : perm_scope. + +Notation "⊤" := top : perm_scope. + +Definition perm_incl {Σ} (ρ1 ρ2 : @perm Σ) := + ∀ tid, ρ1 tid ⊢ ρ2 tid. \ No newline at end of file diff --git a/types.v b/type.v similarity index 77% rename from types.v rename to type.v index d67540d7a46d745fc0c4c6e69f36eaabe3194754..c82c9431da7194c15d13fce406092da7a674c922 100644 --- a/types.v +++ b/type.v @@ -1,7 +1,6 @@ From iris.algebra Require Import upred_big_op. From iris.program_logic Require Import hoare thread_local. -From lrust Require Export notation. -From lrust Require Import lifetime heap. +From lrust Require Export notation lifetime heap. Definition mgmtE := nclose tlN ∪ lftN. Definition lrustN := nroot .@ "lrust". @@ -10,6 +9,7 @@ Section defs. Context `{heapG Σ, lifetimeG Σ, thread_localG Σ}. + (* [perm] is defined here instead of perm.v in order to define [cont] *) Definition perm := thread_id → iProp Σ. Record type := @@ -42,55 +42,59 @@ Section defs. [κ]{q} ★ tl_own tid N ={E}=> ∃ q', ▷l ↦★{q'}: ty_own tid ★ (▷l ↦★{q'}: ty_own tid ={E}=★ [κ]{q} ★ tl_own tid N) }. - Global Existing Instance ty_shr_persistent. - Definition ty_incl (ty1 ty2 : type) := - ((□ ∀ tid vl, ty1.(ty_own) tid vl → ty2.(ty_own) tid vl) ∧ - (□ ∀ κ tid E l, ty1.(ty_shr) κ tid E l → ty2.(ty_shr) κ tid E l))%I. - Record simple_type := - { st_size : nat; st_dup : bool; + { st_size : nat; st_own : thread_id → list val → iProp Σ; st_size_eq tid vl : st_own tid vl ⊢ length vl = st_size; - st_dup_dup tid vl : st_dup → st_own tid vl ⊢ st_own tid vl ★ st_own tid vl - }. + st_own_persistent tid vl : PersistentP (st_own tid vl) }. + Global Existing Instance st_own_persistent. Program Definition ty_of_st (st : simple_type) : type := - {| ty_size := st.(st_size); ty_dup := st.(st_dup); + {| ty_size := st.(st_size); ty_dup := true; ty_own := st.(st_own); - ty_shr := λ κ tid _ l, (&frac{κ} λ q, l ↦★{q}: st.(st_own) tid)%I + ty_shr := λ κ tid _ l, + (∃ vl, (&frac{κ} λ q, l ↦★{q} vl) ★ ▷ st.(st_own) tid vl)%I |}. Next Obligation. apply st_size_eq. Qed. - Next Obligation. apply st_dup_dup. Qed. + Next Obligation. iIntros (st tid vl _) "H". eauto. Qed. Next Obligation. - intros st E N κ l tid q ??. iIntros "Hmt Hlft". iFrame. - by iApply lft_borrow_fracture. + intros st E N κ l tid q ??. iIntros "Hmt Htok". + iVs (lft_borrow_exists with "Hmt Htok") as (vl) "[Hmt Htok]". set_solver. + iVs (lft_borrow_split with "Hmt") as "[Hmt Hown]". set_solver. + iVs (lft_borrow_persistent with "Hown Htok") as "[Hown $]". set_solver. + iExists vl. iFrame. by iApply lft_borrow_fracture. Qed. Next Obligation. - iIntros (st κ κ' tid N l) "#Hord". by iApply lft_frac_borrow_incl. + iIntros (st κ κ' tid N l) "#Hord H". iDestruct "H" as (vl) "[Hf Hown]". + iExists vl. iFrame. by iApply (lft_frac_borrow_incl with "Hord"). Qed. Next Obligation. - intros st κ tid N E l q ???. iIntros "#Hshr!#[Hlft Htlown]". - iVs (lft_frac_borrow_open with "[] Hshr Hlft"); [set_solver| |by iFrame]. - iIntros "!#". iIntros (q1 q2). iSplit; iIntros "H". - - iDestruct "H" as (vl) "[Hq1q2 Hown]". - iDestruct (st_dup_dup with "Hown") as "[Hown1 Hown2]". done. - rewrite -heap_mapsto_vec_op_eq. iDestruct "Hq1q2" as "[Hq1 Hq2]". - by iSplitL "Hq1 Hown1"; iExists _; iFrame. - - iDestruct "H" as "[H1 H2]". - iDestruct "H1" as (vl1) "[Hq1 Hown1]". - iDestruct "H2" as (vl2) "[Hq2 Hown2]". - iAssert (length vl1 = length vl2)%I with "[#]" as "%". - { iDestruct (st_size_eq with "Hown2") as %->. - iApply (st_size_eq with "Hown1"). } - iCombine "Hq1" "Hq2" as "Hq1q2". rewrite heap_mapsto_vec_op; last done. - iDestruct "Hq1q2" as "[% Hq1q2]". subst vl2. iExists vl1. by iFrame. + intros st κ tid N E l q ???. iIntros "#Hshr!#[Hlft $]". + iDestruct "Hshr" as (vl) "[Hf Hown]". + iVs (lft_frac_borrow_open with "[] Hf Hlft") as (q') "[Hmt Hclose]"; + first set_solver. + - iIntros "!#". iIntros (q1 q2). rewrite heap_mapsto_vec_op_eq. + iSplit; auto. + - iVsIntro. rewrite {1}heap_mapsto_vec_op_split. iExists _. + iDestruct "Hmt" as "[Hmt1 Hmt2]". iSplitL "Hmt1". + + iNext. iExists _. by iFrame. + + iIntros "Hmt1". iDestruct "Hmt1" as (vl') "[Hmt1 #Hown']". + iAssert (▷ (length vl = length vl'))%I as ">%". + { iNext. + iDestruct (st_size_eq with "Hown") as %->. + iDestruct (st_size_eq with "Hown'") as %->. done. } + iCombine "Hmt1" "Hmt2" as "Hmt". rewrite heap_mapsto_vec_op // Qp_div_2. + iDestruct "Hmt" as "[>% Hmt]". subst. by iApply "Hclose". Qed. End defs. +Delimit Scope lrust_type_scope with T. +Bind Scope lrust_type_scope with type. + Module Types. Section types. (* TODO : make ty_of_st work as a coercion. *) @@ -98,36 +102,44 @@ Section types. Context `{heapG Σ, lifetimeG Σ, thread_localG Σ}. Program Definition bot := - ty_of_st {| st_size := 1; st_dup := true; st_own tid vl := False%I |}. + {| ty_size := 0; ty_dup := true; + ty_own tid vl := False%I; ty_shr κ tid N l := False%I |}. Next Obligation. iIntros (tid vl) "[]". Qed. - Next Obligation. iIntros (tid vl _) "[]". Qed. + Next Obligation. iIntros (???) "[]". Qed. + Next Obligation. + iIntros (????????) "Hb Htok". + iVs (lft_borrow_exists with "Hb Htok") as (vl) "[Hb Htok]". set_solver. + iVs (lft_borrow_split with "Hb") as "[_ Hb]". set_solver. + iVs (lft_borrow_persistent with "Hb Htok") as "[>[] _]". set_solver. + Qed. + Next Obligation. iIntros (?????) "_ []". Qed. + Next Obligation. intros. iIntros "[]". Qed. Program Definition unit := - ty_of_st {| st_size := 0; st_dup := true; st_own tid vl := (vl = [])%I |}. - Next Obligation. iIntros (tid vl) "%". by subst. Qed. - Next Obligation. iIntros (tid vl _) "%". auto. Qed. + ty_of_st {| st_size := 0; st_own tid vl := (vl = [])%I |}. + Next Obligation. iIntros (tid vl) "%". simpl. by subst. Qed. Program Definition bool := - ty_of_st {| st_size := 1; st_dup := true; - st_own tid vl := (∃ z:bool, vl = [ #z ])%I - |}. + ty_of_st {| st_size := 1; st_own tid vl := (∃ z:bool, vl = [ #z ])%I |}. Next Obligation. iIntros (tid vl) "H". iDestruct "H" as (z) "%". by subst. Qed. - Next Obligation. iIntros (tid vl _) "H". auto. Qed. Program Definition int := - ty_of_st {| st_size := 1; st_dup := true; - st_own tid vl := (∃ z:Z, vl = [ #z ])%I - |}. + ty_of_st {| st_size := 1; st_own tid vl := (∃ z:Z, vl = [ #z ])%I |}. Next Obligation. iIntros (tid vl) "H". iDestruct "H" as (z) "%". by subst. Qed. - Next Obligation. iIntros (tid vl _) "H". auto. Qed. (* TODO own and uniq_borrow are very similar. They could probably somehow share some bits.. *) Program Definition own (q : Qp) (ty : type) := {| ty_size := 1; ty_dup := false; ty_own tid vl := - (∃ l:loc, vl = [ #l ] ★ †{q}l…ty.(ty_size) - ★ ▷ l ↦★: ty.(ty_own) tid)%I; + (* We put a later in front of the †{q}, because we cannot use + [ty_size_eq] on [ty] at step index 0, which would in turn + prevent us to prove [ty_incl_own]. + + Since this assertion is timeless, this should not cause + problems. *) + (∃ l:loc, vl = [ #l ] ★ ▷ †{q}l…ty.(ty_size) + ★ ▷ l ↦★: ty.(ty_own) tid)%I; ty_shr κ tid N l := (∃ l':loc, &frac{κ}(λ q', l ↦{q'} #l') ★ ∀ q', [κ]{q'} ={mgmtE ∪ N, mgmtE}▷=> ty.(ty_shr) κ tid N l' ★ [κ]{q'})%I @@ -238,13 +250,12 @@ Section types. Next Obligation. done. Qed. Program Definition shared_borrow (κ : lifetime) (ty : type) := - ty_of_st {| st_size := 1; st_dup := true; - st_own tid vl := (∃ l:loc, vl = [ #l ] ★ ty.(ty_shr) κ tid lrustN l)%I + ty_of_st {| st_size := 1; + st_own tid vl := (∃ l:loc, vl = [ #l ] ★ ty.(ty_shr) κ tid lrustN l)%I; |}. Next Obligation. iIntros (κ ty tid vl) "H". iDestruct "H" as (l) "[% _]". by subst. Qed. - Next Obligation. iIntros (κ ty tid vl _) "H". auto. Qed. Fixpoint combine_accu_size (tyl : list type) (accu : nat) := match tyl with @@ -404,7 +415,22 @@ Section types. iExists (#i::vl). rewrite heap_mapsto_vec_cons. iFrame. eauto. Qed. - Program Definition sum n (tyl : list type) (Hsz : Forall ((= n) ∘ ty_size) tyl) := + Class LstTySize (n : nat) (tyl : list type) := + size_eq : Forall ((= n) ∘ ty_size) tyl. + Instance LstTySize_nil n : LstTySize n nil := List.Forall_nil _. + Hint Extern 1 (LstTySize _ (_ :: _)) => + apply List.Forall_cons; [reflexivity|]. + + Lemma sum_size_eq n tid i tyl vl {Hn : LstTySize n tyl} : + ty_own (nth i tyl bot) tid vl ⊢ length vl = n. + Proof. + iIntros "Hown". iDestruct (ty_size_eq with "Hown") as %->. + revert Hn. rewrite /LstTySize List.Forall_forall /= =>Hn. + edestruct nth_in_or_default as [| ->]. by eauto. + iDestruct "Hown" as "[]". + Qed. + + Program Definition sum {n} (tyl : list type) {_:LstTySize n tyl} := {| ty_size := S n; ty_dup := forallb ty_dup tyl; ty_own tid vl := (∃ (i : nat) vl', vl = #i :: vl' ★ (nth i tyl bot).(ty_own) tid vl')%I; @@ -414,10 +440,7 @@ Section types. |}. Next Obligation. iIntros (n tyl Hn tid vl) "Hown". iDestruct "Hown" as (i vl') "(%&Hown)". subst. - simpl. iDestruct (ty_size_eq with "Hown") as %->. - rewrite ->List.Forall_forall in Hn. simpl in Hn. - edestruct nth_in_or_default as [| ->]. by eauto. - iDestruct "Hown" as "[]". + simpl. by iDestruct (sum_size_eq with "Hown") as %->. Qed. Next Obligation. iIntros (n tyl Hn tid vl Hdup%Is_true_eq_true) "Hown". @@ -452,11 +475,8 @@ Section types. rewrite ->forallb_forall in Hdup. auto using Is_true_eq_left. } destruct (Qp_lower_bound q'1 q'2) as (q' & q'01 & q'02 & -> & ->). iExists q'. iVsIntro. - rewrite -{1}heap_mapsto_op_eq -{1}heap_mapsto_vec_prop_op; last first. - { iIntros (vl) "H". iDestruct (ty_size_eq with "H") as %->. - edestruct nth_in_or_default as [| ->]. - - rewrite ->List.Forall_forall in Hn. by rewrite Hn. - - iDestruct "H" as "[]". } + rewrite -{1}heap_mapsto_op_eq -{1}heap_mapsto_vec_prop_op; + last (by intros; apply sum_size_eq, Hn). iDestruct "Hownq" as "[Hownq1 Hownq2]". iDestruct "Hown" as "[Hown1 Hown2]". iSplitL "Hown1 Hownq1". - iNext. iExists i. by iFrame. @@ -466,31 +486,30 @@ Section types. iDestruct "Hown" as "[>#Hi Hown]". iDestruct "Hi" as %[= ->%Z_of_nat_inj]. iVs ("Hclose" with "Hown") as "$". iCombine "Hownq1" "Hownq2" as "Hownq". - rewrite heap_mapsto_vec_prop_op; last first. - { iIntros (vl) "H". iDestruct (ty_size_eq with "H") as %->. - edestruct nth_in_or_default as [| ->]. - - rewrite ->List.Forall_forall in Hn. by rewrite Hn. - - iDestruct "H" as "[]". } + rewrite heap_mapsto_vec_prop_op; last (by intros; apply sum_size_eq, Hn). iApply ("Hclose'" with "Hownq"). Qed. Program Definition undef (n : nat) := - ty_of_st {| st_size := n; st_dup := true; st_own tid vl := (length vl = n)%I |}. + ty_of_st {| st_size := n; st_own tid vl := (length vl = n)%I |}. Next Obligation. done. Qed. - Next Obligation. iIntros (n tid vl _) "H"; by iSplit. Qed. Program Definition cont {n : nat} (perm : vec val n → perm (Σ := Σ)):= - ty_of_st {| st_size := 1; st_dup := false; - st_own tid vl := (∃ f xl e Hcl, vl = [@RecV f xl e Hcl] ★ + {| ty_size := 1; ty_dup := false; + ty_own tid vl := (∃ f xl e Hcl, vl = [@RecV f xl e Hcl] ★ ∀ vl tid, perm vl tid -★ tl_own tid ⊤ - -★ WP e (map of_val (vec_to_list vl)) {{λ _, False}})%I |}. + -★ WP e (map of_val (vec_to_list vl)) {{λ _, False}})%I; + ty_shr κ tid N l := True%I |}. Next Obligation. iIntros (n perm tid vl) "H". iDestruct "H" as (f xl e Hcl) "[% _]". by subst. Qed. Next Obligation. done. Qed. + Next Obligation. intros. by iIntros "_ $". Qed. + Next Obligation. intros. by iIntros "_ _". Qed. + Next Obligation. done. Qed. Program Definition fn {n : nat} (perm : vec val n → perm (Σ := Σ)):= - ty_of_st {| st_size := 1; st_dup := true; + ty_of_st {| st_size := 1; st_own tid vl := (∃ f xl e Hcl, vl = [@RecV f xl e Hcl] ★ ∀ vl tid, {{ perm vl tid ★ tl_own tid ⊤ }} e (map of_val (vec_to_list vl)) @@ -498,23 +517,39 @@ Section types. Next Obligation. iIntros (n perm tid vl) "H". iDestruct "H" as (f xl e Hcl) "[% _]". by subst. Qed. - Next Obligation. iIntros (n perm tid vl _) "#H". by iSplit. Qed. - Program Definition forall_ty {A : Type} n dup (ty : A -> type) {_:Inhabited A} - (Hsz : ∀ x, (ty x).(ty_size) = n) (Hdup : ∀ x, (ty x).(ty_dup) = dup) := - ty_of_st {| st_size := n; st_dup := dup; - st_own tid vl := (∀ x, (ty x).(ty_own) tid vl)%I |}. - Next Obligation. - intros A n dup ty ? Hn Hdup tid vl. iIntros "H". iSpecialize ("H" $! inhabitant). - rewrite -(Hn inhabitant). by iApply ty_size_eq. - Qed. - Next Obligation. - intros A n [] ty ? Hn Hdup tid vl []. - (* FIXME: A quantified assertion is not necessarilly dupicable if - its contents is.*) - admit. - Admitted. + (* TODO *) + (* Program Definition forall_ty {A : Type} n dup (ty : A -> type) {_:Inhabited A} *) + (* (Hsz : ∀ x, (ty x).(ty_size) = n) (Hdup : ∀ x, (ty x).(ty_dup) = dup) := *) + (* ty_of_st {| st_size := n; st_dup := dup; *) + (* st_own tid vl := (∀ x, (ty x).(ty_own) tid vl)%I |}. *) + (* Next Obligation. *) + (* intros A n dup ty ? Hn Hdup tid vl. iIntros "H". iSpecialize ("H" $! inhabitant). *) + (* rewrite -(Hn inhabitant). by iApply ty_size_eq. *) + (* Qed. *) + (* Next Obligation. *) + (* intros A n [] ty ? Hn Hdup tid vl []. *) + (* (* FIXME: A quantified assertion is not necessarilly dupicable if *) + (* its contents is.*) *) + (* admit. *) + (* Admitted. *) End types. End Types. + +Import Types. + +Notation "!" := bot : lrust_type_scope. +Notation "&uniq{ κ } ty" := (uniq_borrow κ ty) + (format "&uniq{ κ } ty", at level 20, right associativity) : lrust_type_scope. +Notation "&shr{ κ } ty" := (shared_borrow κ ty) + (format "&shr{ κ } ty", at level 20, right associativity) : lrust_type_scope. +Notation "( ty1 * ty2 * .. * tyn )" := + (product (cons ty1 (cons ty2 ( .. (cons tyn nil) .. )))) + (format "( ty1 * ty2 * .. * tyn )") : lrust_type_scope. +Notation "( ty1 + ty2 + .. + tyn )" := + (sum (cons ty1 (cons ty2 ( .. (cons tyn nil) .. )))) + (format "( ty1 + ty2 + .. + tyn )") : lrust_type_scope. + +(* TODO : notation for forall *) \ No newline at end of file diff --git a/type_incl.v b/type_incl.v new file mode 100644 index 0000000000000000000000000000000000000000..fd3dbc5821a381a39d40f95dfc2c13bf49749ab2 --- /dev/null +++ b/type_incl.v @@ -0,0 +1,119 @@ +From iris.algebra Require Import upred_big_op. +From iris.program_logic Require Import thread_local. +From lrust Require Export type perm. + +Import Types. + +Section ty_incl. + + Context `{heapG Σ, lifetimeG Σ, thread_localG Σ}. + + Definition ty_incl (ρ : perm) (ty1 ty2 : type) := + ∀ tid, + ρ tid ⊢ + (□ ∀ tid vl, ty1.(ty_own) tid vl → ty2.(ty_own) tid vl) ∧ + (□ ∀ κ tid E l, ty1.(ty_shr) κ tid E l → + ty2.(ty_shr) κ tid E l + (* [ty_incl] needs to prove something about the length of the + object when it is shared. We place this property under the + hypothesis that [ty2.(ty_shr)] holds, so that the [!] type + is still included in any other. *) + ★ ty1.(ty_size) = ty2.(ty_size)). + + Lemma ty_incl_refl ρ ty : ty_incl ρ ty ty. + Proof. iIntros (tid0) "_". iSplit; iIntros "!#"; eauto. Qed. + + Lemma ty_incl_trans ρ ty1 ty2 ty3 : + ty_incl ρ ty1 ty2 → ty_incl ρ ty2 ty3 → ty_incl ρ ty1 ty3. + Proof. + iIntros (H12 H23 tid0) "H". + iDestruct (H12 with "H") as "[#H12 #H12']". + iDestruct (H23 with "H") as "[#H23 #H23']". + iSplit; iIntros "{H}!#*H1". + - by iApply "H23"; iApply "H12". + - iDestruct ("H12'" $! _ _ _ _ with "H1") as "[H2 %]". + iDestruct ("H23'" $! _ _ _ _ with "H2") as "[$ %]". + iPureIntro. congruence. + Qed. + + Lemma ty_weaken ρ θ ty1 ty2 : + perm_incl ρ θ → ty_incl θ ty1 ty2 → ty_incl ρ ty1 ty2. + Proof. iIntros (Hρθ Hθ tid) "H". iApply Hθ. by iApply Hρθ. Qed. + + Lemma ty_incl_bot ρ ty : ty_incl ρ ! ty. + Proof. iIntros (tid0) "_". iSplit; iIntros "!#*/=[]". Qed. + + Lemma ty_incl_own ρ ty1 ty2 q : + ty_incl ρ ty1 ty2 → ty_incl ρ (own q ty1) (own q ty2). + Proof. + iIntros (Hincl tid0) "H/=". iDestruct (Hincl with "H") as "[#Howni #Hshri]". + iClear "H". iSplit; iIntros "!#*H". + - iDestruct "H" as (l) "(%&H†&Hmt)". subst. iExists _. iSplit. done. + iDestruct "Hmt" as (vl') "[Hmt Hown]". iNext. + iDestruct (ty_size_eq with "Hown") as %<-. + iDestruct ("Howni" $! _ _ with "Hown") as "Hown". + iDestruct (ty_size_eq with "Hown") as %<-. iFrame. + iExists _. by iFrame. + - iDestruct "H" as (l') "[Hfb #Hvs]". iSplit; last done. iExists l'. iFrame. + iIntros (q') "!#Hκ". + iVs ("Hvs" $! _ with "Hκ") as "Hvs'". iIntros "!==>!>". + iVs "Hvs'" as "[Hshr $]". iVsIntro. + by iDestruct ("Hshri" $! _ _ _ _ with "Hshr") as "[$ _]". + Qed. + + Lemma lft_incl_ty_incl_uniq_borrow ρ ty κ1 κ2 : + perm_incl ρ (κ1 ⊑ κ2) → ty_incl ρ (&uniq{κ2}ty) (&uniq{κ1}ty). + Proof. + iIntros (Hκκ' tid0) "H". iDestruct (Hκκ' with "H") as "#Hκκ'". iClear "H". + iSplit; iIntros "!#*H". + - iDestruct "H" as (l) "[% Hown]". subst. iExists _. iSplit. done. + by iApply (lft_borrow_incl with "Hκκ'"). + - admit. (* TODO : fix the definition before *) + Admitted. + + Lemma lft_incl_ty_incl_shared_borrow ρ ty κ1 κ2 : + perm_incl ρ (κ1 ⊑ κ2) → ty_incl ρ (&shr{κ2}ty) (&shr{κ1}ty). + Proof. + iIntros (Hκκ' tid0) "H". iDestruct (Hκκ' with "H") as "#Hκκ'". iClear "H". + iSplit; iIntros "!#*H". + - iDestruct "H" as (l) "[% Hown]". subst. iExists _. iSplit. done. + by iApply (ty.(ty_shr_mono) with "Hκκ'"). + - iDestruct "H" as (vl) "#[Hfrac Hty]". iSplit; last done. + iExists vl. iFrame "#". iNext. + iDestruct "Hty" as (l0) "[% Hty]". subst. iExists _. iSplit. done. + by iApply (ty_shr_mono with "Hκκ' Hty"). + Qed. + + Lemma ty_incl_prod ρ tyl1 tyl2 : + Forall2 (ty_incl ρ) tyl1 tyl2 → ty_incl ρ (product tyl1) (product tyl2). + Proof. + rewrite {2}/ty_incl /product /=. iIntros (HFA tid0) "Hρ". iSplit. + - assert (Himpl : ρ tid0 ⊢ + □ (∀ tid vll, length tyl1 = length vll → + ([★ list] tyvl ∈ combine tyl1 vll, ty_own (tyvl.1) tid (tyvl.2)) + → ([★ list] tyvl ∈ combine tyl2 vll, ty_own (tyvl.1) tid (tyvl.2)))). + { induction HFA as [|ty1 ty2 tyl1 tyl2 Hincl HFA IH]. + - iIntros "_!#* _ _". by rewrite big_sepL_nil. + - iIntros "Hρ". iDestruct (IH with "Hρ") as "#Hqimpl". + iDestruct (Hincl with "Hρ") as "[#Hhimpl _]". iIntros "!#*%". + destruct vll as [|vlh vllq]. discriminate. rewrite !big_sepL_cons. + iIntros "[Hh Hq]". iSplitL "Hh". by iApply "Hhimpl". + iApply ("Hqimpl" with "[] Hq"). iPureIntro. simpl in *. congruence. } + iDestruct (Himpl with "Hρ") as "#Himpl". iIntros "{Hρ}!#*H". + iDestruct "H" as (vll) "(%&%&H)". iExists _. iSplit. done. iSplit. + by rewrite -(Forall2_length _ _ _ HFA). by iApply ("Himpl" with "[] H"). + - iRevert "Hρ". generalize O. + change (ndot (A:=nat)) with (λ N i, N .@ (0+i)%nat). generalize O. + induction HFA as [|ty1 ty2 tyl1 tyl2 Hincl HFA IH]. + + iIntros (i offs) "_!#* _". rewrite big_sepL_nil. eauto. + + iIntros (i offs) "Hρ". iDestruct (IH with "[] Hρ") as "#Hqimpl". done. + iDestruct (Hincl with "Hρ") as "[_ #Hhimpl]". iIntros "!#*". + rewrite !big_sepL_cons. iIntros "[Hh Hq]". + setoid_rewrite <-Nat.add_succ_comm. + iDestruct ("Hhimpl" $! _ _ _ _ with "Hh") as "[$ %]". + replace ty2.(ty_size) with ty1.(ty_size) by done. + iDestruct ("Hqimpl" $! _ _ _ _ with "Hq") as "[$ %]". + iIntros "!%/=". congruence. + Qed. + +End ty_incl. \ No newline at end of file