Commit ebeb86dd authored by Robbert Krebbers's avatar Robbert Krebbers

Merge branch 'robbert/local_updates'

parents 24d759e5 3b076d87
...@@ -78,7 +78,6 @@ program_logic/ectxi_language.v ...@@ -78,7 +78,6 @@ program_logic/ectxi_language.v
program_logic/ectx_lifting.v program_logic/ectx_lifting.v
program_logic/ghost_ownership.v program_logic/ghost_ownership.v
program_logic/saved_prop.v program_logic/saved_prop.v
program_logic/auth.v
program_logic/sts.v program_logic/sts.v
program_logic/namespaces.v program_logic/namespaces.v
program_logic/boxes.v program_logic/boxes.v
......
...@@ -200,26 +200,20 @@ Proof. by rewrite /op /auth_op /= left_id. Qed. ...@@ -200,26 +200,20 @@ Proof. by rewrite /op /auth_op /= left_id. Qed.
Lemma auth_auth_valid a : a ( a). Lemma auth_auth_valid a : a ( a).
Proof. intros; split; simpl; auto using ucmra_unit_leastN. Qed. Proof. intros; split; simpl; auto using ucmra_unit_leastN. Qed.
Lemma auth_update a af b : Lemma auth_update a b a' b' :
a ~l~> b @ Some af (a af) a ~~> (b af) b. (a,b) ~l~> (a',b') a b ~~> a' b'.
Proof. Proof.
intros [Hab Hab']; apply cmra_total_update. intros Hup; apply cmra_total_update.
move=> n [[[?|]|] bf1] // =>-[[bf2 Ha] ?]; do 2 red; simpl in *. move=> n [[[?|]|] bf1] // [[bf2 Ha] ?]; do 2 red; simpl in *.
move: Ha; rewrite !left_id=> Hm; split; auto. move: Ha; rewrite !left_id -assoc=> Ha.
exists bf2. rewrite -assoc. destruct (Hup n (Some (bf1 bf2))); auto.
apply (Hab' _ (Some _)); auto. by rewrite /= assoc. split; last done. exists bf2. by rewrite -assoc.
Qed. Qed.
Lemma auth_update_no_frame a b : a ~l~> b @ Some a a ~~> b b. Lemma auth_update_alloc a a' b' : (a,) ~l~> (a',b') a ~~> a' b'.
Proof. Proof. intros. rewrite -(right_id _ _ ( a)). by apply auth_update. Qed.
intros. rewrite -{1}(right_id _ _ a) -{1}(right_id _ _ b). Lemma auth_update_dealloc a b a' : (a,b) ~l~> (a',) a b ~~> a'.
by apply auth_update. Proof. intros. rewrite -(right_id _ _ ( a')). by apply auth_update. Qed.
Qed.
Lemma auth_update_no_frag af b : ~l~> b @ Some af af ~~> (b af) b.
Proof.
intros. rewrite -{1}(left_id _ _ af) -{1}(right_id _ _ ( _)).
by apply auth_update.
Qed.
End cmra. End cmra.
Arguments authR : clear implicits. Arguments authR : clear implicits.
......
...@@ -48,11 +48,11 @@ Section coPset. ...@@ -48,11 +48,11 @@ Section coPset.
Lemma coPset_update X Y : X ~~> Y. Lemma coPset_update X Y : X ~~> Y.
Proof. done. Qed. Proof. done. Qed.
Lemma coPset_local_update X Y mXf : X Y X ~l~> Y @ mXf. Lemma coPset_local_update X Y X' : X X' (X,Y) ~l~> (X',X').
Proof. Proof.
intros (Z&->&?)%subseteq_disjoint_union_L. intros (Z&->&?)%subseteq_disjoint_union_L.
intros; apply local_update_total; split; [done|]; simpl. rewrite local_update_unital_discrete=> Z' _ /leibniz_equiv_iff->.
intros mZ _. rewrite !coPset_opM=> HX. by rewrite (comm_L _ X) -!assoc_L HX. split. done. rewrite coPset_op_union. set_solver.
Qed. Qed.
End coPset. End coPset.
......
...@@ -300,31 +300,22 @@ Proof. eauto using csum_updateP_l. Qed. ...@@ -300,31 +300,22 @@ Proof. eauto using csum_updateP_l. Qed.
Lemma csum_updateP'_r (P : B Prop) b : Lemma csum_updateP'_r (P : B Prop) b :
b ~~>: P Cinr b ~~>: λ m', b', m' = Cinr b' P b'. b ~~>: P Cinr b ~~>: λ m', b', m' = Cinr b' P b'.
Proof. eauto using csum_updateP_r. Qed. Proof. eauto using csum_updateP_r. Qed.
Lemma csum_local_update_l (a1 a2 : A) af :
( af', af = Cinl <$> af' a1 ~l~> a2 @ af') Cinl a1 ~l~> Cinl a2 @ af. Lemma csum_local_update_l (a1 a2 a1' a2' : A) :
(a1,a2) ~l~> (a1',a2') (Cinl a1,Cinl a2) ~l~> (Cinl a1',Cinl a2').
Proof. Proof.
intros Ha. split; destruct af as [[af'| |]|]=>//=. intros Hup n mf ? Ha1; simpl in *.
- by eapply (Ha (Some af')). destruct (Hup n (mf = maybe Cinl)); auto.
- by eapply (Ha None). { by destruct mf as [[]|]; inversion_clear Ha1. }
- destruct (Ha (Some af') (reflexivity _)) as [_ Ha']. split. done. by destruct mf as [[]|]; inversion_clear Ha1; constructor.
intros n [[mz|mz|]|] ?; inversion 1; subst; constructor.
by apply (Ha' n (Some mz)). by apply (Ha' n None).
- destruct (Ha None (reflexivity _)) as [_ Ha'].
intros n [[mz|mz|]|] ?; inversion 1; subst; constructor.
by apply (Ha' n (Some mz)). by apply (Ha' n None).
Qed. Qed.
Lemma csum_local_update_r (b1 b2 : B) bf : Lemma csum_local_update_r (b1 b2 b1' b2' : B) :
( bf', bf = Cinr <$> bf' b1 ~l~> b2 @ bf') Cinr b1 ~l~> Cinr b2 @ bf. (b1,b2) ~l~> (b1',b2') (Cinr b1,Cinr b2) ~l~> (Cinr b1',Cinr b2').
Proof. Proof.
intros Hb. split; destruct bf as [[|bf'|]|]=>//=. intros Hup n mf ? Ha1; simpl in *.
- by eapply (Hb (Some bf')). destruct (Hup n (mf = maybe Cinr)); auto.
- by eapply (Hb None). { by destruct mf as [[]|]; inversion_clear Ha1. }
- destruct (Hb (Some bf') (reflexivity _)) as [_ Hb']. split. done. by destruct mf as [[]|]; inversion_clear Ha1; constructor.
intros n [[mz|mz|]|] ?; inversion 1; subst; constructor.
by apply (Hb' n (Some mz)). by apply (Hb' n None).
- destruct (Hb None (reflexivity _)) as [_ Hb'].
intros n [[mz|mz|]|] ?; inversion 1; subst; constructor.
by apply (Hb' n (Some mz)). by apply (Hb' n None).
Qed. Qed.
End cmra. End cmra.
......
...@@ -378,50 +378,63 @@ Section freshness. ...@@ -378,50 +378,63 @@ Section freshness.
Qed. Qed.
End freshness. End freshness.
Lemma insert_local_update m i x y mf : Lemma alloc_local_update m1 m2 i x :
x ~l~> y @ mf = (!! i) <[i:=x]>m ~l~> <[i:=y]>m @ mf. m1 !! i = None x (m1,m2) ~l~> (<[i:=x]>m1, <[i:=x]>m2).
Proof. Proof.
intros [Hxy Hxy']; split. rewrite cmra_valid_validN=> Hi ?.
- intros n Hm j. move: (Hm j). destruct (decide (i = j)); subst. apply local_update_unital=> n mf Hmv Hm; simpl in *.
+ rewrite !lookup_opM !lookup_insert !Some_op_opM. apply Hxy. split; auto using insert_validN.
+ by rewrite !lookup_opM !lookup_insert_ne. intros j; destruct (decide (i = j)) as [->|].
- intros n mf' Hm Hm' j. move: (Hm j) (Hm' j). - move: (Hm j); rewrite Hi symmetry_iff dist_None lookup_op op_None=>-[_ Hj].
destruct (decide (i = j)); subst. by rewrite lookup_op !lookup_insert Hj.
+ rewrite !lookup_opM !lookup_insert !Some_op_opM !inj_iff. apply Hxy'. - rewrite Hm lookup_insert_ne // !lookup_op lookup_insert_ne //.
+ by rewrite !lookup_opM !lookup_insert_ne. Qed.
Qed.
Lemma alloc_singleton_local_update m i x :
Lemma singleton_local_update i x y mf : m !! i = None x (m,) ~l~> (<[i:=x]>m, {[ i:=x ]}).
x ~l~> y @ mf = (!! i) {[ i := x ]} ~l~> {[ i := y ]} @ mf. Proof. apply alloc_local_update. Qed.
Proof. apply insert_local_update. Qed.
Lemma insert_local_update m1 m2 i x y x' y' :
Lemma alloc_singleton_local_update m i x mf : m1 !! i = Some x m2 !! i = Some y
(m ? mf) !! i = None x m ~l~> <[i:=x]> m @ mf. (x, y) ~l~> (x', y')
(m1, m2) ~l~> (<[i:=x']>m1, <[i:=y']>m2).
Proof. Proof.
rewrite lookup_opM op_None=> -[Hi Hif] ?. intros Hi1 Hi2 Hup; apply local_update_unital=> n mf Hmv Hm; simpl in *.
rewrite insert_singleton_op // comm. apply alloc_local_update. destruct (Hup n (mf !! i)) as [? Hx']; simpl in *.
intros n Hm j. move: (Hm j). destruct (decide (i = j)); subst. { move: (Hmv i). by rewrite Hi1. }
- intros _; rewrite !lookup_opM lookup_op !lookup_singleton Hif Hi. { move: (Hm i). by rewrite lookup_op Hi1 Hi2 Some_op_opM (inj_iff Some). }
by apply cmra_valid_validN. split; auto using insert_validN.
- by rewrite !lookup_opM lookup_op !lookup_singleton_ne // right_id. rewrite Hm Hx'=> j; destruct (decide (i = j)) as [->|].
- by rewrite lookup_insert lookup_op lookup_insert Some_op_opM.
- by rewrite lookup_insert_ne // !lookup_op lookup_insert_ne.
Qed.
Lemma singleton_local_update m i x y x' y' :
m !! i = Some x
(x, y) ~l~> (x', y')
(m, {[ i := y ]}) ~l~> (<[i:=x']>m, {[ i := y' ]}).
Proof.
intros. rewrite /singletonM /map_singleton -(insert_insert i y' y).
eapply insert_local_update; eauto using lookup_insert.
Qed. Qed.
Lemma alloc_unit_singleton_local_update i x mf : Lemma delete_local_update m1 m2 i x `{!Exclusive x} :
mf = (!! i) = None x (:gmap K A) ~l~> {[ i := x ]} @ mf. m2 !! i = Some x (m1, m2) ~l~> (delete i m1, delete i m2).
Proof. Proof.
intros Hi; apply alloc_singleton_local_update. by rewrite lookup_opM Hi. intros Hi. apply local_update_unital=> n mf Hmv Hm; simpl in *.
split; auto using delete_validN.
rewrite Hm=> j; destruct (decide (i = j)) as [<-|].
- rewrite lookup_op !lookup_delete left_id symmetry_iff dist_None.
apply eq_None_not_Some=> -[y Hi'].
move: (Hmv i). rewrite Hm lookup_op Hi Hi' -Some_op. by apply exclusiveN_l.
- by rewrite lookup_op !lookup_delete_ne // lookup_op.
Qed. Qed.
Lemma delete_local_update m i x `{!Exclusive x} mf : Lemma delete_singleton_local_update m i x `{!Exclusive x} :
m !! i = Some x m ~l~> delete i m @ mf. (m, {[ i := x ]}) ~l~> (delete i m, ).
Proof. Proof.
intros Hx; split; [intros n; apply delete_update|]. rewrite -(delete_singleton i x).
intros n mf' Hm Hm' j. move: (Hm j) (Hm' j). eapply delete_local_update; eauto using lookup_singleton.
destruct (decide (i = j)); subst.
+ rewrite !lookup_opM !lookup_delete Hx=> ? Hj.
rewrite (exclusiveN_Some_l n x (mf = lookup j)) //.
by rewrite (exclusiveN_Some_l n x (mf' = lookup j)) -?Hj.
+ by rewrite !lookup_opM !lookup_delete_ne.
Qed. Qed.
End properties. End properties.
......
...@@ -47,16 +47,15 @@ Section gset. ...@@ -47,16 +47,15 @@ Section gset.
Lemma gset_update X Y : X ~~> Y. Lemma gset_update X Y : X ~~> Y.
Proof. done. Qed. Proof. done. Qed.
Lemma gset_local_update X Y mXf : X Y X ~l~> Y @ mXf. Lemma gset_local_update X Y X' : X X' (X,Y) ~l~> (X',X').
Proof. Proof.
intros (Z&->&?)%subseteq_disjoint_union_L. intros (Z&->&?)%subseteq_disjoint_union_L.
intros; apply local_update_total; split; [done|]; simpl. rewrite local_update_unital_discrete=> Z' _ /leibniz_equiv_iff->.
intros mZ _. rewrite !gset_opM=> HX. by rewrite (comm_L _ X) -!assoc_L HX. split. done. rewrite gset_op_union. set_solver.
Qed. Qed.
Global Instance gset_persistent X : Persistent X. Global Instance gset_persistent X : Persistent X.
Proof. by apply persistent_total; rewrite gset_core_self. Qed. Proof. by apply persistent_total; rewrite gset_core_self. Qed.
End gset. End gset.
Arguments gsetR _ {_ _}. Arguments gsetR _ {_ _}.
...@@ -72,6 +71,8 @@ Arguments GSetBot {_ _ _}. ...@@ -72,6 +71,8 @@ Arguments GSetBot {_ _ _}.
Section gset_disj. Section gset_disj.
Context `{Countable K}. Context `{Countable K}.
Arguments op _ _ !_ !_ /. Arguments op _ _ !_ !_ /.
Arguments cmra_op _ !_ !_ /.
Arguments ucmra_op _ !_ !_ /.
Canonical Structure gset_disjC := leibnizC (gset_disj K). Canonical Structure gset_disjC := leibnizC (gset_disj K).
...@@ -174,35 +175,45 @@ Section gset_disj. ...@@ -174,35 +175,45 @@ Section gset_disj.
Proof. eauto using gset_disj_alloc_empty_updateP. Qed. Proof. eauto using gset_disj_alloc_empty_updateP. Qed.
End fresh_updates. End fresh_updates.
Lemma gset_disj_dealloc_local_update X Y Xf : Lemma gset_disj_dealloc_local_update X Y :
GSet X ~l~> GSet (X Y) @ Some (GSet Xf). (GSet X, GSet Y) ~l~> (GSet (X Y), ).
Proof.
apply local_update_total_valid=> _ _ /gset_disj_included HYX.
rewrite local_update_unital_discrete=> -[Xf|] _ /leibniz_equiv_iff //=.
rewrite {1}/op /=. destruct (decide _) as [HXf|]; [intros[= ->]|done].
by rewrite difference_union_distr_l_L
difference_diag_L !left_id_L difference_disjoint_L.
Qed.
Lemma gset_disj_dealloc_empty_local_update X Z :
(GSet Z GSet X, GSet Z) ~l~> (GSet X,).
Proof. Proof.
apply local_update_total; split; simpl. apply local_update_total_valid=> /gset_disj_valid_op HZX _ _.
{ rewrite !gset_disj_valid_op; set_solver. } assert (X = (Z X) Z) as HX by set_solver.
intros mZ ?%gset_disj_valid_op. rewrite gset_disj_union //. rewrite gset_disj_union // {2}HX. apply gset_disj_dealloc_local_update.
destruct mZ as [[Z|]|]; simpl; try done.
- rewrite {1}/op {1}/cmra_op /=. destruct (decide _); simpl; try done.
intros [=]. do 2 f_equal. by apply union_cancel_l_L with X.
- intros [=]. assert (Xf = ) as -> by set_solver. by rewrite right_id.
Qed. Qed.
Lemma gset_disj_dealloc_empty_local_update X Xf : Lemma gset_disj_dealloc_op_local_update X Y Z :
GSet X ~l~> GSet @ Some (GSet Xf). (GSet Z GSet X, GSet Z GSet Y) ~l~> (GSet X,GSet Y).
Proof. Proof.
rewrite -(difference_diag_L X). apply gset_disj_dealloc_local_update. rewrite -{2}(left_id _ (GSet Y)).
apply op_local_update_frame, gset_disj_dealloc_empty_local_update.
Qed. Qed.
Lemma gset_disj_alloc_local_update X i Xf : Lemma gset_disj_alloc_op_local_update X Y Z :
i X i Xf GSet X ~l~> GSet ({[i]} X) @ Some (GSet Xf). Z X (GSet X,GSet Y) ~l~> (GSet Z GSet X, GSet Z GSet Y).
Proof.
intros. apply op_local_update_discrete. by rewrite gset_disj_valid_op.
Qed.
Lemma gset_disj_alloc_local_update X Y Z :
Z X (GSet X,GSet Y) ~l~> (GSet (Z X), GSet (Z Y)).
Proof. Proof.
intros ??; apply local_update_total; split; simpl. intros. apply local_update_total_valid=> _ _ /gset_disj_included ?.
- rewrite !gset_disj_valid_op; set_solver. rewrite -!gset_disj_union //; last set_solver.
- intros mZ ?%gset_disj_valid_op HXf. auto using gset_disj_alloc_op_local_update.
rewrite -gset_disj_union -?assoc ?HXf ?cmra_opM_assoc; set_solver.
Qed. Qed.
Lemma gset_disj_alloc_empty_local_update i Xf : Lemma gset_disj_alloc_empty_local_update X Z :
i Xf GSet ~l~> GSet {[i]} @ Some (GSet Xf). Z X (GSet X, GSet ) ~l~> (GSet (Z X), GSet Z).
Proof. Proof.
intros. rewrite -(right_id_L _ _ {[i]}). intros. rewrite -{2}(right_id_L _ union Z).
apply gset_disj_alloc_local_update; set_solver. apply gset_disj_alloc_local_update; set_solver.
Qed. Qed.
End gset_disj. End gset_disj.
......
...@@ -398,6 +398,7 @@ Section properties. ...@@ -398,6 +398,7 @@ Section properties.
rewrite !cmra_update_updateP=> ?; eauto using list_middle_updateP with subst. rewrite !cmra_update_updateP=> ?; eauto using list_middle_updateP with subst.
Qed. Qed.
(* FIXME
Lemma list_middle_local_update l1 l2 x y ml : Lemma list_middle_local_update l1 l2 x y ml :
x ~l~> y @ ml ≫= (!! length l1) → x ~l~> y @ ml ≫= (!! length l1) →
l1 ++ x :: l2 ~l~> l1 ++ y :: l2 @ ml. l1 ++ x :: l2 ~l~> l1 ++ y :: l2 @ ml.
...@@ -421,6 +422,7 @@ Section properties. ...@@ -421,6 +422,7 @@ Section properties.
Lemma list_singleton_local_update i x y ml : Lemma list_singleton_local_update i x y ml :
x ~l~> y @ ml ≫= (!! i) → {[ i := x ]} ~l~> {[ i := y ]} @ ml. x ~l~> y @ ml ≫= (!! i) → {[ i := x ]} ~l~> {[ i := y ]} @ ml.
Proof. intros; apply list_middle_local_update. by rewrite replicate_length. Qed. Proof. intros; apply list_middle_local_update. by rewrite replicate_length. Qed.
*)
End properties. End properties.
(** Functor *) (** Functor *)
......
From iris.algebra Require Export cmra. From iris.algebra Require Export cmra.
(** * Local updates *) (** * Local updates *)
Record local_update {A : cmraT} (mz : option A) (x y : A) := { Definition local_update {A : cmraT} (x y : A * A) := n mz,
local_update_valid n : {n} (x ? mz) {n} (y ? mz); {n} x.1 x.1 {n} x.2 ? mz {n} y.1 y.1 {n} y.2 ? mz.
local_update_go n mz' :
{n} (x ? mz) x ? mz {n} x ? mz' y ? mz {n} y ? mz'
}.
Notation "x ~l~> y @ mz" := (local_update mz x y) (at level 70).
Instance: Params (@local_update) 1. Instance: Params (@local_update) 1.
Infix "~l~>" := local_update (at level 70).
Section updates. Section updates.
Context {A : cmraT}. Context {A : cmraT}.
Implicit Types x y : A. Implicit Types x y : A.
Global Instance local_update_proper : Global Instance local_update_proper :
Proper (() ==> () ==> () ==> iff) (@local_update A). Proper (() ==> () ==> iff) (@local_update A).
Proof. Proof. unfold local_update. by repeat intro; setoid_subst. Qed.
cut (Proper (() ==> () ==> () ==> impl) (@local_update A)).
{ intros Hproper; split; by apply Hproper. }
intros mz mz' Hmz x x' Hx y y' Hy [Hv Hup]; constructor; setoid_subst; auto.
Qed.
Global Instance local_update_preorder mz : PreOrder (@local_update A mz). Global Instance local_update_preorder : PreOrder (@local_update A).
Proof. Proof. split; unfold local_update; red; naive_solver. Qed.
split.
- intros x; by split.
- intros x1 x2 x3 [??] [??]; split; eauto.
Qed.
Lemma exclusive_local_update `{!Exclusive x} y mz : y x ~l~> y @ mz. Lemma exclusive_local_update `{!Exclusive y} x x' : x' (x,y) ~l~> (x',x').
Proof. Proof.
split; intros n. intros ? n mz Hxv Hx; simpl in *.
- move=> /exclusiveN_opM ->. by apply cmra_valid_validN. move: Hxv; rewrite Hx; move=> /exclusiveN_opM=> ->; split; auto.
- intros mz' ? Hmz. by apply cmra_valid_validN.
by rewrite (exclusiveN_opM n x mz) // (exclusiveN_opM n x mz') -?Hmz. Qed.
Qed.
Lemma op_local_update x1 x2 y mz : Lemma op_local_update x y z :
x1 ~l~> x2 @ Some (y ? mz) x1 y ~l~> x2 y @ mz. ( n, {n} x {n} (z x)) (x,y) ~l~> (z x, z y).
Proof. Proof.
intros [Hv1 H1]; split. intros Hv n mz Hxv Hx; simpl in *; split; [by auto|].
- intros n. rewrite !cmra_opM_assoc. move=> /Hv1 /=; auto. by rewrite Hx -cmra_opM_assoc.
- intros n mz'. rewrite !cmra_opM_assoc. move=> Hv /(H1 _ (Some _) Hv) /=; auto. Qed.
Qed. Lemma op_local_update_discrete `{!CMRADiscrete A} x y z :
( x (z x)) (x,y) ~l~> (z x, z y).
Proof.
intros; apply op_local_update=> n. by rewrite -!(cmra_discrete_valid_iff n).
Qed.
Lemma alloc_local_update x y mz : Lemma op_local_update_frame x y x' y' yf :
( n, {n} (x ? mz) {n} (x y ? mz)) x ~l~> x y @ mz. (x,y) ~l~> (x',y') (x,y yf) ~l~> (x', y' yf).
Proof. Proof.
split; first done. intros Hup n mz Hxv Hx; simpl in *.
intros n mz' _. by rewrite !(comm _ x) !cmra_opM_assoc=> ->. destruct (Hup n (Some (yf ? mz))); [done|by rewrite /= -cmra_opM_assoc|].
Qed. by rewrite cmra_opM_assoc.
Qed.
Lemma local_update_total `{CMRADiscrete A} x y mz : Lemma local_update_discrete `{!CMRADiscrete A} (x y x' y' : A) :
x ~l~> y @ mz (x,y) ~l~> (x',y') mz, x x y ? mz x' x' y' ? mz.
( (x ? mz) (y ? mz)) Proof.
( mz', (x ? mz) x ? mz x ? mz' y ? mz y ? mz'). rewrite /local_update /=. setoid_rewrite <-cmra_discrete_valid_iff.
Proof. setoid_rewrite <-(λ n, timeless_iff n x).
split. setoid_rewrite <-(λ n, timeless_iff n x'). naive_solver eauto using 0.
- destruct 1. split; intros until 0; Qed.
rewrite !(cmra_discrete_valid_iff 0) ?(timeless_iff 0); auto.
- intros [??]; split; intros until 0; Lemma local_update_valid0 x y x' y' :
rewrite -!cmra_discrete_valid_iff -?timeless_iff; auto. ({0} x {0} y x {0} y y {0} x (x,y) ~l~> (x',y'))
Qed. (x,y) ~l~> (x',y').
Proof.
intros Hup n mz Hmz Hz; simpl in *. apply Hup; auto.
- by apply (cmra_validN_le n); last lia.
- apply (cmra_validN_le n); last lia.
move: Hmz; rewrite Hz. destruct mz; simpl; eauto using cmra_validN_op_l.
- destruct mz as [z|].
+ right. exists z. apply dist_le with n; auto with lia.
+ left. apply dist_le with n; auto with lia.
Qed.
Lemma local_update_valid `{!CMRADiscrete A} x y x' y' :
( x y x y y x (x,y) ~l~> (x',y')) (x,y) ~l~> (x',y').
Proof.
rewrite !(cmra_discrete_valid_iff 0)
(cmra_discrete_included_iff 0) (timeless_iff 0).
apply local_update_valid0.
Qed.
Lemma local_update_total_valid0 `{!CMRATotal A} x y x' y' :
({0} x {0} y y {0} x (x,y) ~l~> (x',y')) (x,y) ~l~> (x',y').
Proof.
intros Hup. apply local_update_valid0=> ?? [Hx|?]; apply Hup; auto.
by rewrite Hx.
Qed.
Lemma local_update_total_valid `{!CMRATotal A, !CMRADiscrete A} x y x' y' :
( x y y x (x,y) ~l~> (x',y')) (x,y) ~l~> (x',y').
Proof.
rewrite !(cmra_discrete_valid_iff 0) (cmra_discrete_included_iff 0).
apply local_update_total_valid0.
Qed.
End updates. End updates.
Section updates_unital.
Context {A : ucmraT}.