Tactic Notation "rewr" constr(e) := match goal with E : e = _ |- _ => rewrite E | E : _ = e |- _ => rewrite <-E end.
Tactic Notation "rewr" constr(e) "in" "*" := match goal with E : e = _ |- _ => rewrite E in * | E : _ = e |- _ => rewrite <-E in * end.
Tactic Notation "rewr" constr(e) "in" hyp(H) := match goal with E : e = _ |- _ => rewrite E in H | E : _ = e |- _ => rewrite <-E in H end.
(* Subject reduction : taking a step let us stay in the invariant *)

Theorem soundness sch F G thd pool :
(forall l, precise (resinvs G l)) ->
selfjoins (reindex thd pool) ->
lockpool_matches pool (resinvs G) ->
functions_safe G F ->
(forall i oracle m p,
nth thd i = Some (m, p) ->
safe step (G, oracle, m, p)) ->
safe machine (sch, F, G, thd, pool).