From d0f2c02ef0143ee85edb8e1aef45725e4d44dff1 Mon Sep 17 00:00:00 2001 From: Robbert Krebbers <mail@robbertkrebbers.nl> Date: Thu, 24 Nov 2016 16:57:32 +0100 Subject: [PATCH] Split lifetime logic into multiple files. --- _CoqProject | 25 +- theories/lifetime.v | 947 -------------------------------- theories/lifetime/creation.v | 294 ++++++++++ theories/lifetime/definitions.v | 192 +++++++ theories/lifetime/derived.v | 125 +++++ theories/lifetime/primitive.v | 298 ++++++++++ theories/lifetime/todo.v | 63 +++ 7 files changed, 977 insertions(+), 967 deletions(-) delete mode 100644 theories/lifetime.v create mode 100644 theories/lifetime/creation.v create mode 100644 theories/lifetime/definitions.v create mode 100644 theories/lifetime/derived.v create mode 100644 theories/lifetime/primitive.v create mode 100644 theories/lifetime/todo.v diff --git a/_CoqProject b/_CoqProject index cd1cc58d..d8ed7fbb 100644 --- a/_CoqProject +++ b/_CoqProject @@ -1,22 +1,7 @@ -Q theories lrust -Q iris-enabled iris -theories/adequacy.v -theories/derived.v -theories/heap.v -theories/lang.v -theories/lifting.v -theories/memcpy.v -theories/notation.v -theories/proofmode.v -theories/races.v -theories/tactics.v -theories/wp_tactics.v -theories/lifetime.v -theories/tl_borrow.v -theories/shr_borrow.v -theories/frac_borrow.v -theories/type.v -theories/type_incl.v -theories/perm.v -theories/perm_incl.v -theories/typing.v +theories/lifetime/definitions.v +theories/lifetime/derived.v +theories/lifetime/creation.v +theories/lifetime/primitive.v +theories/lifetime/todo.v diff --git a/theories/lifetime.v b/theories/lifetime.v deleted file mode 100644 index 6c1a4eed..00000000 --- a/theories/lifetime.v +++ /dev/null @@ -1,947 +0,0 @@ -From iris.algebra Require Import csum auth frac gmap dec_agree gset. -From iris.prelude Require Import gmultiset. -From iris.base_logic.lib Require Export invariants. -From iris.base_logic.lib Require Import boxes. -From iris.base_logic Require Import big_op. -From iris.proofmode Require Import tactics. -Import uPred. - -Definition lftN : namespace := nroot .@ "lft". -Definition borN : namespace := lftN .@ "bor". -Definition inhN : namespace := lftN .@ "inh". -Definition mgmtN : namespace := lftN .@ "mgmt". - -Definition atomic_lft := positive. -Notation lft := (gmultiset positive). -Definition static : lft := ∅. - -Inductive bor_state := - | Bor_in - | Bor_open (q : frac) - | Bor_rebor (κ : lft). -Instance bor_state_eq_dec : EqDecision bor_state. -Proof. solve_decision. Defined. - -Definition bor_filled (s : bor_state) : bool := - match s with Bor_in => true | _ => false end. - -Definition lft_stateR := csumR fracR unitR. -Definition to_lft_stateR (b : bool) : lft_stateR := - if b then Cinl 1%Qp else Cinr (). - -Record lft_names := LftNames { - bor_name : gname; - cnt_name : gname; - inh_name : gname -}. -Instance lft_names_eq_dec : EqDecision lft_names. -Proof. solve_decision. Defined. - -Class lftG Σ := LftG { - lft_box :> boxG Σ; - alft_inG :> inG Σ (authR (gmapUR atomic_lft lft_stateR)); - alft_name : gname; - ilft_inG :> inG Σ (authR (gmapUR lft (dec_agreeR lft_names))); - ilft_name : gname; - lft_bor_box :> - inG Σ (authR (gmapUR slice_name (prodR fracR (dec_agreeR bor_state)))); - lft_cnt_inG :> inG Σ (authR natUR); - lft_inh_box :> inG Σ (authR (gset_disjUR slice_name)); -}. - -Section defs. - Context `{invG Σ, lftG Σ}. - - Definition lft_tok (q : Qp) (κ : lft) : iProp Σ := - ([∗ mset] Λ ∈ κ, own alft_name (◯ {[ Λ := Cinl q ]}))%I. - - Definition lft_dead (κ : lft) : iProp Σ := - (∃ Λ, ⌜Λ ∈ κ⌝ ∗ own alft_name (◯ {[ Λ := Cinr () ]}))%I. - - Definition own_alft_auth (A : gmap atomic_lft bool) : iProp Σ := - own alft_name (● (to_lft_stateR <$> A)). - Definition own_ilft_auth (I : gmap lft lft_names) : iProp Σ := - own ilft_name (● (DecAgree <$> I)). - - Definition own_bor (κ : lft) - (x : auth (gmap slice_name (frac * dec_agree bor_state))) : iProp Σ := - (∃ γs, - own ilft_name (◯ {[ κ := DecAgree γs ]}) ∗ - own (bor_name γs) x)%I. - - Definition own_cnt (κ : lft) (x : auth nat) : iProp Σ := - (∃ γs, - own ilft_name (◯ {[ κ := DecAgree γs ]}) ∗ - own (cnt_name γs) x)%I. - - Definition own_inh (κ : lft) (x : auth (gset_disj slice_name)) : iProp Σ := - (∃ γs, - own ilft_name (◯ {[ κ := DecAgree γs ]}) ∗ - own (inh_name γs) x)%I. - - Definition bor_cnt (κ : lft) (s : bor_state) : iProp Σ := - match s with - | Bor_in => True - | Bor_open q => lft_tok q κ - | Bor_rebor κ' => ⌜κ ⊂ κ'⌝ ∗ own_cnt κ' (◯ 1) - end%I. - - Definition lft_bor_alive (κ : lft) (P : iProp Σ) : iProp Σ := - (∃ B : gmap slice_name bor_state, - box borN (bor_filled <$> B) P ∗ - own_bor κ (● ((1%Qp,) ∘ DecAgree <$> B)) ∗ - [∗ map] s ∈ B, bor_cnt κ s)%I. - - Definition lft_bor_dead (κ : lft) : iProp Σ := - (∃ (B: gset slice_name) (P : iProp Σ), - own_bor κ (● to_gmap (1%Qp, DecAgree Bor_in) B) ∗ - box borN (to_gmap false B) P)%I. - - Definition lft_inh (κ : lft) (s : bool) (P : iProp Σ) : iProp Σ := - (∃ E : gset slice_name, - own_inh κ (● GSet E) ∗ - box inhN (to_gmap s E) P)%I. - - Definition lft_vs_inv_go (κ : lft) (lft_inv_alive : ∀ κ', κ' ⊂ κ → iProp Σ) - (I : gmap lft lft_names) : iProp Σ := - (lft_bor_dead κ ∗ - own_ilft_auth I ∗ - [∗ set] κ' ∈ dom _ I, ∀ Hκ : κ' ⊂ κ, lft_inv_alive κ' Hκ)%I. - - Definition lft_vs_go (κ : lft) (lft_inv_alive : ∀ κ', κ' ⊂ κ → iProp Σ) - (P Q : iProp Σ) : iProp Σ := - (∃ n : nat, - own_cnt κ (● n) ∗ - ∀ I : gmap lft lft_names, - lft_vs_inv_go κ lft_inv_alive I -∗ ▷ P -∗ lft_dead κ - ={⊤∖↑mgmtN}=∗ - lft_vs_inv_go κ lft_inv_alive I ∗ ▷ Q ∗ own_cnt κ (◯ n))%I. - - Definition lft_inv_alive_go (κ : lft) - (lft_inv_alive : ∀ κ', κ' ⊂ κ → iProp Σ) : iProp Σ := - (∃ P Q, - lft_bor_alive κ P ∗ - lft_vs_go κ lft_inv_alive P Q ∗ - lft_inh κ false Q)%I. - - Definition lft_inv_alive (κ : lft) : iProp Σ := - Fix_F _ lft_inv_alive_go (gmultiset_wf κ). - Definition lft_vs_inv (κ : lft) (I : gmap lft lft_names) : iProp Σ := - lft_vs_inv_go κ (λ κ' _, lft_inv_alive κ') I. - Definition lft_vs (κ : lft) (P Q : iProp Σ) : iProp Σ := - lft_vs_go κ (λ κ' _, lft_inv_alive κ') P Q. - - Definition lft_inv_dead (κ : lft) : iProp Σ := - (∃ P, - lft_bor_dead κ ∗ - own_cnt κ (● 0) ∗ - lft_inh κ true P)%I. - - Definition lft_alive_in (A : gmap atomic_lft bool) (κ : lft) : Prop := - ∀ Λ, Λ ∈ κ → A !! Λ = Some true. - Definition lft_dead_in (A : gmap atomic_lft bool) (κ : lft) : Prop := - ∃ Λ, Λ ∈ κ ∧ A !! Λ = Some false. - - Definition lft_inv (A : gmap atomic_lft bool) (κ : lft) : iProp Σ := - (lft_inv_alive κ ∗ ⌜lft_alive_in A κ⌝ ∨ - lft_inv_dead κ ∗ ⌜lft_dead_in A κ⌝)%I. - - Definition lfts_inv : iProp Σ := - (∃ (A : gmap atomic_lft bool) (I : gmap lft lft_names), - own_alft_auth A ∗ - own_ilft_auth I ∗ - [∗ set] κ ∈ dom _ I, lft_inv A κ)%I. - - Definition lft_ctx : iProp Σ := inv mgmtN lfts_inv. - - Definition lft_incl (κ κ' : lft) : iProp Σ := - (□ ((∀ q, lft_tok q κ ={↑lftN}=∗ ∃ q', - lft_tok q' κ' ∗ (lft_tok q' κ' ={↑lftN}=∗ lft_tok q κ)) ∗ - (lft_dead κ' ={↑lftN}=∗ lft_dead κ)))%I. - - Definition bor_idx := (lft * slice_name)%type. - - Definition idx_bor_own (q : frac) (i : bor_idx) : iProp Σ := - own_bor (i.1) (◯ {[ i.2 := (q,DecAgree Bor_in) ]}). - Definition idx_bor (κ : lft) (i : bor_idx) (P : iProp Σ) : iProp Σ := - (lft_incl κ (i.1) ∗ slice borN (i.2) P)%I. - Definition raw_bor (i : bor_idx) (P : iProp Σ) : iProp Σ := - (idx_bor_own 1 i ∗ slice borN (i.2) P)%I. - Definition bor (κ : lft) (P : iProp Σ) : iProp Σ := - (∃ i, lft_incl κ (i.1) ∗ raw_bor i P)%I. -End defs. - -Instance: Params (@lft_bor_alive) 4. -Instance: Params (@lft_inh) 5. -Instance: Params (@lft_vs) 4. -Instance: Params (@idx_bor) 5. -Instance: Params (@raw_bor) 4. -Instance: Params (@bor) 4. - -Notation "q .[ κ ]" := (lft_tok q κ) - (format "q .[ κ ]", at level 0) : uPred_scope. -Notation "[† κ ]" := (lft_dead κ) (format "[† κ ]"): uPred_scope. - -Notation "&{ κ } P" := (bor κ P) - (format "&{ κ } P", at level 20, right associativity) : uPred_scope. -Notation "&{ κ , i } P" := (idx_bor κ i P) - (format "&{ κ , i } P", at level 20, right associativity) : uPred_scope. - -Infix "⊑" := lft_incl (at level 70) : uPred_scope. - -Typeclasses Opaque lft_tok lft_dead bor_cnt lft_bor_alive lft_bor_dead - lft_inh lft_inv_alive lft_vs_inv lft_vs lft_inv_dead lft_inv lft_incl - idx_bor_own idx_bor raw_bor bor. - -Section theorems. -Context `{invG Σ, lftG Σ}. -Implicit Types κ : lft. - -(* Unfolding lemmas *) -Lemma lft_vs_inv_go_ne κ (f f' : ∀ κ', κ' ⊂ κ → iProp Σ) I n : - (∀ κ' (Hκ : κ' ⊂ κ), f κ' Hκ ≡{n}≡ f' κ' Hκ) → - lft_vs_inv_go κ f I ≡{n}≡ lft_vs_inv_go κ f' I. -Proof. - intros Hf. apply sep_ne, sep_ne, big_opS_ne=> // κ'. - by apply forall_ne=> Hκ. -Qed. - -Lemma lft_vs_go_ne κ (f f' : ∀ κ', κ' ⊂ κ → iProp Σ) P P' Q Q' n : - (∀ κ' (Hκ : κ' ⊂ κ), f κ' Hκ ≡{n}≡ f' κ' Hκ) → - P ≡{n}≡ P' → Q ≡{n}≡ Q' → - lft_vs_go κ f P Q ≡{n}≡ lft_vs_go κ f' P' Q'. -Proof. - intros Hf HP HQ. apply exist_ne=> n'. - apply sep_ne, forall_ne=> // I. rewrite lft_vs_inv_go_ne //. solve_proper. -Qed. - -Lemma lft_inv_alive_go_ne κ (f f' : ∀ κ', κ' ⊂ κ → iProp Σ) n : - (∀ κ' (Hκ : κ' ⊂ κ), f κ' Hκ ≡{n}≡ f' κ' Hκ) → - lft_inv_alive_go κ f ≡{n}≡ lft_inv_alive_go κ f'. -Proof. - intros Hf. apply exist_ne=> P; apply exist_ne=> Q. by rewrite lft_vs_go_ne. -Qed. - -Lemma lft_inv_alive_unfold κ : - lft_inv_alive κ ⊣⊢ ∃ P Q, lft_bor_alive κ P ∗ lft_vs κ P Q ∗ lft_inh κ false Q. -Proof. - apply equiv_dist=> n. rewrite /lft_inv_alive -Fix_F_eq. - apply lft_inv_alive_go_ne=> κ' Hκ. - apply (Fix_F_proper _ (λ _, dist n)); auto using lft_inv_alive_go_ne. -Qed. -Lemma lft_vs_inv_unfold κ (I : gmap lft lft_names) : - lft_vs_inv κ I ⊣⊢ lft_bor_dead κ ∗ - own_ilft_auth I ∗ - [∗ set] κ' ∈ dom _ I, ⌜κ' ⊂ κ⌝ → lft_inv_alive κ'. -Proof. - rewrite /lft_vs_inv /lft_vs_inv_go. by setoid_rewrite pure_impl_forall. -Qed. -Lemma lft_vs_unfold κ P Q : - lft_vs κ P Q ⊣⊢ ∃ n : nat, - own_cnt κ (● n) ∗ - ∀ I : gmap lft lft_names, - lft_vs_inv κ I -∗ ▷ P -∗ lft_dead κ ={⊤∖↑mgmtN}=∗ - lft_vs_inv κ I ∗ ▷ Q ∗ own_cnt κ (◯ n). -Proof. done. Qed. - -Global Instance lft_bor_alive_ne κ n : Proper (dist n ==> dist n) (lft_bor_alive κ). -Proof. solve_proper. Qed. -Global Instance lft_bor_alive_proper κ : Proper ((≡) ==> (≡)) (lft_bor_alive κ). -Proof. apply (ne_proper _). Qed. - -Global Instance lft_inh_ne κ s n : Proper (dist n ==> dist n) (lft_inh κ s). -Proof. solve_proper. Qed. -Global Instance lft_inh_proper κ s : Proper ((≡) ==> (≡)) (lft_inh κ s). -Proof. apply (ne_proper _). Qed. - -Global Instance lft_vs_ne κ n : - Proper (dist n ==> dist n ==> dist n) (lft_vs κ). -Proof. intros P P' HP Q Q' HQ. by apply lft_vs_go_ne. Qed. -Global Instance lft_vs_proper κ : Proper ((≡) ==> (≡) ==> (≡)) (lft_vs κ). -Proof. apply (ne_proper_2 _). Qed. - -Global Instance idx_bor_ne κ i n : Proper (dist n ==> dist n) (idx_bor κ i). -Proof. solve_proper. Qed. -Global Instance idx_bor_proper κ i : Proper ((≡) ==> (≡)) (idx_bor κ i). -Proof. apply (ne_proper _). Qed. - -Global Instance raw_bor_ne i n : Proper (dist n ==> dist n) (raw_bor i). -Proof. solve_proper. Qed. -Global Instance raw_bor_proper i : Proper ((≡) ==> (≡)) (raw_bor i). -Proof. apply (ne_proper _). Qed. - -Global Instance bor_ne κ n : Proper (dist n ==> dist n) (bor κ). -Proof. solve_proper. Qed. -Global Instance bor_proper κ : Proper ((≡) ==> (≡)) (bor κ). -Proof. apply (ne_proper _). Qed. - -(*** PersistentP and TimelessP instances *) -Global Instance lft_tok_timeless q κ : TimelessP q.[κ]. -Proof. rewrite /lft_tok. apply _. Qed. -Global Instance lft_dead_persistent κ : PersistentP [†κ]. -Proof. rewrite /lft_dead. apply _. Qed. -Global Instance lft_dead_timeless κ : PersistentP [†κ]. -Proof. rewrite /lft_tok. apply _. Qed. - -Global Instance lft_incl_persistent κ κ' : PersistentP (κ ⊑ κ'). -Proof. rewrite /lft_incl. apply _. Qed. - -Global Instance idx_bor_persistent κ i P : PersistentP (&{κ,i} P). -Proof. rewrite /idx_bor. apply _. Qed. -Global Instance idx_borrow_own_timeless q i : TimelessP (idx_bor_own q i). -Proof. rewrite /idx_bor_own. apply _. Qed. - -Global Instance lft_ctx_persistent : PersistentP lft_ctx. -Proof. rewrite /lft_ctx. apply _. Qed. - -(** Alive and dead *) -Global Instance lft_alive_in_dec A κ : Decision (lft_alive_in A κ). -Proof. - refine (cast_if (decide (set_Forall (λ Λ, A !! Λ = Some true) - (dom (gset atomic_lft) κ)))); - rewrite /lft_alive_in; by setoid_rewrite <-gmultiset_elem_of_dom. -Qed. -Global Instance lft_dead_in_dec A κ : Decision (lft_dead_in A κ). -Proof. - refine (cast_if (decide (set_Exists (λ Λ, A !! Λ = Some false) - (dom (gset atomic_lft) κ)))); - rewrite /lft_dead_in; by setoid_rewrite <-gmultiset_elem_of_dom. -Qed. - -Lemma lft_alive_or_dead_in A κ : - (∃ Λ, Λ ∈ κ ∧ A !! Λ = None) ∨ (lft_alive_in A κ ∨ lft_dead_in A κ). -Proof. - rewrite /lft_alive_in /lft_dead_in. - destruct (decide (set_Exists (λ Λ, A !! Λ = None) (dom (gset _) κ))) - as [(Λ & ?%gmultiset_elem_of_dom & HAΛ)|HA%(not_set_Exists_Forall _)]; first eauto. - destruct (decide (set_Exists (λ Λ, A !! Λ = Some false) (dom (gset _) κ))) - as [(Λ & HΛ%gmultiset_elem_of_dom & ?)|HA'%(not_set_Exists_Forall _)]; first eauto. - right; left. intros Λ HΛ%gmultiset_elem_of_dom. - move: (HA _ HΛ) (HA' _ HΛ)=> /=. case: (A !! Λ)=>[[]|]; naive_solver. -Qed. -Lemma lft_alive_and_dead_in A κ : lft_alive_in A κ → lft_dead_in A κ → False. -Proof. intros Halive (Λ&HΛ&?). generalize (Halive _ HΛ). naive_solver. Qed. - -Lemma lft_alive_in_subseteq A κ κ' : - lft_alive_in A κ → κ' ⊆ κ → lft_alive_in A κ'. -Proof. intros Halive ? Λ ?. by eapply Halive, gmultiset_elem_of_subseteq. Qed. - -Lemma lft_alive_in_insert A κ Λ b : - A !! Λ = None → lft_alive_in A κ → lft_alive_in (<[Λ:=b]> A) κ. -Proof. - intros HΛ Halive Λ' HΛ'. - assert (Λ ≠ Λ') by (intros ->; move:(Halive _ HΛ'); by rewrite HΛ). - rewrite lookup_insert_ne; eauto. -Qed. -Lemma lft_alive_in_insert_false A κ Λ b : - Λ ∉ κ → lft_alive_in A κ → lft_alive_in (<[Λ:=b]> A) κ. -Proof. - intros HΛ Halive Λ' HΛ'. - rewrite lookup_insert_ne; last (by intros ->); auto. -Qed. - -Lemma lft_dead_in_insert A κ Λ b : - A !! Λ = None → lft_dead_in A κ → lft_dead_in (<[Λ:=b]> A) κ. -Proof. - intros HΛ (Λ'&?&HΛ'). - assert (Λ ≠ Λ') by (intros ->; move:HΛ'; by rewrite HΛ). - exists Λ'. by rewrite lookup_insert_ne. -Qed. -Lemma lft_dead_in_insert_false A κ Λ : - lft_dead_in A κ → lft_dead_in (<[Λ:=false]> A) κ. -Proof. - intros (Λ'&?&HΛ'). destruct (decide (Λ = Λ')) as [<-|]. - - exists Λ. by rewrite lookup_insert. - - exists Λ'. by rewrite lookup_insert_ne. -Qed. -Lemma lft_dead_in_insert_false' A κ Λ : Λ ∈ κ → lft_dead_in (<[Λ:=false]> A) κ. -Proof. exists Λ. by rewrite lookup_insert. Qed. - -(** Silly stuff *) -Lemma own_ilft_auth_agree (I : gmap lft lft_names) κ γs : - own_ilft_auth I ⊢ - own ilft_name (◯ {[κ := DecAgree γs]}) -∗ ⌜is_Some (I !! κ)⌝. -Proof. - iIntros "HI Hκ". iDestruct (own_valid_2 with "HI Hκ") - as %[[? [??]]%singleton_included _]%auth_valid_discrete_2. - simplify_map_eq; simplify_option_eq; eauto. -Qed. - -Lemma own_bor_auth I κ x : own_ilft_auth I ⊢ own_bor κ x -∗ ⌜is_Some (I !! κ)⌝. -Proof. - iIntros "HI"; iDestruct 1 as (γs) "[? _]". - by iApply (own_ilft_auth_agree with "HI"). -Qed. -Lemma own_bor_op κ x y : own_bor κ (x ⋅ y) ⊣⊢ own_bor κ x ∗ own_bor κ y. -Proof. - iSplit. - { iDestruct 1 as (γs) "[#? [Hx Hy]]"; iSplitL "Hx"; iExists γs; eauto. } - iIntros "[Hx Hy]". - iDestruct "Hx" as (γs) "[Hγs Hx]"; iDestruct "Hy" as (γs') "[Hγs' Hy]". - iDestruct (own_valid_2 with "Hγs Hγs'") as %Hγs%auth_own_valid. - move: Hγs; rewrite /= op_singleton singleton_valid=> /dec_agree_op_inv [<-]. - iExists γs. iSplit. done. rewrite own_op; iFrame. -Qed. -Lemma own_bor_valid κ x : own_bor κ x ⊢ ✓ x. -Proof. iDestruct 1 as (γs) "[#? Hx]". by iApply own_valid. Qed. -Lemma own_bor_valid_2 κ x y : own_bor κ x ⊢ own_bor κ y -∗ ✓ (x ⋅ y). -Proof. apply wand_intro_r. rewrite -own_bor_op. apply own_bor_valid. Qed. -Lemma own_bor_update κ x y : x ~~> y → own_bor κ x ==∗ own_bor κ y. -Proof. - iDestruct 1 as (γs) "[#Hκ Hx]"; iExists γs. iFrame "Hκ". by iApply own_update. -Qed. - -Lemma own_cnt_auth I κ x : own_ilft_auth I ⊢ own_cnt κ x -∗ ⌜is_Some (I !! κ)⌝. -Proof. - iIntros "HI"; iDestruct 1 as (γs) "[? _]". - by iApply (own_ilft_auth_agree with "HI"). -Qed. -Lemma own_cnt_op κ x y : own_cnt κ (x ⋅ y) ⊣⊢ own_cnt κ x ∗ own_cnt κ y. -Proof. - iSplit. - { iDestruct 1 as (γs) "[#? [Hx Hy]]"; iSplitL "Hx"; iExists γs; eauto. } - iIntros "[Hx Hy]". - iDestruct "Hx" as (γs) "[Hγs Hx]"; iDestruct "Hy" as (γs') "[Hγs' Hy]". - iDestruct (own_valid_2 with "Hγs Hγs'") as %Hγs%auth_own_valid. - move: Hγs; rewrite /= op_singleton singleton_valid=> /dec_agree_op_inv [<-]. - iExists γs. iSplit; first done. rewrite own_op; iFrame. -Qed. -Lemma own_cnt_valid κ x : own_cnt κ x ⊢ ✓ x. -Proof. iDestruct 1 as (γs) "[#? Hx]". by iApply own_valid. Qed. -Lemma own_cnt_valid_2 κ x y : own_cnt κ x ⊢ own_cnt κ y -∗ ✓ (x ⋅ y). -Proof. apply wand_intro_r. rewrite -own_cnt_op. apply own_cnt_valid. Qed. -Lemma own_cnt_update κ x y : x ~~> y → own_cnt κ x ==∗ own_cnt κ y. -Proof. - iDestruct 1 as (γs) "[#Hκ Hx]"; iExists γs. iFrame "Hκ". by iApply own_update. -Qed. -Lemma own_cnt_update_2 κ x1 x2 y : - x1 ⋅ x2 ~~> y → own_cnt κ x1 ⊢ own_cnt κ x2 ==∗ own_cnt κ y. -Proof. - intros. apply wand_intro_r. rewrite -own_cnt_op. by apply own_cnt_update. -Qed. - -Lemma own_inh_auth I κ x : own_ilft_auth I ⊢ own_inh κ x -∗ ⌜is_Some (I !! κ)⌝. -Proof. - iIntros "HI"; iDestruct 1 as (γs) "[? _]". - by iApply (own_ilft_auth_agree with "HI"). -Qed. -Lemma own_inh_op κ x y : own_inh κ (x ⋅ y) ⊣⊢ own_inh κ x ∗ own_inh κ y. -Proof. - iSplit. - { iDestruct 1 as (γs) "[#? [Hx Hy]]"; iSplitL "Hx"; iExists γs; eauto. } - iIntros "[Hx Hy]". - iDestruct "Hx" as (γs) "[Hγs Hx]"; iDestruct "Hy" as (γs') "[Hγs' Hy]". - iDestruct (own_valid_2 with "Hγs Hγs'") as %Hγs%auth_own_valid. - move: Hγs; rewrite /= op_singleton singleton_valid=> /dec_agree_op_inv [<-]. - iExists γs. iSplit. done. rewrite own_op; iFrame. -Qed. -Lemma own_inh_valid κ x : own_inh κ x ⊢ ✓ x. -Proof. iDestruct 1 as (γs) "[#? Hx]". by iApply own_valid. Qed. -Lemma own_inh_valid_2 κ x y : own_inh κ x ⊢ own_inh κ y -∗ ✓ (x ⋅ y). -Proof. apply wand_intro_r. rewrite -own_inh_op. apply own_inh_valid. Qed. -Lemma own_inh_update κ x y : x ~~> y → own_inh κ x ==∗ own_inh κ y. -Proof. - iDestruct 1 as (γs) "[#Hκ Hx]"; iExists γs. iFrame "Hκ". by iApply own_update. -Qed. - -Lemma lft_inv_alive_twice κ : lft_inv_alive κ ⊢ lft_inv_alive κ -∗ False. -Proof. - rewrite lft_inv_alive_unfold /lft_inh. - iDestruct 1 as (P Q) "(_&_&Hinh)"; iDestruct 1 as (P' Q') "(_&_&Hinh')". - iDestruct "Hinh" as (E) "[HE _]"; iDestruct "Hinh'" as (E') "[HE' _]". - by iDestruct (own_inh_valid_2 with "HE HE'") as %?. -Qed. - -(** Basic rules about lifetimes *) -Lemma lft_tok_op q κ1 κ2 : q.[κ1] ∗ q.[κ2] ⊣⊢ q.[κ1 ∪ κ2]. -Proof. by rewrite /lft_tok -big_sepMS_union. Qed. - -Lemma lft_dead_or κ1 κ2 : [†κ1] ∨ [†κ2] ⊣⊢ [† κ1 ∪ κ2]. -Proof. - rewrite /lft_dead -or_exist. apply exist_proper=> Λ. - rewrite -sep_or_r -pure_or. do 2 f_equiv. set_solver. -Qed. - -Lemma lft_tok_frac_op κ q q' : (q + q').[κ] ⊣⊢ q.[κ] ∗ q'.[κ]. -Proof. - rewrite /lft_tok -big_sepMS_sepMS. apply big_sepMS_proper=> Λ _. - by rewrite -own_op -auth_frag_op op_singleton. -Qed. - -Lemma lft_tok_split κ q : q.[κ] ⊣⊢ (q/2).[κ] ∗ (q/2).[κ]. -Proof. by rewrite -lft_tok_frac_op Qp_div_2. Qed. - -Lemma lft_tok_dead_own q κ : q.[κ] ⊢ [† κ] -∗ False. -Proof. - rewrite /lft_tok /lft_dead. iIntros "H"; iDestruct 1 as (Λ') "[% H']". - iDestruct (big_sepMS_elem_of _ _ Λ' with "H") as "H"=> //. - iDestruct (own_valid_2 with "H H'") as %Hvalid. - move: Hvalid=> /auth_own_valid /=; by rewrite op_singleton singleton_valid. -Qed. - -Lemma lft_tok_static q : True ⊢ q.[static]. -Proof. by rewrite /lft_tok big_sepMS_empty. Qed. - -Lemma lft_dead_static : [† static] ⊢ False. -Proof. rewrite /lft_dead. iDestruct 1 as (Λ) "[% H']". set_solver. Qed. - -(* Lifetime creation *) -Lemma lft_inh_kill E κ Q : - ↑inhN ⊆ E → - lft_inh κ false Q ∗ ▷ Q ={E}=∗ lft_inh κ true Q. -Proof. - rewrite /lft_inh. iIntros (?) "[Hinh HQ]". - iDestruct "Hinh" as (E') "[Hinh Hbox]". - iMod (box_fill_all with "[$Hbox $HQ]") as "?"=>//. - rewrite fmap_to_gmap. iModIntro. iExists E'. by iFrame. -Qed. - -Lemma lft_vs_inv_frame (KI K : gset lft) κ : - (∀ κ', κ' ∈ KI → κ' ⊂ κ → κ' ∈ K) → - ([∗ set] κ' ∈ K, lft_inv_alive κ') ⊢ - ([∗ set] κ' ∈ KI, ⌜κ' ⊂ κ⌝ → lft_inv_alive κ') ∗ - (([∗ set] κ' ∈ KI, ⌜κ' ⊂ κ⌝ → lft_inv_alive κ') -∗ - ([∗ set] κ' ∈ K, lft_inv_alive κ')). -Proof. - intros ?. - destruct (proj1 (subseteq_disjoint_union_L (filter (⊂ κ) KI) K)) as (K'&->&?). - { intros κ'. rewrite elem_of_filter. set_solver. } - rewrite big_sepS_union // big_sepS_filter. iIntros "[$ $]"; auto. -Qed. - -Lemma ilft_create A I κ : - own_ilft_auth I ⊢ own_alft_auth A -∗ ▷ ([∗ set] κ ∈ dom _ I, lft_inv A κ) - ==∗ ∃ A' I', ⌜is_Some (I' !! κ)⌝ ∗ - own_ilft_auth I' ∗ own_alft_auth A' ∗ ▷ ([∗ set] κ ∈ dom _ I', lft_inv A' κ). -Proof. - iIntros "HI HA HA'". - destruct (decide (is_Some (I !! κ))) as [?|HIκ%eq_None_not_Some]. - { iModIntro. iExists A, I. by iFrame. } - iMod (own_alloc (● 0 ⋅ ◯ 0)) as (γcnt) "[Hcnt Hcnt']"; first done. - iMod (own_alloc ((● ∅ ⋅ ◯ ∅) :auth (gmap slice_name - (frac * dec_agree bor_state)))) as (γbor) "[Hbor Hbor']"; - first by apply auth_valid_discrete_2. - iMod (own_alloc ((● ∅ ⋅ ◯ ∅) :auth (gset_disj slice_name))) - as (γinh) "[Hinh Hinh']"; first by apply auth_valid_discrete_2. - set (γs := LftNames γbor γcnt γinh). - iMod (own_update with "HI") as "[HI Hγs]". - { apply auth_update_alloc, - (alloc_singleton_local_update _ κ (DecAgree γs)); last done. - by rewrite lookup_fmap HIκ. } - iDestruct "Hγs" as "#Hγs". - iAssert (lft_inv_dead κ ∧ lft_inv_alive κ)%I - with "[-HA HA' HI]" as "Hdeadandalive". - { iSplit. - - rewrite /lft_inv_dead. iExists True%I. iSplitL "Hbor". - { rewrite /lft_bor_dead. iExists ∅, True%I. rewrite !to_gmap_empty. - iSplitL "Hbor". iExists γs. by iFrame. iApply box_alloc. } - iSplitL "Hcnt". - { rewrite /own_cnt. iExists γs. by iFrame. } - rewrite /lft_inh. iExists ∅. rewrite to_gmap_empty. - iSplitL; [|iApply box_alloc]. rewrite /own_inh. iExists γs. by iSplit. - - rewrite lft_inv_alive_unfold. iExists True%I, True%I. iSplitL "Hbor". - { rewrite /lft_bor_alive. iExists ∅. rewrite !fmap_empty big_sepM_empty. - iSplitR; [iApply box_alloc|]. iSplit=>//. - rewrite /own_bor. iExists γs. by iFrame. } - rewrite lft_vs_unfold. iSplitR "Hinh". - { iExists 0. iSplitL "Hcnt". - { rewrite /own_cnt. iExists γs. by iFrame. } - iIntros (I') "$ $ _ !>". rewrite /own_cnt. iExists γs. by iFrame. } - rewrite /lft_inh. iExists ∅. rewrite to_gmap_empty. - iSplitL; [|iApply box_alloc]. rewrite /own_inh. iExists γs. by iFrame. } - destruct (lft_alive_or_dead_in A κ) as [(Λ&?&HAΛ)|Haliveordead]. - - iMod (own_update with "HA") as "[HA _]". - { apply auth_update_alloc, - (alloc_singleton_local_update _ Λ (Cinr ())); last done. - by rewrite lookup_fmap HAΛ. } - iModIntro. iExists (<[Λ:=false]>A), (<[κ:=γs]> I). - iSplit; first rewrite lookup_insert; eauto. - rewrite /own_ilft_auth /own_alft_auth !fmap_insert. iFrame "HA HI". - rewrite dom_insert_L big_sepS_insert ?not_elem_of_dom //. - iSplitR "HA'". - { rewrite /lft_inv. iNext. iRight. iSplit. - { by iDestruct "Hdeadandalive" as "[? _]". } - iPureIntro. exists Λ. rewrite lookup_insert; auto. } - iNext. iApply (big_sepS_impl _ _ (dom (gset lft) I) with "[$HA']"). - rewrite /lft_inv. iIntros "!#"; iIntros (κ' ?%elem_of_dom) - "[[HA HA']|[HA HA']]"; iDestruct "HA'" as %HA. - + iLeft. iFrame "HA". iPureIntro. by apply lft_alive_in_insert. - + iRight. iFrame "HA". iPureIntro. by apply lft_dead_in_insert. - - iModIntro. iExists A, (<[κ:=γs]> I). - iSplit; first rewrite lookup_insert; eauto. - iSplitL "HI"; first by rewrite /own_ilft_auth fmap_insert. - rewrite dom_insert_L big_sepS_insert ?not_elem_of_dom //. - iFrame "HA HA'". iNext. rewrite /lft_inv. destruct Haliveordead. - + iLeft. by iDestruct "Hdeadandalive" as "[_ $]". - + iRight. by iDestruct "Hdeadandalive" as "[$ _]". -Qed. - -Lemma lft_kill (I : gmap lft lft_names) (K K' : gset lft) (κ : lft) : - let Iinv := ( - own_ilft_auth I ∗ - ([∗ set] κ' ∈ K, lft_inv_alive κ') ∗ - ([∗ set] κ' ∈ K', lft_inv_dead κ'))%I in - (∀ κ', is_Some (I !! κ') → κ' ⊂ κ → κ' ∈ K) → - (∀ κ', is_Some (I !! κ') → κ ⊂ κ' → κ' ∈ K') → - Iinv ⊢ lft_inv_alive κ -∗ [†κ] ={⊤∖↑mgmtN}=∗ Iinv ∗ lft_inv_dead κ. -Proof. - iIntros (Iinv HK HK') "(HI & Halive & Hdead) Hlalive Hκ". - rewrite lft_inv_alive_unfold; - iDestruct "Hlalive" as (P Q) "(Hbor & Hvs & Hinh)". - rewrite /lft_bor_alive; iDestruct "Hbor" as (B) "(Hbox & Hbor & HB)". - iAssert ⌜∀ i s, B !! i = Some s → s = Bor_in⌝%I with "[#]" as %HB. - { iIntros (i s HBI). - iDestruct (big_sepM_lookup _ B with "HB") as "HB"=> //. - destruct s as [|q|κ']; rewrite /bor_cnt //. - { iDestruct (lft_tok_dead_own with "HB Hκ") as "[]". } - iDestruct "HB" as "[% Hcnt]". - iDestruct (own_cnt_auth with "HI Hcnt") as %?. - iDestruct (big_sepS_elem_of _ K' with "Hdead") as "Hdead"; first by eauto. - rewrite /lft_inv_dead; iDestruct "Hdead" as (R) "(_ & Hcnt' & _)". - iDestruct (own_cnt_valid_2 with "Hcnt' Hcnt") - as %[?%nat_included _]%auth_valid_discrete_2; omega. } - iMod (box_empty_all with "Hbox") as "[HP Hbox]"=>//; first solve_ndisj. - { intros i s. by rewrite lookup_fmap fmap_Some=> -[? [/HB -> ->]]. } - rewrite lft_vs_unfold; iDestruct "Hvs" as (n) "[Hcnt Hvs]". - iDestruct (lft_vs_inv_frame (dom _ I) _ κ with "Halive") as "[Halive Halive']". - { intros κ'. rewrite elem_of_dom. eauto. } - iMod ("Hvs" $! I with "[HI Halive Hbox Hbor] HP Hκ") as "(Hinv & HQ & Hcnt')". - { rewrite lft_vs_inv_unfold. iFrame. rewrite /lft_bor_dead. - iExists (dom _ B), P. rewrite !to_gmap_dom -map_fmap_compose. - rewrite (map_fmap_ext _ ((1%Qp,) ∘ DecAgree) B); last naive_solver. - iFrame. } - rewrite lft_vs_inv_unfold; iDestruct "Hinv" as "(?&HI&Halive)". - iSpecialize ("Halive'" with "Halive"). - iMod (own_cnt_update_2 with "Hcnt Hcnt'") as "?". - { apply auth_update_dealloc, (nat_local_update _ _ 0 0); omega. } - rewrite /Iinv. iFrame "Hdead Halive' HI". - iMod (lft_inh_kill with "[$Hinh $HQ]"); first solve_ndisj. - iModIntro. rewrite /lft_inv_dead. iExists Q. by iFrame. -Qed. - -Lemma lfts_kill A (I : gmap lft lft_names) (K K' : gset lft) : - let Iinv K' := (own_ilft_auth I ∗ [∗ set] κ' ∈ K', lft_inv_alive κ')%I in - (∀ κ κ', κ ∈ K → is_Some (I !! κ') → κ ⊆ κ' → κ' ∈ K) → - (∀ κ κ', κ ∈ K → lft_alive_in A κ → is_Some (I !! κ') → - κ' ∉ K → κ' ⊂ κ → κ' ∈ K') → - Iinv K' ⊢ ([∗ set] κ ∈ K, lft_inv A κ ∗ [†κ]) - ={⊤∖↑mgmtN}=∗ Iinv K' ∗ [∗ set] κ ∈ K, lft_inv_dead κ. -Proof. - intros Iinv. revert K'. - induction (collection_wf K) as [K _ IH]=> K' HK HK'. - iIntros "[HI Halive] HK". - pose (Kalive := filter (lft_alive_in A) K). - destruct (decide (Kalive = ∅)) as [HKalive|]. - { iModIntro. rewrite /Iinv. iFrame. - iApply (big_sepS_impl _ _ K with "[$HK]"); iAlways. - rewrite /lft_inv. iIntros (κ Hκ) "[[[_ %]|[$ _]] _]". set_solver. } - destruct (minimal_exists_L (⊂) Kalive) - as (κ & [Hκalive HκK]%elem_of_filter & Hκmin); first done. - iDestruct (big_sepS_delete _ K κ with "HK") as "[[Hκinv Hκ] HK]"; first done. - rewrite {1}/lft_inv. iDestruct "Hκinv" as "[[Hκalive _]|[_ %]]"; last first. - { by destruct (lft_alive_and_dead_in A κ). } - iAssert ⌜κ ∉ K'⌝%I with "[#]" as %HκK'. - { iIntros (Hκ). iApply (lft_inv_alive_twice κ with "Hκalive"). - by iApply (big_sepS_elem_of _ K' κ with "Halive"). } - specialize (IH (K ∖ {[ κ ]})). feed specialize IH; [set_solver +HκK|]. - iMod (IH ({[ κ ]} ∪ K') with "[HI Halive Hκalive] HK") as "[[HI Halive] Hdead]". - { intros κ' κ''. - rewrite !elem_of_difference !elem_of_singleton=> -[? Hneq] ??. - split; [by eauto|]; intros ->. - eapply (minimal_strict_1 _ _ κ' Hκmin), strict_spec_alt; eauto. - apply elem_of_filter; eauto using lft_alive_in_subseteq. } - { intros κ' κ'' Hκ' ? [γs'' ?]. - destruct (decide (κ'' = κ)) as [->|]; [set_solver +|]. - move: Hκ'; rewrite not_elem_of_difference elem_of_difference - elem_of_union not_elem_of_singleton elem_of_singleton. - intros [??] [?|?]; eauto. } - { rewrite /Iinv big_sepS_insert //. iFrame. } - iDestruct (big_sepS_insert _ K' with "Halive") as "[Hκalive Halive]"; first done. - iMod (lft_kill with "[$HI $Halive $Hdead] Hκalive Hκ") - as "[(HI&Halive&Hdead) Hκdead]". - { intros κ' ??. eapply (HK' κ); eauto. - intros ?. eapply (minimal_strict_1 _ _ _ Hκmin); eauto. - apply elem_of_filter; split; last done. - eapply lft_alive_in_subseteq, gmultiset_subset_subseteq; eauto. } - { intros κ' ? [??]%strict_spec_alt. - rewrite elem_of_difference elem_of_singleton; eauto. } - iModIntro. rewrite /Iinv (big_sepS_delete _ K) //. iFrame. -Qed. - -Definition kill_set (I : gmap lft lft_names) (Λ : atomic_lft) : gset lft := - filter (Λ ∈) (dom (gset lft) I). - -Lemma elem_of_kill_set I Λ κ : κ ∈ kill_set I Λ ↔ Λ ∈ κ ∧ is_Some (I !! κ). -Proof. by rewrite /kill_set elem_of_filter elem_of_dom. Qed. -Lemma kill_set_subseteq I Λ : kill_set I Λ ⊆ dom (gset lft) I. -Proof. intros κ [??]%elem_of_kill_set. by apply elem_of_dom. Qed. - -Definition down_close (A : gmap atomic_lft bool) - (I : gmap lft lft_names) (K : gset lft) : gset lft := - filter (λ κ, κ ∉ K ∧ - set_Exists (λ κ', κ ⊂ κ' ∧ lft_alive_in A κ') K) (dom (gset lft) I). -Lemma elem_of_down_close A I K κ : - κ ∈ down_close A I K ↔ - is_Some (I !! κ) ∧ κ ∉ K ∧ ∃ κ', κ' ∈ K ∧ κ ⊂ κ' ∧ lft_alive_in A κ'. -Proof. rewrite /down_close elem_of_filter elem_of_dom /set_Exists. tauto. Qed. - -Lemma down_close_lft_alive_in A I K κ : κ ∈ down_close A I K → lft_alive_in A κ. -Proof. - rewrite elem_of_down_close; intros (?&?&?&?&?&?). - eapply lft_alive_in_subseteq, gmultiset_subset_subseteq; eauto. -Qed. -Lemma down_close_disjoint A I K : K ⊥ down_close A I K. -Proof. intros κ. rewrite elem_of_down_close. naive_solver. Qed. -Lemma down_close_subseteq A I K : - down_close A I K ⊆ dom (gset lft) I. -Proof. intros κ [??]%elem_of_down_close. by apply elem_of_dom. Qed. - -Lemma lft_create E : - ↑lftN ⊆ E → - lft_ctx ={E}=∗ ∃ κ, 1.[κ] ∗ □ (1.[κ] ={⊤,⊤∖↑lftN}▷=∗ [†κ]). -Proof. - iIntros (?) "#Hmgmt". - iInv mgmtN as (A I) "(>HA & >HI & Hinv)" "Hclose". - destruct (exist_fresh (dom (gset _) A)) as [Λ HΛ%not_elem_of_dom]. - iMod (own_update with "HA") as "[HA HΛ]". - { apply auth_update_alloc, (alloc_singleton_local_update _ Λ (Cinl 1%Qp))=>//. - by rewrite lookup_fmap HΛ. } - iMod ("Hclose" with "[HA HI Hinv]") as "_". - { iNext. rewrite /lfts_inv /own_alft_auth. - iExists (<[Λ:=true]>A), I; rewrite fmap_insert; iFrame. - iApply (big_sepS_impl _ _ (dom (gset lft) I) with "[$Hinv]"). - iAlways. rewrite /lft_inv. iIntros (κ ?) "[[Hκ %]|[Hκ %]]". - - iLeft. iFrame "Hκ". iPureIntro. by apply lft_alive_in_insert. - - iRight. iFrame "Hκ". iPureIntro. by apply lft_dead_in_insert. } - iModIntro; iExists {[ Λ ]}. - rewrite {1}/lft_tok big_sepMS_singleton. iFrame "HΛ". - clear I A HΛ. iIntros "!# HΛ". - iApply (step_fupd_mask_mono ⊤ _ _ (⊤∖↑mgmtN)); [solve_ndisj..|]. - iInv mgmtN as (A I) "(>HA & >HI & Hinv)" "Hclose". - rewrite /lft_tok big_sepMS_singleton. - iDestruct (own_valid_2 with "HA HΛ") - as %[[s [?%leibniz_equiv ?]]%singleton_included _]%auth_valid_discrete_2. - iMod (own_update_2 with "HA HΛ") as "[HA HΛ]". - { by eapply auth_update, singleton_local_update, - (exclusive_local_update _ (Cinr ())). } - iDestruct "HΛ" as "#HΛ". iModIntro; iNext. - pose (K := kill_set I Λ); pose (K' := down_close A I K). - assert (K ⊥ K') by (by apply down_close_disjoint). - destruct (proj1 (subseteq_disjoint_union_L (K ∪ K') - (dom (gset lft) I))) as (K''&HI&?). - { apply union_least. apply kill_set_subseteq. apply down_close_subseteq. } - rewrite HI !big_sepS_union //. iDestruct "Hinv" as "[[HinvK HinvD] Hinv]". - iAssert ([∗ set] κ ∈ K', lft_inv_alive κ)%I with "[HinvD]" as "HinvD". - { iApply (big_sepS_impl _ _ K' with "[$HinvD]"); iIntros "!#". - rewrite /lft_inv. iIntros (κ Hκ) "[[$ _]|[_ %]]". - destruct (lft_alive_and_dead_in A κ); eauto using down_close_lft_alive_in. } - iAssert ([∗ set] κ ∈ K, lft_inv A κ ∗ [† κ])%I with "[HinvK]" as "HinvK". - { iApply (big_sepS_impl _ _ K with "[$HinvK]"); iIntros "!#". - iIntros (κ [? _]%elem_of_kill_set) "$". rewrite /lft_dead. eauto. } - iMod (lfts_kill A I K K' with "[$HI $HinvD] HinvK") as "[[HI HinvD] HinvK]". - { intros κ κ' [??]%elem_of_kill_set ??. apply elem_of_kill_set. - split; last done. by eapply gmultiset_elem_of_subseteq. } - { intros κ κ' ?????. apply elem_of_down_close; eauto 10. } - iMod ("Hclose" with "[-]") as "_"; last first. - { iModIntro. rewrite /lft_dead. iExists Λ. - rewrite elem_of_singleton. auto. } - iNext. iExists (<[Λ:=false]>A), I. - rewrite /own_alft_auth fmap_insert. iFrame "HA HI". - rewrite HI !big_sepS_union //. - iSplitL "HinvK HinvD"; first iSplitL "HinvK". - - iApply (big_sepS_impl _ _ K with "[$HinvK]"); iIntros "!#". - iIntros (κ [? _]%elem_of_kill_set) "Hdead". rewrite /lft_inv. - iRight. iFrame. iPureIntro. by apply lft_dead_in_insert_false'. - - iApply (big_sepS_impl _ _ K' with "[$HinvD]"); iIntros "!#". - iIntros (κ Hκ) "Halive". rewrite /lft_inv. - iLeft. iFrame "Halive". iPureIntro. - assert (lft_alive_in A κ) as Halive by (by eapply down_close_lft_alive_in). - apply lft_alive_in_insert_false; last done. - apply elem_of_down_close in Hκ as (?&HFOO&_). - move: HFOO. by rewrite elem_of_kill_set not_and_l=> -[?|[] //]. - - iApply (big_sepS_impl _ _ K'' with "[$Hinv]"); iIntros "!#". - rewrite /lft_inv. iIntros (κ Hκ) "[[? %]|[? %]]". - + iLeft. iFrame. iPureIntro. - apply lft_alive_in_insert_false; last done. - assert (κ ∉ K). intros ?. eapply H5. 2: eauto. rewrite elem_of_union. eauto. - move: H7. rewrite elem_of_kill_set not_and_l. intros [?|?]. done. -contradict H7. apply elem_of_dom. set_solver +HI Hκ. - + iRight. iFrame. iPureIntro. by apply lft_dead_in_insert_false. -Qed. - -(** Basic borrows *) -Lemma bor_create E κ P : - ↑lftN ⊆ E → - lft_ctx ⊢ ▷ P ={E}=∗ &{κ} P ∗ ([†κ] ={E}=∗ ▷ P). -Proof. Admitted. -Lemma bor_fake E κ P : - ↑lftN ⊆ E → - lft_ctx ⊢ [†κ] ={E}=∗ &{κ}P. -Proof. - iIntros (?) "#?". (* iDestruct 1 as (Λ) "[% ?]". *) -Admitted. -Lemma bor_sep E κ P Q : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ} (P ∗ Q) ={E}=∗ &{κ} P ∗ &{κ} Q. -Proof. - iIntros (?) "#? Hbor". -Admitted. -Lemma bor_combine E κ P Q : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ} P -∗ &{κ} Q ={E}=∗ &{κ} (P ∗ Q). -Proof. Admitted. -Lemma bor_acc_strong E q κ P : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ} P -∗ q.[κ] ={E}=∗ ▷ P ∗ - ∀ Q, ▷ Q ∗ ▷([†κ] -∗ ▷ Q ={⊤∖↑lftN}=∗ ▷ P) ={E}=∗ &{κ} Q ∗ q.[κ]. -Proof. Admitted. -Lemma bor_acc_atomic_strong E κ P : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ} P ={E,E∖↑lftN}=∗ - (▷ P ∗ ∀ Q, ▷ Q ∗ ▷ ([†κ] -∗ ▷ Q ={⊤∖↑lftN}=∗ ▷ P) ={E∖↑lftN,E}=∗ &{κ} Q) ∨ - [†κ] ∗ |={E∖↑lftN,E}=> True. -Proof. Admitted. -Lemma bor_reborrow' E κ κ' P : - ↑lftN ⊆ E → κ ⊆ κ' → - lft_ctx ⊢ &{κ} P ={E}=∗ &{κ'} P ∗ ([†κ'] ={E}=∗ &{κ} P). -Proof. Admitted. -Lemma bor_unnest E κ κ' P : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ'} &{κ} P ={E}▷=∗ &{κ ∪ κ'} P. -Proof. Admitted. - -(** Indexed borrow *) -Lemma idx_bor_acc E q κ i P : - ↑lftN ⊆ E → - lft_ctx ⊢ idx_bor κ i P -∗ idx_bor_own 1 i -∗ q.[κ] ={E}=∗ - ▷ P ∗ (▷ P ={E}=∗ idx_bor_own 1 i ∗ q.[κ]). -Proof. Admitted. - -Lemma idx_bor_atomic_acc E q κ i P : - ↑lftN ⊆ E → - lft_ctx ⊢ idx_bor κ i P -∗ idx_bor_own q i ={E,E∖↑lftN}=∗ - ▷ P ∗ (▷ P ={E∖↑lftN,E}=∗ idx_bor_own q i) ∨ - [†κ] ∗ (|={E∖↑lftN,E}=> idx_bor_own q i). -Proof. Admitted. - -Lemma idx_bor_shorten κ κ' i P : - κ ⊑ κ' ⊢ idx_bor κ' i P -∗ idx_bor κ i P. -Proof. Admitted. - -(*** Derived lemmas *) -Lemma bor_acc E q κ P : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ}P -∗ q.[κ] ={E}=∗ ▷ P ∗ (▷ P ={E}=∗ &{κ}P ∗ q.[κ]). -Proof. - iIntros (?) "#LFT HP Htok". - iMod (bor_acc_strong with "LFT HP Htok") as "[HP Hclose]"; first done. - iIntros "!> {$HP} HP". iApply "Hclose". by iIntros "{$HP}!>_$". -Qed. - -Lemma bor_exists {A} (Φ : A → iProp Σ) `{!Inhabited A} E κ : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ}(∃ x, Φ x) ={E}=∗ ∃ x, &{κ}Φ x. -Proof. - iIntros (?) "#LFT Hb". - iMod (bor_acc_atomic_strong with "LFT Hb") as "[[HΦ Hclose]|[H† Hclose]]"; first done. - - iDestruct "HΦ" as (x) "HΦ". iExists x. - iApply "Hclose". iIntros "{$HΦ} !> _ ?"; eauto. - - iMod "Hclose" as "_". iExists inhabitant. by iApply (bor_fake with "LFT"). -Qed. - -Lemma bor_or E κ P Q : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ}(P ∨ Q) ={E}=∗ (&{κ}P ∨ &{κ}Q). -Proof. - iIntros (?) "#LFT H". rewrite uPred.or_alt. - iMod (bor_exists with "LFT H") as ([]) "H"; auto. -Qed. - -Lemma bor_persistent `{!PersistentP P} E κ q : - ↑lftN ⊆ E → - lft_ctx ⊢ &{κ}P -∗ q.[κ] ={E}=∗ ▷ P ∗ q.[κ]. -Proof. - iIntros (?) "#LFT Hb Htok". - iMod (bor_acc with "LFT Hb Htok") as "[#HP Hob]"; first done. - by iMod ("Hob" with "HP") as "[_$]". -Qed. - -Lemma lft_incl_acc E κ κ' q : - ↑lftN ⊆ E → - κ ⊑ κ' ⊢ q.[κ] ={E}=∗ ∃ q', q'.[κ'] ∗ (q'.[κ'] ={E}=∗ q.[κ]). -Proof. - rewrite /lft_incl. - iIntros (?) "#[H _] Hq". iApply fupd_mask_mono; first done. - iMod ("H" with "* Hq") as (q') "[Hq' Hclose]". iExists q'. - iIntros "{$Hq'} !> Hq". iApply fupd_mask_mono; first done. by iApply "Hclose". -Qed. - -Lemma lft_incl_dead E κ κ' : ↑lftN ⊆ E → κ ⊑ κ' ⊢ [†κ'] ={E}=∗ [†κ]. -Proof. - rewrite /lft_incl. - iIntros (?) "#[_ H] Hq". iApply fupd_mask_mono; first done. by iApply "H". -Qed. - -Lemma lft_le_incl κ κ' : κ' ⊆ κ → True ⊢ κ ⊑ κ'. -Proof. (* - iIntros (->%gmultiset_union_difference) "!#". iSplitR. - - iIntros (q). rewrite -lft_tok_op. iIntros (q) "[Hκ' Hκ0]". iExists q. iIntros "!>{$Hκ'}Hκ'!>". by iSplitR "Hκ0". - - iIntros "? !>". iApply lft_dead_or. auto. -Qed. *) Admitted. - -Lemma lft_incl_refl κ : True ⊢ κ ⊑ κ. -Proof. by apply lft_le_incl. Qed. - -Lemma lft_incl_trans κ κ' κ'': κ ⊑ κ' ∗ κ' ⊑ κ'' ⊢ κ ⊑ κ''. -Proof. - rewrite /lft_incl. iIntros "[#[H1 H1†] #[H2 H2†]] !#". iSplitR. - - iIntros (q) "Hκ". - iMod ("H1" with "*Hκ") as (q') "[Hκ' Hclose]". - iMod ("H2" with "*Hκ'") as (q'') "[Hκ'' Hclose']". - iExists q''. iIntros "{$Hκ''} !> Hκ''". - iMod ("Hclose'" with "Hκ''") as "Hκ'". by iApply "Hclose". - - iIntros "H†". iMod ("H2†" with "H†"). by iApply "H1†". -Qed. - -Lemma bor_shorten κ κ' P: κ ⊑ κ' ⊢ &{κ'}P -∗ &{κ}P. -Proof. - iIntros "Hκκ' H". rewrite /bor. iDestruct "H" as (i) "[??]". - iExists i. iFrame. (* -Check idx_bor_shorten. - by iApply (idx_bor_shorten with "Hκκ'"). - Qed. *) Admitted. - -Lemma lft_incl_lb κ κ' κ'' : κ ⊑ κ' ∗ κ ⊑ κ'' ⊢ κ ⊑ κ' ∪ κ''. -Proof. (* - iIntros "[#[H1 H1†] #[H2 H2†]]!#". iSplitR. - - iIntros (q) "[Hκ'1 Hκ'2]". - iMod ("H1" with "*Hκ'1") as (q') "[Hκ' Hclose']". - iMod ("H2" with "*Hκ'2") as (q'') "[Hκ'' Hclose'']". - destruct (Qp_lower_bound q' q'') as (qq & q'0 & q''0 & -> & ->). - iExists qq. rewrite -lft_tok_op !lft_tok_frac_op. - iDestruct "Hκ'" as "[$ Hκ']". iDestruct "Hκ''" as "[$ Hκ'']". - iIntros "!>[Hκ'0 Hκ''0]". - iMod ("Hclose'" with "[$Hκ' $Hκ'0]") as "$". - by iMod ("Hclose''" with "[$Hκ'' $Hκ''0]") as "$". - - rewrite -lft_dead_or. iIntros "[H†|H†]". by iApply "H1†". by iApply "H2†". -Qed. *) Admitted. - -Lemma lft_incl_static κ : True ⊢ κ ⊑ static. -Proof. - iIntros "!#". iSplitR. - - iIntros (q) "?". iExists 1%Qp. iSplitR. by iApply lft_tok_static. auto. - - iIntros "Hst". by iDestruct (lft_dead_static with "Hst") as "[]". -Qed. - -Lemma reborrow E P κ κ' : - ↑lftN ⊆ E → - lft_ctx ⊢ κ' ⊑ κ -∗ &{κ}P ={E}=∗ &{κ'}P ∗ ([†κ'] ={E}=∗ &{κ}P). -Proof. - iIntros (?) "#LFT #H⊑ HP". iMod (bor_reborrow' with "LFT HP") as "[Hκ' H∋]". - done. (* by exists κ'. - iDestruct (borrow_shorten with "[H⊑] Hκ'") as "$". - { iApply lft_incl_lb. iSplit. done. iApply lft_incl_refl. } - iIntros "!>Hκ'". iApply ("H∋" with "[Hκ']"). iApply lft_dead_or. auto. -Qed. -*) -Admitted. diff --git a/theories/lifetime/creation.v b/theories/lifetime/creation.v new file mode 100644 index 00000000..26a83c55 --- /dev/null +++ b/theories/lifetime/creation.v @@ -0,0 +1,294 @@ +From lrust.lifetime Require Export primitive. +From iris.algebra Require Import csum auth frac gmap dec_agree gset. +From iris.base_logic Require Import big_op. +From iris.base_logic.lib Require Import boxes. +From iris.proofmode Require Import tactics. + +Section creation. +Context `{invG Σ, lftG Σ}. +Implicit Types κ : lft. + +(* Lifetime creation *) +Lemma lft_inh_kill E κ Q : + ↑inhN ⊆ E → + lft_inh κ false Q ∗ ▷ Q ={E}=∗ lft_inh κ true Q. +Proof. + rewrite /lft_inh. iIntros (?) "[Hinh HQ]". + iDestruct "Hinh" as (E') "[Hinh Hbox]". + iMod (box_fill_all with "[$Hbox $HQ]") as "?"=>//. + rewrite fmap_to_gmap. iModIntro. iExists E'. by iFrame. +Qed. + +Lemma lft_vs_inv_frame (KI K : gset lft) κ : + (∀ κ', κ' ∈ KI → κ' ⊂ κ → κ' ∈ K) → + ([∗ set] κ' ∈ K, lft_inv_alive κ') ⊢ + ([∗ set] κ' ∈ KI, ⌜κ' ⊂ κ⌝ → lft_inv_alive κ') ∗ + (([∗ set] κ' ∈ KI, ⌜κ' ⊂ κ⌝ → lft_inv_alive κ') -∗ + ([∗ set] κ' ∈ K, lft_inv_alive κ')). +Proof. + intros ?. + destruct (proj1 (subseteq_disjoint_union_L (filter (⊂ κ) KI) K)) as (K'&->&?). + { intros κ'. rewrite elem_of_filter. set_solver. } + rewrite big_sepS_union // big_sepS_filter. iIntros "[$ $]"; auto. +Qed. + +Lemma ilft_create A I κ : + own_ilft_auth I ⊢ own_alft_auth A -∗ ▷ ([∗ set] κ ∈ dom _ I, lft_inv A κ) + ==∗ ∃ A' I', ⌜is_Some (I' !! κ)⌝ ∗ + own_ilft_auth I' ∗ own_alft_auth A' ∗ ▷ ([∗ set] κ ∈ dom _ I', lft_inv A' κ). +Proof. + iIntros "HI HA HA'". + destruct (decide (is_Some (I !! κ))) as [?|HIκ%eq_None_not_Some]. + { iModIntro. iExists A, I. by iFrame. } + iMod (own_alloc (● 0 ⋅ ◯ 0)) as (γcnt) "[Hcnt Hcnt']"; first done. + iMod (own_alloc ((● ∅ ⋅ ◯ ∅) :auth (gmap slice_name + (frac * dec_agree bor_state)))) as (γbor) "[Hbor Hbor']"; + first by apply auth_valid_discrete_2. + iMod (own_alloc ((● ∅ ⋅ ◯ ∅) :auth (gset_disj slice_name))) + as (γinh) "[Hinh Hinh']"; first by apply auth_valid_discrete_2. + set (γs := LftNames γbor γcnt γinh). + iMod (own_update with "HI") as "[HI Hγs]". + { apply auth_update_alloc, + (alloc_singleton_local_update _ κ (DecAgree γs)); last done. + by rewrite lookup_fmap HIκ. } + iDestruct "Hγs" as "#Hγs". + iAssert (lft_inv_dead κ ∧ lft_inv_alive κ)%I + with "[-HA HA' HI]" as "Hdeadandalive". + { iSplit. + - rewrite /lft_inv_dead. iExists True%I. iSplitL "Hbor". + { rewrite /lft_bor_dead. iExists ∅, True%I. rewrite !to_gmap_empty. + iSplitL "Hbor". iExists γs. by iFrame. iApply box_alloc. } + iSplitL "Hcnt". + { rewrite /own_cnt. iExists γs. by iFrame. } + rewrite /lft_inh. iExists ∅. rewrite to_gmap_empty. + iSplitL; [|iApply box_alloc]. rewrite /own_inh. iExists γs. by iSplit. + - rewrite lft_inv_alive_unfold. iExists True%I, True%I. iSplitL "Hbor". + { rewrite /lft_bor_alive. iExists ∅. rewrite !fmap_empty big_sepM_empty. + iSplitR; [iApply box_alloc|]. iSplit=>//. + rewrite /own_bor. iExists γs. by iFrame. } + rewrite lft_vs_unfold. iSplitR "Hinh". + { iExists 0. iSplitL "Hcnt". + { rewrite /own_cnt. iExists γs. by iFrame. } + iIntros (I') "$ $ _ !>". rewrite /own_cnt. iExists γs. by iFrame. } + rewrite /lft_inh. iExists ∅. rewrite to_gmap_empty. + iSplitL; [|iApply box_alloc]. rewrite /own_inh. iExists γs. by iFrame. } + destruct (lft_alive_or_dead_in A κ) as [(Λ&?&HAΛ)|Haliveordead]. + - iMod (own_update with "HA") as "[HA _]". + { apply auth_update_alloc, + (alloc_singleton_local_update _ Λ (Cinr ())); last done. + by rewrite lookup_fmap HAΛ. } + iModIntro. iExists (<[Λ:=false]>A), (<[κ:=γs]> I). + iSplit; first rewrite lookup_insert; eauto. + rewrite /own_ilft_auth /own_alft_auth !fmap_insert. iFrame "HA HI". + rewrite dom_insert_L big_sepS_insert ?not_elem_of_dom //. + iSplitR "HA'". + { rewrite /lft_inv. iNext. iRight. iSplit. + { by iDestruct "Hdeadandalive" as "[? _]". } + iPureIntro. exists Λ. rewrite lookup_insert; auto. } + iNext. iApply (big_sepS_impl _ _ (dom (gset lft) I) with "[$HA']"). + rewrite /lft_inv. iIntros "!#"; iIntros (κ' ?%elem_of_dom) + "[[HA HA']|[HA HA']]"; iDestruct "HA'" as %HA. + + iLeft. iFrame "HA". iPureIntro. by apply lft_alive_in_insert. + + iRight. iFrame "HA". iPureIntro. by apply lft_dead_in_insert. + - iModIntro. iExists A, (<[κ:=γs]> I). + iSplit; first rewrite lookup_insert; eauto. + iSplitL "HI"; first by rewrite /own_ilft_auth fmap_insert. + rewrite dom_insert_L big_sepS_insert ?not_elem_of_dom //. + iFrame "HA HA'". iNext. rewrite /lft_inv. destruct Haliveordead. + + iLeft. by iDestruct "Hdeadandalive" as "[_ $]". + + iRight. by iDestruct "Hdeadandalive" as "[$ _]". +Qed. + +Lemma lft_kill (I : gmap lft lft_names) (K K' : gset lft) (κ : lft) : + let Iinv := ( + own_ilft_auth I ∗ + ([∗ set] κ' ∈ K, lft_inv_alive κ') ∗ + ([∗ set] κ' ∈ K', lft_inv_dead κ'))%I in + (∀ κ', is_Some (I !! κ') → κ' ⊂ κ → κ' ∈ K) → + (∀ κ', is_Some (I !! κ') → κ ⊂ κ' → κ' ∈ K') → + Iinv ⊢ lft_inv_alive κ -∗ [†κ] ={⊤∖↑mgmtN}=∗ Iinv ∗ lft_inv_dead κ. +Proof. + iIntros (Iinv HK HK') "(HI & Halive & Hdead) Hlalive Hκ". + rewrite lft_inv_alive_unfold; + iDestruct "Hlalive" as (P Q) "(Hbor & Hvs & Hinh)". + rewrite /lft_bor_alive; iDestruct "Hbor" as (B) "(Hbox & Hbor & HB)". + iAssert ⌜∀ i s, B !! i = Some s → s = Bor_in⌝%I with "[#]" as %HB. + { iIntros (i s HBI). + iDestruct (big_sepM_lookup _ B with "HB") as "HB"=> //. + destruct s as [|q|κ']; rewrite /bor_cnt //. + { iDestruct (lft_tok_dead_own with "HB Hκ") as "[]". } + iDestruct "HB" as "[% Hcnt]". + iDestruct (own_cnt_auth with "HI Hcnt") as %?. + iDestruct (big_sepS_elem_of _ K' with "Hdead") as "Hdead"; first by eauto. + rewrite /lft_inv_dead; iDestruct "Hdead" as (R) "(_ & Hcnt' & _)". + iDestruct (own_cnt_valid_2 with "Hcnt' Hcnt") + as %[?%nat_included _]%auth_valid_discrete_2; omega. } + iMod (box_empty_all with "Hbox") as "[HP Hbox]"=>//; first solve_ndisj. + { intros i s. by rewrite lookup_fmap fmap_Some=> -[? [/HB -> ->]]. } + rewrite lft_vs_unfold; iDestruct "Hvs" as (n) "[Hcnt Hvs]". + iDestruct (lft_vs_inv_frame (dom _ I) _ κ with "Halive") as "[Halive Halive']". + { intros κ'. rewrite elem_of_dom. eauto. } + iMod ("Hvs" $! I with "[HI Halive Hbox Hbor] HP Hκ") as "(Hinv & HQ & Hcnt')". + { rewrite lft_vs_inv_unfold. iFrame. rewrite /lft_bor_dead. + iExists (dom _ B), P. rewrite !to_gmap_dom -map_fmap_compose. + rewrite (map_fmap_ext _ ((1%Qp,) ∘ DecAgree) B); last naive_solver. + iFrame. } + rewrite lft_vs_inv_unfold; iDestruct "Hinv" as "(?&HI&Halive)". + iSpecialize ("Halive'" with "Halive"). + iMod (own_cnt_update_2 with "Hcnt Hcnt'") as "?". + { apply auth_update_dealloc, (nat_local_update _ _ 0 0); omega. } + rewrite /Iinv. iFrame "Hdead Halive' HI". + iMod (lft_inh_kill with "[$Hinh $HQ]"); first solve_ndisj. + iModIntro. rewrite /lft_inv_dead. iExists Q. by iFrame. +Qed. + +Lemma lfts_kill A (I : gmap lft lft_names) (K K' : gset lft) : + let Iinv K' := (own_ilft_auth I ∗ [∗ set] κ' ∈ K', lft_inv_alive κ')%I in + (∀ κ κ', κ ∈ K → is_Some (I !! κ') → κ ⊆ κ' → κ' ∈ K) → + (∀ κ κ', κ ∈ K → lft_alive_in A κ → is_Some (I !! κ') → + κ' ∉ K → κ' ⊂ κ → κ' ∈ K') → + Iinv K' ⊢ ([∗ set] κ ∈ K, lft_inv A κ ∗ [†κ]) + ={⊤∖↑mgmtN}=∗ Iinv K' ∗ [∗ set] κ ∈ K, lft_inv_dead κ. +Proof. + intros Iinv. revert K'. + induction (collection_wf K) as [K _ IH]=> K' HK HK'. + iIntros "[HI Halive] HK". + pose (Kalive := filter (lft_alive_in A) K). + destruct (decide (Kalive = ∅)) as [HKalive|]. + { iModIntro. rewrite /Iinv. iFrame. + iApply (big_sepS_impl _ _ K with "[$HK]"); iAlways. + rewrite /lft_inv. iIntros (κ Hκ) "[[[_ %]|[$ _]] _]". set_solver. } + destruct (minimal_exists_L (⊂) Kalive) + as (κ & [Hκalive HκK]%elem_of_filter & Hκmin); first done. + iDestruct (big_sepS_delete _ K κ with "HK") as "[[Hκinv Hκ] HK]"; first done. + rewrite {1}/lft_inv. iDestruct "Hκinv" as "[[Hκalive _]|[_ %]]"; last first. + { by destruct (lft_alive_and_dead_in A κ). } + iAssert ⌜κ ∉ K'⌝%I with "[#]" as %HκK'. + { iIntros (Hκ). iApply (lft_inv_alive_twice κ with "Hκalive"). + by iApply (big_sepS_elem_of _ K' κ with "Halive"). } + specialize (IH (K ∖ {[ κ ]})). feed specialize IH; [set_solver +HκK|]. + iMod (IH ({[ κ ]} ∪ K') with "[HI Halive Hκalive] HK") as "[[HI Halive] Hdead]". + { intros κ' κ''. + rewrite !elem_of_difference !elem_of_singleton=> -[? Hneq] ??. + split; [by eauto|]; intros ->. + eapply (minimal_strict_1 _ _ κ' Hκmin), strict_spec_alt; eauto. + apply elem_of_filter; eauto using lft_alive_in_subseteq. } + { intros κ' κ'' Hκ' ? [γs'' ?]. + destruct (decide (κ'' = κ)) as [->|]; [set_solver +|]. + move: Hκ'; rewrite not_elem_of_difference elem_of_difference + elem_of_union not_elem_of_singleton elem_of_singleton. + intros [??] [?|?]; eauto. } + { rewrite /Iinv big_sepS_insert //. iFrame. } + iDestruct (big_sepS_insert _ K' with "Halive") as "[Hκalive Halive]"; first done. + iMod (lft_kill with "[$HI $Halive $Hdead] Hκalive Hκ") + as "[(HI&Halive&Hdead) Hκdead]". + { intros κ' ??. eapply (HK' κ); eauto. + intros ?. eapply (minimal_strict_1 _ _ _ Hκmin); eauto. + apply elem_of_filter; split; last done. + eapply lft_alive_in_subseteq, gmultiset_subset_subseteq; eauto. } + { intros κ' ? [??]%strict_spec_alt. + rewrite elem_of_difference elem_of_singleton; eauto. } + iModIntro. rewrite /Iinv (big_sepS_delete _ K) //. iFrame. +Qed. + +Definition kill_set (I : gmap lft lft_names) (Λ : atomic_lft) : gset lft := + filter (Λ ∈) (dom (gset lft) I). + +Lemma elem_of_kill_set I Λ κ : κ ∈ kill_set I Λ ↔ Λ ∈ κ ∧ is_Some (I !! κ). +Proof. by rewrite /kill_set elem_of_filter elem_of_dom. Qed. +Lemma kill_set_subseteq I Λ : kill_set I Λ ⊆ dom (gset lft) I. +Proof. intros κ [??]%elem_of_kill_set. by apply elem_of_dom. Qed. + +Definition down_close (A : gmap atomic_lft bool) + (I : gmap lft lft_names) (K : gset lft) : gset lft := + filter (λ κ, κ ∉ K ∧ + set_Exists (λ κ', κ ⊂ κ' ∧ lft_alive_in A κ') K) (dom (gset lft) I). +Lemma elem_of_down_close A I K κ : + κ ∈ down_close A I K ↔ + is_Some (I !! κ) ∧ κ ∉ K ∧ ∃ κ', κ' ∈ K ∧ κ ⊂ κ' ∧ lft_alive_in A κ'. +Proof. rewrite /down_close elem_of_filter elem_of_dom /set_Exists. tauto. Qed. + +Lemma down_close_lft_alive_in A I K κ : κ ∈ down_close A I K → lft_alive_in A κ. +Proof. + rewrite elem_of_down_close; intros (?&?&?&?&?&?). + eapply lft_alive_in_subseteq, gmultiset_subset_subseteq; eauto. +Qed. +Lemma down_close_disjoint A I K : K ⊥ down_close A I K. +Proof. intros κ. rewrite elem_of_down_close. naive_solver. Qed. +Lemma down_close_subseteq A I K : + down_close A I K ⊆ dom (gset lft) I. +Proof. intros κ [??]%elem_of_down_close. by apply elem_of_dom. Qed. + +Lemma lft_create E : + ↑lftN ⊆ E → + lft_ctx ={E}=∗ ∃ κ, 1.[κ] ∗ □ (1.[κ] ={⊤,⊤∖↑lftN}▷=∗ [†κ]). +Proof. + iIntros (?) "#Hmgmt". + iInv mgmtN as (A I) "(>HA & >HI & Hinv)" "Hclose". + destruct (exist_fresh (dom (gset _) A)) as [Λ HΛ%not_elem_of_dom]. + iMod (own_update with "HA") as "[HA HΛ]". + { apply auth_update_alloc, (alloc_singleton_local_update _ Λ (Cinl 1%Qp))=>//. + by rewrite lookup_fmap HΛ. } + iMod ("Hclose" with "[HA HI Hinv]") as "_". + { iNext. rewrite /lfts_inv /own_alft_auth. + iExists (<[Λ:=true]>A), I; rewrite fmap_insert; iFrame. + iApply (big_sepS_impl _ _ (dom (gset lft) I) with "[$Hinv]"). + iAlways. rewrite /lft_inv. iIntros (κ ?) "[[Hκ %]|[Hκ %]]". + - iLeft. iFrame "Hκ". iPureIntro. by apply lft_alive_in_insert. + - iRight. iFrame "Hκ". iPureIntro. by apply lft_dead_in_insert. } + iModIntro; iExists {[ Λ ]}. + rewrite {1}/lft_tok big_sepMS_singleton. iFrame "HΛ". + clear I A HΛ. iIntros "!# HΛ". + iApply (step_fupd_mask_mono ⊤ _ _ (⊤∖↑mgmtN)); [solve_ndisj..|]. + iInv mgmtN as (A I) "(>HA & >HI & Hinv)" "Hclose". + rewrite /lft_tok big_sepMS_singleton. + iDestruct (own_valid_2 with "HA HΛ") + as %[[s [?%leibniz_equiv ?]]%singleton_included _]%auth_valid_discrete_2. + iMod (own_update_2 with "HA HΛ") as "[HA HΛ]". + { by eapply auth_update, singleton_local_update, + (exclusive_local_update _ (Cinr ())). } + iDestruct "HΛ" as "#HΛ". iModIntro; iNext. + pose (K := kill_set I Λ); pose (K' := down_close A I K). + assert (K ⊥ K') by (by apply down_close_disjoint). + destruct (proj1 (subseteq_disjoint_union_L (K ∪ K') + (dom (gset lft) I))) as (K''&HI&?). + { apply union_least. apply kill_set_subseteq. apply down_close_subseteq. } + rewrite HI !big_sepS_union //. iDestruct "Hinv" as "[[HinvK HinvD] Hinv]". + iAssert ([∗ set] κ ∈ K', lft_inv_alive κ)%I with "[HinvD]" as "HinvD". + { iApply (big_sepS_impl _ _ K' with "[$HinvD]"); iIntros "!#". + rewrite /lft_inv. iIntros (κ Hκ) "[[$ _]|[_ %]]". + destruct (lft_alive_and_dead_in A κ); eauto using down_close_lft_alive_in. } + iAssert ([∗ set] κ ∈ K, lft_inv A κ ∗ [† κ])%I with "[HinvK]" as "HinvK". + { iApply (big_sepS_impl _ _ K with "[$HinvK]"); iIntros "!#". + iIntros (κ [? _]%elem_of_kill_set) "$". rewrite /lft_dead. eauto. } + iMod (lfts_kill A I K K' with "[$HI $HinvD] HinvK") as "[[HI HinvD] HinvK]". + { intros κ κ' [??]%elem_of_kill_set ??. apply elem_of_kill_set. + split; last done. by eapply gmultiset_elem_of_subseteq. } + { intros κ κ' ?????. apply elem_of_down_close; eauto 10. } + iMod ("Hclose" with "[-]") as "_"; last first. + { iModIntro. rewrite /lft_dead. iExists Λ. + rewrite elem_of_singleton. auto. } + iNext. iExists (<[Λ:=false]>A), I. + rewrite /own_alft_auth fmap_insert. iFrame "HA HI". + rewrite HI !big_sepS_union //. + iSplitL "HinvK HinvD"; first iSplitL "HinvK". + - iApply (big_sepS_impl _ _ K with "[$HinvK]"); iIntros "!#". + iIntros (κ [? _]%elem_of_kill_set) "Hdead". rewrite /lft_inv. + iRight. iFrame. iPureIntro. by apply lft_dead_in_insert_false'. + - iApply (big_sepS_impl _ _ K' with "[$HinvD]"); iIntros "!#". + iIntros (κ Hκ) "Halive". rewrite /lft_inv. + iLeft. iFrame "Halive". iPureIntro. + assert (lft_alive_in A κ) as Halive by (by eapply down_close_lft_alive_in). + apply lft_alive_in_insert_false; last done. + apply elem_of_down_close in Hκ as (?&HFOO&_). + move: HFOO. by rewrite elem_of_kill_set not_and_l=> -[?|[] //]. + - iApply (big_sepS_impl _ _ K'' with "[$Hinv]"); iIntros "!#". + rewrite /lft_inv. iIntros (κ Hκ) "[[? %]|[? %]]". + + iLeft. iFrame. iPureIntro. + apply lft_alive_in_insert_false; last done. + assert (κ ∉ K). intros ?. eapply H5. 2: eauto. rewrite elem_of_union. eauto. + move: H7. rewrite elem_of_kill_set not_and_l. intros [?|?]. done. +contradict H7. apply elem_of_dom. set_solver +HI Hκ. + + iRight. iFrame. iPureIntro. by apply lft_dead_in_insert_false. +Qed. +End creation. diff --git a/theories/lifetime/definitions.v b/theories/lifetime/definitions.v new file mode 100644 index 00000000..41f14673 --- /dev/null +++ b/theories/lifetime/definitions.v @@ -0,0 +1,192 @@ +From iris.algebra Require Import csum auth frac gmap dec_agree gset. +From iris.prelude Require Export gmultiset strings. +From iris.base_logic.lib Require Export invariants. +From iris.base_logic.lib Require Import boxes. +From iris.base_logic Require Import big_op. + +Definition lftN : namespace := nroot .@ "lft". +Definition borN : namespace := lftN .@ "bor". +Definition inhN : namespace := lftN .@ "inh". +Definition mgmtN : namespace := lftN .@ "mgmt". + +Definition atomic_lft := positive. +Notation lft := (gmultiset positive). +Definition static : lft := ∅. + +Inductive bor_state := + | Bor_in + | Bor_open (q : frac) + | Bor_rebor (κ : lft). +Instance bor_state_eq_dec : EqDecision bor_state. +Proof. solve_decision. Defined. + +Definition bor_filled (s : bor_state) : bool := + match s with Bor_in => true | _ => false end. + +Definition lft_stateR := csumR fracR unitR. +Definition to_lft_stateR (b : bool) : lft_stateR := + if b then Cinl 1%Qp else Cinr (). + +Record lft_names := LftNames { + bor_name : gname; + cnt_name : gname; + inh_name : gname +}. +Instance lft_names_eq_dec : EqDecision lft_names. +Proof. solve_decision. Defined. + +Class lftG Σ := LftG { + lft_box :> boxG Σ; + alft_inG :> inG Σ (authR (gmapUR atomic_lft lft_stateR)); + alft_name : gname; + ilft_inG :> inG Σ (authR (gmapUR lft (dec_agreeR lft_names))); + ilft_name : gname; + lft_bor_box :> + inG Σ (authR (gmapUR slice_name (prodR fracR (dec_agreeR bor_state)))); + lft_cnt_inG :> inG Σ (authR natUR); + lft_inh_box :> inG Σ (authR (gset_disjUR slice_name)); +}. + +Section defs. + Context `{invG Σ, lftG Σ}. + + Definition lft_tok (q : Qp) (κ : lft) : iProp Σ := + ([∗ mset] Λ ∈ κ, own alft_name (◯ {[ Λ := Cinl q ]}))%I. + + Definition lft_dead (κ : lft) : iProp Σ := + (∃ Λ, ⌜Λ ∈ κ⌝ ∗ own alft_name (◯ {[ Λ := Cinr () ]}))%I. + + Definition own_alft_auth (A : gmap atomic_lft bool) : iProp Σ := + own alft_name (● (to_lft_stateR <$> A)). + Definition own_ilft_auth (I : gmap lft lft_names) : iProp Σ := + own ilft_name (● (DecAgree <$> I)). + + Definition own_bor (κ : lft) + (x : auth (gmap slice_name (frac * dec_agree bor_state))) : iProp Σ := + (∃ γs, + own ilft_name (◯ {[ κ := DecAgree γs ]}) ∗ + own (bor_name γs) x)%I. + + Definition own_cnt (κ : lft) (x : auth nat) : iProp Σ := + (∃ γs, + own ilft_name (◯ {[ κ := DecAgree γs ]}) ∗ + own (cnt_name γs) x)%I. + + Definition own_inh (κ : lft) (x : auth (gset_disj slice_name)) : iProp Σ := + (∃ γs, + own ilft_name (◯ {[ κ := DecAgree γs ]}) ∗ + own (inh_name γs) x)%I. + + Definition bor_cnt (κ : lft) (s : bor_state) : iProp Σ := + match s with + | Bor_in => True + | Bor_open q => lft_tok q κ + | Bor_rebor κ' => ⌜κ ⊂ κ'⌝ ∗ own_cnt κ' (◯ 1) + end%I. + + Definition lft_bor_alive (κ : lft) (P : iProp Σ) : iProp Σ := + (∃ B : gmap slice_name bor_state, + box borN (bor_filled <$> B) P ∗ + own_bor κ (● ((1%Qp,) ∘ DecAgree <$> B)) ∗ + [∗ map] s ∈ B, bor_cnt κ s)%I. + + Definition lft_bor_dead (κ : lft) : iProp Σ := + (∃ (B: gset slice_name) (P : iProp Σ), + own_bor κ (● to_gmap (1%Qp, DecAgree Bor_in) B) ∗ + box borN (to_gmap false B) P)%I. + + Definition lft_inh (κ : lft) (s : bool) (P : iProp Σ) : iProp Σ := + (∃ E : gset slice_name, + own_inh κ (● GSet E) ∗ + box inhN (to_gmap s E) P)%I. + + Definition lft_vs_inv_go (κ : lft) (lft_inv_alive : ∀ κ', κ' ⊂ κ → iProp Σ) + (I : gmap lft lft_names) : iProp Σ := + (lft_bor_dead κ ∗ + own_ilft_auth I ∗ + [∗ set] κ' ∈ dom _ I, ∀ Hκ : κ' ⊂ κ, lft_inv_alive κ' Hκ)%I. + + Definition lft_vs_go (κ : lft) (lft_inv_alive : ∀ κ', κ' ⊂ κ → iProp Σ) + (P Q : iProp Σ) : iProp Σ := + (∃ n : nat, + own_cnt κ (● n) ∗ + ∀ I : gmap lft lft_names, + lft_vs_inv_go κ lft_inv_alive I -∗ ▷ P -∗ lft_dead κ + ={⊤∖↑mgmtN}=∗ + lft_vs_inv_go κ lft_inv_alive I ∗ ▷ Q ∗ own_cnt κ (◯ n))%I. + + Definition lft_inv_alive_go (κ : lft) + (lft_inv_alive : ∀ κ', κ' ⊂ κ → iProp Σ) : iProp Σ := + (∃ P Q, + lft_bor_alive κ P ∗ + lft_vs_go κ lft_inv_alive P Q ∗ + lft_inh κ false Q)%I. + + Definition lft_inv_alive (κ : lft) : iProp Σ := + Fix_F _ lft_inv_alive_go (gmultiset_wf κ). + Definition lft_vs_inv (κ : lft) (I : gmap lft lft_names) : iProp Σ := + lft_vs_inv_go κ (λ κ' _, lft_inv_alive κ') I. + Definition lft_vs (κ : lft) (P Q : iProp Σ) : iProp Σ := + lft_vs_go κ (λ κ' _, lft_inv_alive κ') P Q. + + Definition lft_inv_dead (κ : lft) : iProp Σ := + (∃ P, + lft_bor_dead κ ∗ + own_cnt κ (● 0) ∗ + lft_inh κ true P)%I. + + Definition lft_alive_in (A : gmap atomic_lft bool) (κ : lft) : Prop := + ∀ Λ, Λ ∈ κ → A !! Λ = Some true. + Definition lft_dead_in (A : gmap atomic_lft bool) (κ : lft) : Prop := + ∃ Λ, Λ ∈ κ ∧ A !! Λ = Some false. + + Definition lft_inv (A : gmap atomic_lft bool) (κ : lft) : iProp Σ := + (lft_inv_alive κ ∗ ⌜lft_alive_in A κ⌝ ∨ + lft_inv_dead κ ∗ ⌜lft_dead_in A κ⌝)%I. + + Definition lfts_inv : iProp Σ := + (∃ (A : gmap atomic_lft bool) (I : gmap lft lft_names), + own_alft_auth A ∗ + own_ilft_auth I ∗ + [∗ set] κ ∈ dom _ I, lft_inv A κ)%I. + + Definition lft_ctx : iProp Σ := inv mgmtN lfts_inv. + + Definition lft_incl (κ κ' : lft) : iProp Σ := + (□ ((∀ q, lft_tok q κ ={↑lftN}=∗ ∃ q', + lft_tok q' κ' ∗ (lft_tok q' κ' ={↑lftN}=∗ lft_tok q κ)) ∗ + (lft_dead κ' ={↑lftN}=∗ lft_dead κ)))%I. + + Definition bor_idx := (lft * slice_name)%type. + + Definition idx_bor_own (q : frac) (i : bor_idx) : iProp Σ := + own_bor (i.1) (◯ {[ i.2 := (q,DecAgree Bor_in) ]}). + Definition idx_bor (κ : lft) (i : bor_idx) (P : iProp Σ) : iProp Σ := + (lft_incl κ (i.1) ∗ slice borN (i.2) P)%I. + Definition raw_bor (i : bor_idx) (P : iProp Σ) : iProp Σ := + (idx_bor_own 1 i ∗ slice borN (i.2) P)%I. + Definition bor (κ : lft) (P : iProp Σ) : iProp Σ := + (∃ i, lft_incl κ (i.1) ∗ raw_bor i P)%I. +End defs. + +Instance: Params (@lft_bor_alive) 4. +Instance: Params (@lft_inh) 5. +Instance: Params (@lft_vs) 4. +Instance: Params (@idx_bor) 5. +Instance: Params (@raw_bor) 4. +Instance: Params (@bor) 4. + +Notation "q .[ κ ]" := (lft_tok q κ) + (format "q .[ κ ]", at level 0) : uPred_scope. +Notation "[† κ ]" := (lft_dead κ) (format "[† κ ]"): uPred_scope. + +Notation "&{ κ } P" := (bor κ P) + (format "&{ κ } P", at level 20, right associativity) : uPred_scope. +Notation "&{ κ , i } P" := (idx_bor κ i P) + (format "&{ κ , i } P", at level 20, right associativity) : uPred_scope. + +Infix "⊑" := lft_incl (at level 70) : uPred_scope. + +Typeclasses Opaque lft_tok lft_dead bor_cnt lft_bor_alive lft_bor_dead + lft_inh lft_inv_alive lft_vs_inv lft_vs lft_inv_dead lft_inv lft_incl + idx_bor_own idx_bor raw_bor bor. diff --git a/theories/lifetime/derived.v b/theories/lifetime/derived.v new file mode 100644 index 00000000..d0aca0a0 --- /dev/null +++ b/theories/lifetime/derived.v @@ -0,0 +1,125 @@ +From lrust.lifetime Require Export primitive todo. +From iris.proofmode Require Import tactics. + +Section derived. +Context `{invG Σ, lftG Σ}. +Implicit Types κ : lft. + +(*** Derived lemmas *) +Lemma bor_acc E q κ P : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ}P -∗ q.[κ] ={E}=∗ ▷ P ∗ (▷ P ={E}=∗ &{κ}P ∗ q.[κ]). +Proof. + iIntros (?) "#LFT HP Htok". + iMod (bor_acc_strong with "LFT HP Htok") as "[HP Hclose]"; first done. + iIntros "!> {$HP} HP". iApply "Hclose". by iIntros "{$HP}!>_$". +Qed. + +Lemma bor_exists {A} (Φ : A → iProp Σ) `{!Inhabited A} E κ : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ}(∃ x, Φ x) ={E}=∗ ∃ x, &{κ}Φ x. +Proof. + iIntros (?) "#LFT Hb". + iMod (bor_acc_atomic_strong with "LFT Hb") as "[[HΦ Hclose]|[H† Hclose]]"; first done. + - iDestruct "HΦ" as (x) "HΦ". iExists x. + iApply "Hclose". iIntros "{$HΦ} !> _ ?"; eauto. + - iMod "Hclose" as "_". iExists inhabitant. by iApply (bor_fake with "LFT"). +Qed. + +Lemma bor_or E κ P Q : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ}(P ∨ Q) ={E}=∗ (&{κ}P ∨ &{κ}Q). +Proof. + iIntros (?) "#LFT H". rewrite uPred.or_alt. + iMod (bor_exists with "LFT H") as ([]) "H"; auto. +Qed. + +Lemma bor_persistent `{!PersistentP P} E κ q : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ}P -∗ q.[κ] ={E}=∗ ▷ P ∗ q.[κ]. +Proof. + iIntros (?) "#LFT Hb Htok". + iMod (bor_acc with "LFT Hb Htok") as "[#HP Hob]"; first done. + by iMod ("Hob" with "HP") as "[_$]". +Qed. + +Lemma lft_incl_acc E κ κ' q : + ↑lftN ⊆ E → + κ ⊑ κ' ⊢ q.[κ] ={E}=∗ ∃ q', q'.[κ'] ∗ (q'.[κ'] ={E}=∗ q.[κ]). +Proof. + rewrite /lft_incl. + iIntros (?) "#[H _] Hq". iApply fupd_mask_mono; first done. + iMod ("H" with "* Hq") as (q') "[Hq' Hclose]". iExists q'. + iIntros "{$Hq'} !> Hq". iApply fupd_mask_mono; first done. by iApply "Hclose". +Qed. + +Lemma lft_incl_dead E κ κ' : ↑lftN ⊆ E → κ ⊑ κ' ⊢ [†κ'] ={E}=∗ [†κ]. +Proof. + rewrite /lft_incl. + iIntros (?) "#[_ H] Hq". iApply fupd_mask_mono; first done. by iApply "H". +Qed. + +Lemma lft_le_incl κ κ' : κ' ⊆ κ → True ⊢ κ ⊑ κ'. +Proof. (* + iIntros (->%gmultiset_union_difference) "!#". iSplitR. + - iIntros (q). rewrite -lft_tok_op. iIntros (q) "[Hκ' Hκ0]". iExists q. iIntros "!>{$Hκ'}Hκ'!>". by iSplitR "Hκ0". + - iIntros "? !>". iApply lft_dead_or. auto. +Qed. *) Admitted. + +Lemma lft_incl_refl κ : True ⊢ κ ⊑ κ. +Proof. by apply lft_le_incl. Qed. + +Lemma lft_incl_trans κ κ' κ'': κ ⊑ κ' ∗ κ' ⊑ κ'' ⊢ κ ⊑ κ''. +Proof. + rewrite /lft_incl. iIntros "[#[H1 H1†] #[H2 H2†]] !#". iSplitR. + - iIntros (q) "Hκ". + iMod ("H1" with "*Hκ") as (q') "[Hκ' Hclose]". + iMod ("H2" with "*Hκ'") as (q'') "[Hκ'' Hclose']". + iExists q''. iIntros "{$Hκ''} !> Hκ''". + iMod ("Hclose'" with "Hκ''") as "Hκ'". by iApply "Hclose". + - iIntros "H†". iMod ("H2†" with "H†"). by iApply "H1†". +Qed. + +Lemma bor_shorten κ κ' P: κ ⊑ κ' ⊢ &{κ'}P -∗ &{κ}P. +Proof. + iIntros "Hκκ' H". rewrite /bor. iDestruct "H" as (i) "[??]". + iExists i. iFrame. (* +Check idx_bor_shorten. + by iApply (idx_bor_shorten with "Hκκ'"). + Qed. *) Admitted. + +Lemma lft_incl_lb κ κ' κ'' : κ ⊑ κ' ∗ κ ⊑ κ'' ⊢ κ ⊑ κ' ∪ κ''. +Proof. (* + iIntros "[#[H1 H1†] #[H2 H2†]]!#". iSplitR. + - iIntros (q) "[Hκ'1 Hκ'2]". + iMod ("H1" with "*Hκ'1") as (q') "[Hκ' Hclose']". + iMod ("H2" with "*Hκ'2") as (q'') "[Hκ'' Hclose'']". + destruct (Qp_lower_bound q' q'') as (qq & q'0 & q''0 & -> & ->). + iExists qq. rewrite -lft_tok_op !lft_tok_frac_op. + iDestruct "Hκ'" as "[$ Hκ']". iDestruct "Hκ''" as "[$ Hκ'']". + iIntros "!>[Hκ'0 Hκ''0]". + iMod ("Hclose'" with "[$Hκ' $Hκ'0]") as "$". + by iMod ("Hclose''" with "[$Hκ'' $Hκ''0]") as "$". + - rewrite -lft_dead_or. iIntros "[H†|H†]". by iApply "H1†". by iApply "H2†". +Qed. *) Admitted. + +Lemma lft_incl_static κ : True ⊢ κ ⊑ static. +Proof. + iIntros "!#". iSplitR. + - iIntros (q) "?". iExists 1%Qp. iSplitR. by iApply lft_tok_static. auto. + - iIntros "Hst". by iDestruct (lft_dead_static with "Hst") as "[]". +Qed. + +Lemma reborrow E P κ κ' : + ↑lftN ⊆ E → + lft_ctx ⊢ κ' ⊑ κ -∗ &{κ}P ={E}=∗ &{κ'}P ∗ ([†κ'] ={E}=∗ &{κ}P). +Proof. + iIntros (?) "#LFT #H⊑ HP". iMod (bor_reborrow' with "LFT HP") as "[Hκ' H∋]". + done. (* by exists κ'. + iDestruct (borrow_shorten with "[H⊑] Hκ'") as "$". + { iApply lft_incl_lb. iSplit. done. iApply lft_incl_refl. } + iIntros "!>Hκ'". iApply ("H∋" with "[Hκ']"). iApply lft_dead_or. auto. +Qed. +*) +Admitted. +End derived. diff --git a/theories/lifetime/primitive.v b/theories/lifetime/primitive.v new file mode 100644 index 00000000..27fb4938 --- /dev/null +++ b/theories/lifetime/primitive.v @@ -0,0 +1,298 @@ +From lrust.lifetime Require Export definitions. +From iris.algebra Require Import csum auth frac gmap dec_agree gset. +From iris.base_logic Require Import big_op. +From iris.proofmode Require Import tactics. +Import uPred. + +Section primitive. +Context `{invG Σ, lftG Σ}. +Implicit Types κ : lft. + +(* Unfolding lemmas *) +Lemma lft_vs_inv_go_ne κ (f f' : ∀ κ', κ' ⊂ κ → iProp Σ) I n : + (∀ κ' (Hκ : κ' ⊂ κ), f κ' Hκ ≡{n}≡ f' κ' Hκ) → + lft_vs_inv_go κ f I ≡{n}≡ lft_vs_inv_go κ f' I. +Proof. + intros Hf. apply sep_ne, sep_ne, big_opS_ne=> // κ'. + by apply forall_ne=> Hκ. +Qed. + +Lemma lft_vs_go_ne κ (f f' : ∀ κ', κ' ⊂ κ → iProp Σ) P P' Q Q' n : + (∀ κ' (Hκ : κ' ⊂ κ), f κ' Hκ ≡{n}≡ f' κ' Hκ) → + P ≡{n}≡ P' → Q ≡{n}≡ Q' → + lft_vs_go κ f P Q ≡{n}≡ lft_vs_go κ f' P' Q'. +Proof. + intros Hf HP HQ. apply exist_ne=> n'. + apply sep_ne, forall_ne=> // I. rewrite lft_vs_inv_go_ne //. solve_proper. +Qed. + +Lemma lft_inv_alive_go_ne κ (f f' : ∀ κ', κ' ⊂ κ → iProp Σ) n : + (∀ κ' (Hκ : κ' ⊂ κ), f κ' Hκ ≡{n}≡ f' κ' Hκ) → + lft_inv_alive_go κ f ≡{n}≡ lft_inv_alive_go κ f'. +Proof. + intros Hf. apply exist_ne=> P; apply exist_ne=> Q. by rewrite lft_vs_go_ne. +Qed. + +Lemma lft_inv_alive_unfold κ : + lft_inv_alive κ ⊣⊢ ∃ P Q, lft_bor_alive κ P ∗ lft_vs κ P Q ∗ lft_inh κ false Q. +Proof. + apply equiv_dist=> n. rewrite /lft_inv_alive -Fix_F_eq. + apply lft_inv_alive_go_ne=> κ' Hκ. + apply (Fix_F_proper _ (λ _, dist n)); auto using lft_inv_alive_go_ne. +Qed. +Lemma lft_vs_inv_unfold κ (I : gmap lft lft_names) : + lft_vs_inv κ I ⊣⊢ lft_bor_dead κ ∗ + own_ilft_auth I ∗ + [∗ set] κ' ∈ dom _ I, ⌜κ' ⊂ κ⌝ → lft_inv_alive κ'. +Proof. + rewrite /lft_vs_inv /lft_vs_inv_go. by setoid_rewrite pure_impl_forall. +Qed. +Lemma lft_vs_unfold κ P Q : + lft_vs κ P Q ⊣⊢ ∃ n : nat, + own_cnt κ (● n) ∗ + ∀ I : gmap lft lft_names, + lft_vs_inv κ I -∗ ▷ P -∗ lft_dead κ ={⊤∖↑mgmtN}=∗ + lft_vs_inv κ I ∗ ▷ Q ∗ own_cnt κ (◯ n). +Proof. done. Qed. + +Global Instance lft_bor_alive_ne κ n : Proper (dist n ==> dist n) (lft_bor_alive κ). +Proof. solve_proper. Qed. +Global Instance lft_bor_alive_proper κ : Proper ((≡) ==> (≡)) (lft_bor_alive κ). +Proof. apply (ne_proper _). Qed. + +Global Instance lft_inh_ne κ s n : Proper (dist n ==> dist n) (lft_inh κ s). +Proof. solve_proper. Qed. +Global Instance lft_inh_proper κ s : Proper ((≡) ==> (≡)) (lft_inh κ s). +Proof. apply (ne_proper _). Qed. + +Global Instance lft_vs_ne κ n : + Proper (dist n ==> dist n ==> dist n) (lft_vs κ). +Proof. intros P P' HP Q Q' HQ. by apply lft_vs_go_ne. Qed. +Global Instance lft_vs_proper κ : Proper ((≡) ==> (≡) ==> (≡)) (lft_vs κ). +Proof. apply (ne_proper_2 _). Qed. + +Global Instance idx_bor_ne κ i n : Proper (dist n ==> dist n) (idx_bor κ i). +Proof. solve_proper. Qed. +Global Instance idx_bor_proper κ i : Proper ((≡) ==> (≡)) (idx_bor κ i). +Proof. apply (ne_proper _). Qed. + +Global Instance raw_bor_ne i n : Proper (dist n ==> dist n) (raw_bor i). +Proof. solve_proper. Qed. +Global Instance raw_bor_proper i : Proper ((≡) ==> (≡)) (raw_bor i). +Proof. apply (ne_proper _). Qed. + +Global Instance bor_ne κ n : Proper (dist n ==> dist n) (bor κ). +Proof. solve_proper. Qed. +Global Instance bor_proper κ : Proper ((≡) ==> (≡)) (bor κ). +Proof. apply (ne_proper _). Qed. + +(*** PersistentP and TimelessP instances *) +Global Instance lft_tok_timeless q κ : TimelessP q.[κ]. +Proof. rewrite /lft_tok. apply _. Qed. +Global Instance lft_dead_persistent κ : PersistentP [†κ]. +Proof. rewrite /lft_dead. apply _. Qed. +Global Instance lft_dead_timeless κ : PersistentP [†κ]. +Proof. rewrite /lft_tok. apply _. Qed. + +Global Instance lft_incl_persistent κ κ' : PersistentP (κ ⊑ κ'). +Proof. rewrite /lft_incl. apply _. Qed. + +Global Instance idx_bor_persistent κ i P : PersistentP (&{κ,i} P). +Proof. rewrite /idx_bor. apply _. Qed. +Global Instance idx_borrow_own_timeless q i : TimelessP (idx_bor_own q i). +Proof. rewrite /idx_bor_own. apply _. Qed. + +Global Instance lft_ctx_persistent : PersistentP lft_ctx. +Proof. rewrite /lft_ctx. apply _. Qed. + +(** Alive and dead *) +Global Instance lft_alive_in_dec A κ : Decision (lft_alive_in A κ). +Proof. + refine (cast_if (decide (set_Forall (λ Λ, A !! Λ = Some true) + (dom (gset atomic_lft) κ)))); + rewrite /lft_alive_in; by setoid_rewrite <-gmultiset_elem_of_dom. +Qed. +Global Instance lft_dead_in_dec A κ : Decision (lft_dead_in A κ). +Proof. + refine (cast_if (decide (set_Exists (λ Λ, A !! Λ = Some false) + (dom (gset atomic_lft) κ)))); + rewrite /lft_dead_in; by setoid_rewrite <-gmultiset_elem_of_dom. +Qed. + +Lemma lft_alive_or_dead_in A κ : + (∃ Λ, Λ ∈ κ ∧ A !! Λ = None) ∨ (lft_alive_in A κ ∨ lft_dead_in A κ). +Proof. + rewrite /lft_alive_in /lft_dead_in. + destruct (decide (set_Exists (λ Λ, A !! Λ = None) (dom (gset _) κ))) + as [(Λ & ?%gmultiset_elem_of_dom & HAΛ)|HA%(not_set_Exists_Forall _)]; first eauto. + destruct (decide (set_Exists (λ Λ, A !! Λ = Some false) (dom (gset _) κ))) + as [(Λ & HΛ%gmultiset_elem_of_dom & ?)|HA'%(not_set_Exists_Forall _)]; first eauto. + right; left. intros Λ HΛ%gmultiset_elem_of_dom. + move: (HA _ HΛ) (HA' _ HΛ)=> /=. case: (A !! Λ)=>[[]|]; naive_solver. +Qed. +Lemma lft_alive_and_dead_in A κ : lft_alive_in A κ → lft_dead_in A κ → False. +Proof. intros Halive (Λ&HΛ&?). generalize (Halive _ HΛ). naive_solver. Qed. + +Lemma lft_alive_in_subseteq A κ κ' : + lft_alive_in A κ → κ' ⊆ κ → lft_alive_in A κ'. +Proof. intros Halive ? Λ ?. by eapply Halive, gmultiset_elem_of_subseteq. Qed. + +Lemma lft_alive_in_insert A κ Λ b : + A !! Λ = None → lft_alive_in A κ → lft_alive_in (<[Λ:=b]> A) κ. +Proof. + intros HΛ Halive Λ' HΛ'. + assert (Λ ≠ Λ') by (intros ->; move:(Halive _ HΛ'); by rewrite HΛ). + rewrite lookup_insert_ne; eauto. +Qed. +Lemma lft_alive_in_insert_false A κ Λ b : + Λ ∉ κ → lft_alive_in A κ → lft_alive_in (<[Λ:=b]> A) κ. +Proof. + intros HΛ Halive Λ' HΛ'. + rewrite lookup_insert_ne; last (by intros ->); auto. +Qed. + +Lemma lft_dead_in_insert A κ Λ b : + A !! Λ = None → lft_dead_in A κ → lft_dead_in (<[Λ:=b]> A) κ. +Proof. + intros HΛ (Λ'&?&HΛ'). + assert (Λ ≠ Λ') by (intros ->; move:HΛ'; by rewrite HΛ). + exists Λ'. by rewrite lookup_insert_ne. +Qed. +Lemma lft_dead_in_insert_false A κ Λ : + lft_dead_in A κ → lft_dead_in (<[Λ:=false]> A) κ. +Proof. + intros (Λ'&?&HΛ'). destruct (decide (Λ = Λ')) as [<-|]. + - exists Λ. by rewrite lookup_insert. + - exists Λ'. by rewrite lookup_insert_ne. +Qed. +Lemma lft_dead_in_insert_false' A κ Λ : Λ ∈ κ → lft_dead_in (<[Λ:=false]> A) κ. +Proof. exists Λ. by rewrite lookup_insert. Qed. + +(** Silly stuff *) +Lemma own_ilft_auth_agree (I : gmap lft lft_names) κ γs : + own_ilft_auth I ⊢ + own ilft_name (◯ {[κ := DecAgree γs]}) -∗ ⌜is_Some (I !! κ)⌝. +Proof. + iIntros "HI Hκ". iDestruct (own_valid_2 with "HI Hκ") + as %[[? [??]]%singleton_included _]%auth_valid_discrete_2. + simplify_map_eq; simplify_option_eq; eauto. +Qed. + +Lemma own_bor_auth I κ x : own_ilft_auth I ⊢ own_bor κ x -∗ ⌜is_Some (I !! κ)⌝. +Proof. + iIntros "HI"; iDestruct 1 as (γs) "[? _]". + by iApply (own_ilft_auth_agree with "HI"). +Qed. +Lemma own_bor_op κ x y : own_bor κ (x ⋅ y) ⊣⊢ own_bor κ x ∗ own_bor κ y. +Proof. + iSplit. + { iDestruct 1 as (γs) "[#? [Hx Hy]]"; iSplitL "Hx"; iExists γs; eauto. } + iIntros "[Hx Hy]". + iDestruct "Hx" as (γs) "[Hγs Hx]"; iDestruct "Hy" as (γs') "[Hγs' Hy]". + iDestruct (own_valid_2 with "Hγs Hγs'") as %Hγs%auth_own_valid. + move: Hγs; rewrite /= op_singleton singleton_valid=> /dec_agree_op_inv [<-]. + iExists γs. iSplit. done. rewrite own_op; iFrame. +Qed. +Lemma own_bor_valid κ x : own_bor κ x ⊢ ✓ x. +Proof. iDestruct 1 as (γs) "[#? Hx]". by iApply own_valid. Qed. +Lemma own_bor_valid_2 κ x y : own_bor κ x ⊢ own_bor κ y -∗ ✓ (x ⋅ y). +Proof. apply wand_intro_r. rewrite -own_bor_op. apply own_bor_valid. Qed. +Lemma own_bor_update κ x y : x ~~> y → own_bor κ x ==∗ own_bor κ y. +Proof. + iDestruct 1 as (γs) "[#Hκ Hx]"; iExists γs. iFrame "Hκ". by iApply own_update. +Qed. + +Lemma own_cnt_auth I κ x : own_ilft_auth I ⊢ own_cnt κ x -∗ ⌜is_Some (I !! κ)⌝. +Proof. + iIntros "HI"; iDestruct 1 as (γs) "[? _]". + by iApply (own_ilft_auth_agree with "HI"). +Qed. +Lemma own_cnt_op κ x y : own_cnt κ (x ⋅ y) ⊣⊢ own_cnt κ x ∗ own_cnt κ y. +Proof. + iSplit. + { iDestruct 1 as (γs) "[#? [Hx Hy]]"; iSplitL "Hx"; iExists γs; eauto. } + iIntros "[Hx Hy]". + iDestruct "Hx" as (γs) "[Hγs Hx]"; iDestruct "Hy" as (γs') "[Hγs' Hy]". + iDestruct (own_valid_2 with "Hγs Hγs'") as %Hγs%auth_own_valid. + move: Hγs; rewrite /= op_singleton singleton_valid=> /dec_agree_op_inv [<-]. + iExists γs. iSplit; first done. rewrite own_op; iFrame. +Qed. +Lemma own_cnt_valid κ x : own_cnt κ x ⊢ ✓ x. +Proof. iDestruct 1 as (γs) "[#? Hx]". by iApply own_valid. Qed. +Lemma own_cnt_valid_2 κ x y : own_cnt κ x ⊢ own_cnt κ y -∗ ✓ (x ⋅ y). +Proof. apply wand_intro_r. rewrite -own_cnt_op. apply own_cnt_valid. Qed. +Lemma own_cnt_update κ x y : x ~~> y → own_cnt κ x ==∗ own_cnt κ y. +Proof. + iDestruct 1 as (γs) "[#Hκ Hx]"; iExists γs. iFrame "Hκ". by iApply own_update. +Qed. +Lemma own_cnt_update_2 κ x1 x2 y : + x1 ⋅ x2 ~~> y → own_cnt κ x1 ⊢ own_cnt κ x2 ==∗ own_cnt κ y. +Proof. + intros. apply wand_intro_r. rewrite -own_cnt_op. by apply own_cnt_update. +Qed. + +Lemma own_inh_auth I κ x : own_ilft_auth I ⊢ own_inh κ x -∗ ⌜is_Some (I !! κ)⌝. +Proof. + iIntros "HI"; iDestruct 1 as (γs) "[? _]". + by iApply (own_ilft_auth_agree with "HI"). +Qed. +Lemma own_inh_op κ x y : own_inh κ (x ⋅ y) ⊣⊢ own_inh κ x ∗ own_inh κ y. +Proof. + iSplit. + { iDestruct 1 as (γs) "[#? [Hx Hy]]"; iSplitL "Hx"; iExists γs; eauto. } + iIntros "[Hx Hy]". + iDestruct "Hx" as (γs) "[Hγs Hx]"; iDestruct "Hy" as (γs') "[Hγs' Hy]". + iDestruct (own_valid_2 with "Hγs Hγs'") as %Hγs%auth_own_valid. + move: Hγs; rewrite /= op_singleton singleton_valid=> /dec_agree_op_inv [<-]. + iExists γs. iSplit. done. rewrite own_op; iFrame. +Qed. +Lemma own_inh_valid κ x : own_inh κ x ⊢ ✓ x. +Proof. iDestruct 1 as (γs) "[#? Hx]". by iApply own_valid. Qed. +Lemma own_inh_valid_2 κ x y : own_inh κ x ⊢ own_inh κ y -∗ ✓ (x ⋅ y). +Proof. apply wand_intro_r. rewrite -own_inh_op. apply own_inh_valid. Qed. +Lemma own_inh_update κ x y : x ~~> y → own_inh κ x ==∗ own_inh κ y. +Proof. + iDestruct 1 as (γs) "[#Hκ Hx]"; iExists γs. iFrame "Hκ". by iApply own_update. +Qed. + +Lemma lft_inv_alive_twice κ : lft_inv_alive κ ⊢ lft_inv_alive κ -∗ False. +Proof. + rewrite lft_inv_alive_unfold /lft_inh. + iDestruct 1 as (P Q) "(_&_&Hinh)"; iDestruct 1 as (P' Q') "(_&_&Hinh')". + iDestruct "Hinh" as (E) "[HE _]"; iDestruct "Hinh'" as (E') "[HE' _]". + by iDestruct (own_inh_valid_2 with "HE HE'") as %?. +Qed. + +(** Basic rules about lifetimes *) +Lemma lft_tok_op q κ1 κ2 : q.[κ1] ∗ q.[κ2] ⊣⊢ q.[κ1 ∪ κ2]. +Proof. by rewrite /lft_tok -big_sepMS_union. Qed. + +Lemma lft_dead_or κ1 κ2 : [†κ1] ∨ [†κ2] ⊣⊢ [† κ1 ∪ κ2]. +Proof. + rewrite /lft_dead -or_exist. apply exist_proper=> Λ. + rewrite -sep_or_r -pure_or. do 2 f_equiv. set_solver. +Qed. + +Lemma lft_tok_frac_op κ q q' : (q + q').[κ] ⊣⊢ q.[κ] ∗ q'.[κ]. +Proof. + rewrite /lft_tok -big_sepMS_sepMS. apply big_sepMS_proper=> Λ _. + by rewrite -own_op -auth_frag_op op_singleton. +Qed. + +Lemma lft_tok_split κ q : q.[κ] ⊣⊢ (q/2).[κ] ∗ (q/2).[κ]. +Proof. by rewrite -lft_tok_frac_op Qp_div_2. Qed. + +Lemma lft_tok_dead_own q κ : q.[κ] ⊢ [† κ] -∗ False. +Proof. + rewrite /lft_tok /lft_dead. iIntros "H"; iDestruct 1 as (Λ') "[% H']". + iDestruct (big_sepMS_elem_of _ _ Λ' with "H") as "H"=> //. + iDestruct (own_valid_2 with "H H'") as %Hvalid. + move: Hvalid=> /auth_own_valid /=; by rewrite op_singleton singleton_valid. +Qed. + +Lemma lft_tok_static q : True ⊢ q.[static]. +Proof. by rewrite /lft_tok big_sepMS_empty. Qed. + +Lemma lft_dead_static : [† static] ⊢ False. +Proof. rewrite /lft_dead. iDestruct 1 as (Λ) "[% H']". set_solver. Qed. +End primitive. diff --git a/theories/lifetime/todo.v b/theories/lifetime/todo.v new file mode 100644 index 00000000..6d19e3e6 --- /dev/null +++ b/theories/lifetime/todo.v @@ -0,0 +1,63 @@ +From lrust.lifetime Require Export definitions. + +Section todo. +Context `{invG Σ, lftG Σ}. +Implicit Types κ : lft. + +(** Basic borrows *) +Lemma bor_create E κ P : + ↑lftN ⊆ E → + lft_ctx ⊢ ▷ P ={E}=∗ &{κ} P ∗ ([†κ] ={E}=∗ ▷ P). +Proof. Admitted. +Lemma bor_fake E κ P : + ↑lftN ⊆ E → + lft_ctx ⊢ [†κ] ={E}=∗ &{κ}P. +Proof. +Admitted. +Lemma bor_sep E κ P Q : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ} (P ∗ Q) ={E}=∗ &{κ} P ∗ &{κ} Q. +Proof. +Admitted. +Lemma bor_combine E κ P Q : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ} P -∗ &{κ} Q ={E}=∗ &{κ} (P ∗ Q). +Proof. Admitted. +Lemma bor_acc_strong E q κ P : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ} P -∗ q.[κ] ={E}=∗ ▷ P ∗ + ∀ Q, ▷ Q ∗ ▷([†κ] -∗ ▷ Q ={⊤∖↑lftN}=∗ ▷ P) ={E}=∗ &{κ} Q ∗ q.[κ]. +Proof. Admitted. +Lemma bor_acc_atomic_strong E κ P : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ} P ={E,E∖↑lftN}=∗ + (▷ P ∗ ∀ Q, ▷ Q ∗ ▷ ([†κ] -∗ ▷ Q ={⊤∖↑lftN}=∗ ▷ P) ={E∖↑lftN,E}=∗ &{κ} Q) ∨ + [†κ] ∗ |={E∖↑lftN,E}=> True. +Proof. Admitted. +Lemma bor_reborrow' E κ κ' P : + ↑lftN ⊆ E → κ ⊆ κ' → + lft_ctx ⊢ &{κ} P ={E}=∗ &{κ'} P ∗ ([†κ'] ={E}=∗ &{κ} P). +Proof. Admitted. +Lemma bor_unnest E κ κ' P : + ↑lftN ⊆ E → + lft_ctx ⊢ &{κ'} &{κ} P ={E}▷=∗ &{κ ∪ κ'} P. +Proof. Admitted. + +(** Indexed borrow *) +Lemma idx_bor_acc E q κ i P : + ↑lftN ⊆ E → + lft_ctx ⊢ idx_bor κ i P -∗ idx_bor_own 1 i -∗ q.[κ] ={E}=∗ + ▷ P ∗ (▷ P ={E}=∗ idx_bor_own 1 i ∗ q.[κ]). +Proof. Admitted. + +Lemma idx_bor_atomic_acc E q κ i P : + ↑lftN ⊆ E → + lft_ctx ⊢ idx_bor κ i P -∗ idx_bor_own q i ={E,E∖↑lftN}=∗ + ▷ P ∗ (▷ P ={E∖↑lftN,E}=∗ idx_bor_own q i) ∨ + [†κ] ∗ (|={E∖↑lftN,E}=> idx_bor_own q i). +Proof. Admitted. + +Lemma idx_bor_shorten κ κ' i P : + κ ⊑ κ' ⊢ idx_bor κ' i P -∗ idx_bor κ i P. +Proof. Admitted. +End todo. \ No newline at end of file -- GitLab