From eb82a9c7af8d7bf5c11d2bfbfcb74672f0456847 Mon Sep 17 00:00:00 2001 From: Ralf Jung <jung@mpi-sws.org> Date: Mon, 8 Feb 2016 19:06:20 +0100 Subject: [PATCH] prove frame-preservnig updates for global CMRA --- algebra/fin_maps.v | 13 +++++ program_logic/global_cmra.v | 99 +++++++++++++++++++++++++++---------- program_logic/pviewshifts.v | 8 +-- program_logic/viewshifts.v | 30 +++++++++-- 4 files changed, 114 insertions(+), 36 deletions(-) diff --git a/algebra/fin_maps.v b/algebra/fin_maps.v index db841b9f1..2a5afdf23 100644 --- a/algebra/fin_maps.v +++ b/algebra/fin_maps.v @@ -223,6 +223,19 @@ Proof. rewrite !cmra_update_updateP; eauto using map_insert_updateP with congruence. Qed. +Lemma map_singleton_updateP (P : A → Prop) (Q : gmap K A → Prop) i x : + x ~~>: P → (∀ y, P y → Q {[ i ↦ y ]}) → {[ i ↦ x ]} ~~>: Q. +Proof. apply map_insert_updateP. Qed. +Lemma map_singleton_updateP' (P : A → Prop) i x : + x ~~>: P → {[ i ↦ x ]} ~~>: λ m', ∃ y, m' = {[ i ↦ y ]} ∧ P y. +Proof. eauto using map_singleton_updateP. Qed. +Lemma map_singleton_update i (x y : A) : x ~~> y → {[ i ↦ x ]} ~~> {[ i ↦ y ]}. +Proof. + rewrite !cmra_update_updateP=>?. eapply map_singleton_updateP; first eassumption. + by move=>? ->. +Qed. + + Context `{Fresh K (gset K), !FreshSpec K (gset K)}. Lemma map_updateP_alloc (Q : gmap K A → Prop) m x : ✓ x → (∀ i, m !! i = None → Q (<[i:=x]>m)) → m ~~>: Q. diff --git a/program_logic/global_cmra.v b/program_logic/global_cmra.v index 0c42e3a03..326110b65 100644 --- a/program_logic/global_cmra.v +++ b/program_logic/global_cmra.v @@ -8,23 +8,33 @@ Definition globalC (Σ : gid → iFunctor) : iFunctor := Class InG Λ (Σ : gid → iFunctor) (i : gid) (A : cmraT) := inG : A = Σ i (laterC (iPreProp Λ (globalC Σ))). -Definition to_Σ {Λ} {Σ : gid → iFunctor} (i : gid) - `{!InG Λ Σ i A} (a : A) : Σ i (laterC (iPreProp Λ (globalC Σ))) := - eq_rect A id a _ inG. -Definition to_globalC {Λ} {Σ : gid → iFunctor} - (i : gid) (γ : gid) `{!InG Λ Σ i A} (a : A) : iGst Λ (globalC Σ) := - iprod_singleton i {[ γ ↦ to_Σ _ a ]}. -Definition own {Λ} {Σ : gid → iFunctor} - (i : gid) `{!InG Λ Σ i A} (γ : gid) (a : A) : iProp Λ (globalC Σ) := - ownG (to_globalC i γ a). Section global. Context {Λ : language} {Σ : gid → iFunctor} (i : gid) `{!InG Λ Σ i A}. Implicit Types a : A. -(* Proeprties of to_globalC *) +Definition to_Σ (a : A) : Σ i (laterC (iPreProp Λ (globalC Σ))) := + eq_rect A id a _ inG. +Definition to_globalC (γ : gid) `{!InG Λ Σ i A} (a : A) : iGst Λ (globalC Σ) := + iprod_singleton i {[ γ ↦ to_Σ a ]}. +Definition own (γ : gid) (a : A) : iProp Λ (globalC Σ) := + ownG (to_globalC γ a). + +Definition from_Σ (b : Σ i (laterC (iPreProp Λ (globalC Σ)))) : A := + eq_rect (Σ i _) id b _ (Logic.eq_sym inG). +Definition P_to_Σ (P : A → Prop) (b : Σ i (laterC (iPreProp Λ (globalC Σ)))) : Prop + := P (from_Σ b). + +(* Properties of the transport. *) +Lemma to_from_Σ b : + to_Σ (from_Σ b) = b. +Proof. + rewrite /to_Σ /from_Σ. by destruct inG. +Qed. + +(* Properties of to_globalC *) Lemma globalC_op γ a1 a2 : - to_globalC i γ (a1 ⋅ a2) ≡ to_globalC i γ a1 ⋅ to_globalC i γ a2. + to_globalC γ (a1 ⋅ a2) ≡ to_globalC γ a1 ⋅ to_globalC γ a2. Proof. rewrite /to_globalC iprod_op_singleton map_op_singleton. apply iprod_singleton_proper, (fin_maps.singleton_proper (M:=gmap _)). @@ -32,7 +42,7 @@ Proof. Qed. Lemma globalC_validN n γ a : - ✓{n} (to_globalC i γ a) <-> ✓{n} a. + ✓{n} (to_globalC γ a) <-> ✓{n} a. Proof. rewrite /to_globalC. rewrite -iprod_validN_singleton -map_validN_singleton. @@ -40,7 +50,7 @@ Proof. Qed. Lemma globalC_unit γ a : - unit (to_globalC i γ a) ≡ to_globalC i γ (unit a). + unit (to_globalC γ a) ≡ to_globalC γ (unit a). Proof. rewrite /to_globalC. rewrite iprod_unit_singleton map_unit_singleton. @@ -48,57 +58,92 @@ Proof. by rewrite /to_Σ; destruct inG. Qed. -Global Instance globalC_timeless γ m : Timeless m → Timeless (to_globalC i γ m). +Global Instance globalC_timeless γ m : Timeless m → Timeless (to_globalC γ m). Proof. rewrite /to_globalC => ?. apply iprod_singleton_timeless, map_singleton_timeless. by rewrite /to_Σ; destruct inG. Qed. +(* Properties of the lifted frame-preserving updates *) +Lemma update_to_Σ a P : + a ~~>: P → to_Σ a ~~>: P_to_Σ P. +Proof. + move=>Hu gf n Hf. destruct (Hu (from_Σ gf) n) as [a' Ha']. + { move: Hf. rewrite /to_Σ /from_Σ. by destruct inG. } + exists (to_Σ a'). move:Hf Ha'. + rewrite /P_to_Σ /to_Σ /from_Σ. destruct inG. done. +Qed. + (* Properties of own *) -Global Instance own_ne γ n : Proper (dist n ==> dist n) (own i γ). +Global Instance own_ne γ n : Proper (dist n ==> dist n) (own γ). Proof. intros m m' Hm; apply ownG_ne, iprod_singleton_ne, singleton_ne. by rewrite /to_globalC /to_Σ; destruct inG. Qed. -Global Instance own_proper γ : Proper ((≡) ==> (≡)) (own i γ) := ne_proper _. +Global Instance own_proper γ : Proper ((≡) ==> (≡)) (own γ) := ne_proper _. -Lemma own_op γ a1 a2 : own i γ (a1 ⋅ a2) ≡ (own i γ a1 ★ own i γ a2)%I. +Lemma own_op γ a1 a2 : own γ (a1 ⋅ a2) ≡ (own γ a1 ★ own γ a2)%I. Proof. rewrite /own -ownG_op. apply ownG_proper, globalC_op. Qed. (* TODO: This also holds if we just have ✓a at the current step-idx, as Iris assertion. However, the map_updateP_alloc does not suffice to show this. *) Lemma own_alloc E a : - ✓a → True ⊑ pvs E E (∃ γ, own i γ a). + ✓a → True ⊑ pvs E E (∃ γ, own γ a). Proof. - intros Hm. set (P m := ∃ γ, m = to_globalC i γ a). + intros Ha. set (P m := ∃ γ, m = to_globalC γ a). rewrite -(pvs_mono _ _ (∃ m, ■P m ∧ ownG m)%I). - - rewrite -pvs_updateP_empty //; []. + - rewrite -pvs_ownG_updateP_empty //; []. subst P. eapply (iprod_singleton_updateP_empty i). - + eapply map_updateP_alloc' with (x:=to_Σ i a). + + apply map_updateP_alloc' with (x:=to_Σ a). by rewrite /to_Σ; destruct inG. + simpl. move=>? [γ [-> ?]]. exists γ. done. - - apply exist_elim=>m. apply const_elim_l. - move=>[p ->] {P}. by rewrite -(exist_intro p). + - apply exist_elim=>m. apply const_elim_l=>-[p ->] {P}. + by rewrite -(exist_intro p). Qed. -Lemma always_own_unit γ m : (□ own i γ (unit m))%I ≡ own i γ (unit m). +Lemma always_own_unit γ a : (□ own γ (unit a))%I ≡ own γ (unit a). Proof. rewrite /own -globalC_unit. by apply always_ownG_unit. Qed. -Lemma own_valid γ m : (own i γ m) ⊑ (✓ m). +Lemma own_valid γ a : (own γ a) ⊑ (✓ a). Proof. rewrite /own ownG_valid. apply uPred.valid_mono=>n. by apply globalC_validN. Qed. -Lemma own_valid_r' γ m : (own i γ m) ⊑ (own i γ m ★ ✓ m). +Lemma own_valid_r' γ a : (own γ a) ⊑ (own γ a ★ ✓ a). Proof. apply (uPred.always_entails_r' _ _), own_valid. Qed. -Global Instance ownG_timeless γ m : Timeless m → TimelessP (own i γ m). +Global Instance ownG_timeless γ a : Timeless a → TimelessP (own γ a). Proof. intros. apply ownG_timeless. apply _. Qed. +Lemma pvs_updateP E γ a P : + a ~~>: P → own γ a ⊑ pvs E E (∃ a', ■P a' ∧ own γ a'). +Proof. + intros Ha. set (P' m := ∃ a', P a' ∧ m = to_globalC γ a'). + rewrite -(pvs_mono _ _ (∃ m, ■P' m ∧ ownG m)%I). + - rewrite -pvs_ownG_updateP; first by rewrite /own. + rewrite /to_globalC. eapply iprod_singleton_updateP. + + (* FIXME RJ: I tried apply... with instead of instantiate, that + does not work. *) + apply map_singleton_updateP'. instantiate (1:=P_to_Σ P). + by apply update_to_Σ. + + simpl. move=>? [y [-> HP]]. exists (from_Σ y). split. + * move: HP. rewrite /P_to_Σ /from_Σ. by destruct inG. + * clear HP. rewrite /to_globalC to_from_Σ; done. + - apply exist_elim=>m. apply const_elim_l=>-[a' [HP ->]]. + rewrite -(exist_intro a'). apply and_intro; last done. + by apply const_intro. +Qed. + +Lemma pvs_update E γ a a' : a ~~> a' → own γ a ⊑ pvs E E (own γ a'). +Proof. + intros; rewrite (pvs_updateP E _ _ (a' =)); last by apply cmra_update_updateP. + by apply pvs_mono, uPred.exist_elim=> m''; apply uPred.const_elim_l=> ->. +Qed. + End global. diff --git a/program_logic/pviewshifts.v b/program_logic/pviewshifts.v index b9728d643..73235c04e 100644 --- a/program_logic/pviewshifts.v +++ b/program_logic/pviewshifts.v @@ -97,7 +97,7 @@ Proof. * by rewrite -(left_id_L ∅ (∪) Ef). * apply uPred_weaken with r n; auto. Qed. -Lemma pvs_updateP E m (P : iGst Λ Σ → Prop) : +Lemma pvs_ownG_updateP E m (P : iGst Λ Σ → Prop) : m ~~>: P → ownG m ⊑ pvs E E (∃ m', ■P m' ∧ ownG m'). Proof. intros Hup%option_updateP' r [|n] ? Hinv%ownG_spec rf [|k] Ef σ ???; try lia. @@ -105,7 +105,7 @@ Proof. { apply cmra_includedN_le with (S n); auto. } by exists (update_gst m' r); split; [exists m'; split; [|apply ownG_spec]|]. Qed. -Lemma pvs_updateP_empty `{Empty (iGst Λ Σ), !CMRAIdentity (iGst Λ Σ)} +Lemma pvs_ownG_updateP_empty `{Empty (iGst Λ Σ), !CMRAIdentity (iGst Λ Σ)} E (P : iGst Λ Σ → Prop) : ∅ ~~>: P → True ⊑ pvs E E (∃ m', ■P m' ∧ ownG m'). Proof. @@ -148,9 +148,9 @@ Lemma pvs_mask_weaken E1 E2 P : E1 ⊆ E2 → pvs E1 E1 P ⊑ pvs E2 E2 P. Proof. intros; rewrite (union_difference_L E1 E2) //; apply pvs_mask_frame; auto. Qed. -Lemma pvs_update E m m' : m ~~> m' → ownG m ⊑ pvs E E (ownG m'). +Lemma pvs_ownG_update E m m' : m ~~> m' → ownG m ⊑ pvs E E (ownG m'). Proof. - intros; rewrite (pvs_updateP E _ (m' =)); last by apply cmra_update_updateP. + intros; rewrite (pvs_ownG_updateP E _ (m' =)); last by apply cmra_update_updateP. by apply pvs_mono, uPred.exist_elim=> m''; apply uPred.const_elim_l=> ->. Qed. End pvs. diff --git a/program_logic/viewshifts.v b/program_logic/viewshifts.v index 812844f87..0db7e6673 100644 --- a/program_logic/viewshifts.v +++ b/program_logic/viewshifts.v @@ -1,6 +1,8 @@ Require Export program_logic.pviewshifts. Require Import program_logic.ownership. +(* TODO: State lemmas in terms of inv and own. *) + Definition vs {Λ Σ} (E1 E2 : coPset) (P Q : iProp Λ Σ) : iProp Λ Σ := (□ (P → pvs E1 E2 Q))%I. Arguments vs {_ _} _ _ _%I _%I. @@ -25,14 +27,18 @@ Proof. intros; rewrite -{1}always_const; apply always_intro, impl_intro_l. by rewrite always_const (right_id _ _). Qed. + Global Instance vs_ne E1 E2 n : Proper (dist n ==> dist n ==> dist n) (@vs Λ Σ E1 E2). Proof. by intros P P' HP Q Q' HQ; rewrite /vs HP HQ. Qed. + Global Instance vs_proper E1 E2 : Proper ((≡) ==> (≡) ==> (≡)) (@vs Λ Σ E1 E2). Proof. apply ne_proper_2, _. Qed. + Lemma vs_mono E1 E2 P P' Q Q' : P ⊑ P' → Q' ⊑ Q → P' >{E1,E2}> Q' ⊑ P >{E1,E2}> Q. Proof. by intros HP HQ; rewrite /vs -HP HQ. Qed. + Global Instance vs_mono' E1 E2 : Proper (flip (⊑) ==> (⊑) ==> (⊑)) (@vs Λ Σ E1 E2). Proof. by intros until 2; apply vs_mono. Qed. @@ -41,6 +47,7 @@ Lemma vs_false_elim E1 E2 P : False >{E1,E2}> P. Proof. apply vs_alt, False_elim. Qed. Lemma vs_timeless E P : TimelessP P → ▷ P >{E}> P. Proof. by intros ?; apply vs_alt, pvs_timeless. Qed. + Lemma vs_transitive E1 E2 E3 P Q R : E2 ⊆ E1 ∪ E3 → (P >{E1,E2}> Q ∧ Q >{E2,E3}> R) ⊑ P >{E1,E3}> R. Proof. @@ -48,54 +55,67 @@ Proof. rewrite always_and (associative _) (always_elim (P → _)) impl_elim_r. by rewrite pvs_impl_r; apply pvs_trans. Qed. + Lemma vs_transitive' E P Q R : (P >{E}> Q ∧ Q >{E}> R) ⊑ P >{E}> R. Proof. apply vs_transitive; solve_elem_of. Qed. Lemma vs_reflexive E P : P >{E}> P. Proof. apply vs_alt, pvs_intro. Qed. + Lemma vs_impl E P Q : □ (P → Q) ⊑ P >{E}> Q. Proof. apply always_intro, impl_intro_l. by rewrite always_elim impl_elim_r -pvs_intro. Qed. + Lemma vs_frame_l E1 E2 P Q R : P >{E1,E2}> Q ⊑ (R ★ P) >{E1,E2}> (R ★ Q). Proof. apply always_intro, impl_intro_l. rewrite -pvs_frame_l always_and_sep_r -always_wand_impl -(associative _). by rewrite always_elim wand_elim_r. Qed. + Lemma vs_frame_r E1 E2 P Q R : P >{E1,E2}> Q ⊑ (P ★ R) >{E1,E2}> (Q ★ R). Proof. rewrite !(commutative _ _ R); apply vs_frame_l. Qed. + Lemma vs_mask_frame E1 E2 Ef P Q : Ef ∩ (E1 ∪ E2) = ∅ → P >{E1,E2}> Q ⊑ P >{E1 ∪ Ef,E2 ∪ Ef}> Q. Proof. intros ?; apply always_intro, impl_intro_l; rewrite (pvs_mask_frame _ _ Ef)//. by rewrite always_elim impl_elim_r. Qed. + Lemma vs_mask_frame' E Ef P Q : Ef ∩ E = ∅ → P >{E}> Q ⊑ P >{E ∪ Ef}> Q. Proof. intros; apply vs_mask_frame; solve_elem_of. Qed. Lemma vs_open i P : ownI i P >{{[i]},∅}> ▷ P. Proof. intros; apply vs_alt, pvs_open. Qed. + Lemma vs_open' E i P : i ∉ E → ownI i P >{{[i]} ∪ E,E}> ▷ P. Proof. intros; rewrite -{2}(left_id_L ∅ (∪) E) -vs_mask_frame; last solve_elem_of. apply vs_open. Qed. + Lemma vs_close i P : (ownI i P ∧ ▷ P) >{∅,{[i]}}> True. Proof. intros; apply vs_alt, pvs_close. Qed. + Lemma vs_close' E i P : i ∉ E → (ownI i P ∧ ▷ P) >{E,{[i]} ∪ E}> True. Proof. intros; rewrite -{1}(left_id_L ∅ (∪) E) -vs_mask_frame; last solve_elem_of. apply vs_close. Qed. -Lemma vs_updateP E m (P : iGst Λ Σ → Prop) : + +Lemma vs_ownG_updateP E m (P : iGst Λ Σ → Prop) : m ~~>: P → ownG m >{E}> (∃ m', ■P m' ∧ ownG m'). -Proof. by intros; apply vs_alt, pvs_updateP. Qed. -Lemma vs_updateP_empty `{Empty (iGst Λ Σ), !CMRAIdentity (iGst Λ Σ)} +Proof. by intros; apply vs_alt, pvs_ownG_updateP. Qed. + +Lemma vs_ownG_updateP_empty `{Empty (iGst Λ Σ), !CMRAIdentity (iGst Λ Σ)} E (P : iGst Λ Σ → Prop) : ∅ ~~>: P → True >{E}> (∃ m', ■P m' ∧ ownG m'). -Proof. by intros; apply vs_alt, pvs_updateP_empty. Qed. +Proof. by intros; apply vs_alt, pvs_ownG_updateP_empty. Qed. + Lemma vs_update E m m' : m ~~> m' → ownG m >{E}> ownG m'. -Proof. by intros; apply vs_alt, pvs_update. Qed. +Proof. by intros; apply vs_alt, pvs_ownG_update. Qed. Lemma vs_alloc E P : ¬set_finite E → ▷ P >{E}> (∃ i, ■(i ∈ E) ∧ ownI i P). Proof. by intros; apply vs_alt, pvs_alloc. Qed. + End vs. -- GitLab