(*+ Collection of disjoint maps *)
(** For the proof of composition of safety, we need to maintain the invariants "all the maps are disjoint*" which is why we need this section.  * pairwise-disjointness is equivalent to arbitrary disjointness because the permissions are "set-theoretical" *)
Definition sameperms (m n : map) := forall x, m x = None <-> n x = None.

(* Specifications: *)
Lemma sameperms_refl m : sameperms m m.
Lemma sameperms_sym m n : sameperms m n -> sameperms n m.
Lemma sameperms_trans m n o : sameperms m n -> sameperms n o -> sameperms m o.
Hint Resolve sameperms_refl sameperms_sym sameperms_trans.
Lemma sameperms_updatemap m x e m' : updatemap m x e = Some m' -> sameperms m m'.
Lemma sameperms_joins m m' n : sameperms m m' -> joins m n -> joins m' n.
Hint Resolve sameperms_updatemap.
Lemma selfjoins_sameperms_compat {A} maps1 maps2 : (forall i:A, sameperms (maps1 i) (maps2 i)) -> selfjoins maps1 -> selfjoins maps2.
Definition swapped {A} (m1 m2 : A -> map) i j a b c d :=
m1 i = a /\
m1 j = b /\
m2 i = c /\
m2 j = d /\
forall k, k <> i -> k <> j -> m1 k = m2 k.
Lemma selfjoins_swapped {A} {m1 m2 : A -> map} (Adec:forall x y:A,{x=y}+{x<>y})
i j (J:selfjoins m1) e a b c d :
swapped m1 m2 i j a b c d ->
join a b e ->
join c d e ->
selfjoins m2.
Lemma natnateqdec (x y : nat + nat) : {x=y}+{x<>y}. repeat decide equality. Defined.
Tactic Notation "rewr" :=
match goal with
| H : ?f = _ |- context [?f] => rewrite H
| H : ?f _ = ?f _ |- _ => try (injection H; repeat intros ->)
end.