diff --git a/theories/examples/counterexamples.v b/theories/examples/counterexamples.v
deleted file mode 100644
index 9003e3f1f3024d5657c44ee4dcc957a3b9384e9e..0000000000000000000000000000000000000000
--- a/theories/examples/counterexamples.v
+++ /dev/null
@@ -1,227 +0,0 @@
-From iris.algebra Require Import base stepindex.
-
-(** counter-examples for existential properties *)
-Section existential_negative.
-  (* Transfinite step-index types cannot validate the bounded existential property. *)
-  Context {SI : indexT}. 
-  Record sProp := 
-    { 
-      prop : SI → Prop; 
-      prop_downclosed : ∀ α β, α ≺ β → prop β → prop α
-    }. 
-  Program Definition sProp_later (P : sProp) := Build_sProp (λ γ, ∀ γ', γ' ≺ γ → prop P γ') _.
-  Next Obligation. 
-    intros [P Pdown] α β Hα. cbn. eauto with index.
-  Qed.
-  Program Definition sProp_false := Build_sProp (λ _, False) _. 
-  Next Obligation.  intros. assumption. Qed.
-
-  Program Definition sProp_ex {X} (Φ : X → sProp) := Build_sProp (λ α, ∃ x, prop (Φ x) α) _. 
-  Next Obligation. 
-    intros X Φ α β Hα. cbn. intros [x H]. exists x. by eapply prop_downclosed. 
-  Qed.
-
-  Definition bounded_existential (X : Type) (Φ : X → sProp) α:=
-    (∀ β, β ≺ α → ∃ x : X, prop (Φ x) β)
-    → ∃ x : X, ∀ β, β ≺ α → prop (Φ x) β.
-  Definition existential (X : Type) (Φ : X → sProp) := 
-    (∀ α, ∃ x : X, prop (Φ x) α) 
-    → ∃ x : X, ∀ α, prop (Φ x) α. 
-
-  Section transfinite.
-    Hypothesis (ω: SI).
-    Hypothesis (is_limit_of_nat: ∀ n, Nat.iter n (index_succ SI) zero ≺ ω).
-    Hypothesis (is_smallest: ∀ α, α ≺ ω → ∃ n, α = Nat.iter n (index_succ SI) zero).
-    
-    Lemma transfinite_no_bounded_existential : 
-      bounded_existential nat (λ n, Nat.iter n sProp_later sProp_false) ω → False.
-    Proof. 
-      intros H. unfold bounded_existential in H. edestruct H as [n H']. 
-      { intros β Hβ. apply is_smallest in Hβ as (n & ->). exists (S n).
-        induction n as [ | n IH]. 
-        - intros ? []%index_lt_zero_is_normal.
-        - intros α Hα. apply index_succ_iff in Hα as [ -> | Hα]. now apply IH. 
-          intros β Hβ. apply IH. eauto with index. 
-      } 
-      specialize (H' (Nat.iter n (index_succ SI) zero) ltac:(apply is_limit_of_nat)). 
-      induction n as [ | n IH]; cbn in H'. exact H'. 
-      apply IH. apply H'. apply index_succ_greater. 
-    Qed.
-  End transfinite.
-End existential_negative.
-
-Section no_later_exists.
-(** A step-indexed logic cannot have 
-  * a sound later-operation,  
-  * Löb induction 
-  * Commutation of later with existentials: ▷ (∃ x. P) ⊢ ▷ False ∨ ∃ x. ▷ P
-  * the existential property for countable types, if ⊢ ∃ n : nat. P n, then there is n : nat such that ⊢ P n. 
-*)
-
-  Context 
-    (PROP : Type) (* the type of propositions *)
-    (entail : PROP → PROP → Prop) (* the entailment relation *)
-    (TRUE : PROP) (* the true proposition *)
-    (FALSE : PROP) (* the false proposition *)
-    (later : PROP → PROP) (* the later modality *)
-    (ex : (nat → PROP) → PROP). (* for simplicity, we restrict to predicates over nat here since we don't need more for the proof *)
-
-  Implicit Types (P Q: PROP). 
-
-  Notation "▷ P" := (later P) (at level 20). 
-  Notation "P ⊢ Q" := (entail P Q) (at level 60). 
-  Notation "⊢ P" := (entail TRUE P) (at level 60). 
-
-  (* standard structural rules *)
-  Context 
-    (cut : ∀ P Q R, P ⊢ Q → Q ⊢ R → P ⊢ R)
-    (assumption : ∀ P, P ⊢ P)
-    (ex_intro : ∀ P Φ, (∃ n, P ⊢ Φ n) → P ⊢ ex Φ)
-    (ex_elim : ∀ P Φ, (∀ n, Φ n ⊢ P) → ex Φ ⊢ P). 
-
-  
-  (* relevant assumptions about our step-indexed logic *)
-  Context 
-    (logic_sound: ¬ ⊢ FALSE) 
-    (later_sound: ∀ P, ⊢ ▷ P → ⊢ P) (* later is sound *)
-    (existential : ∀ (Φ : nat → PROP), (⊢ ex Φ) → ∃ n, ⊢ (Φ n)) (* the existential property for nat *)
-    (Löb : ∀ P, (▷ P ⊢ P) → ⊢ P). (* Löb induction *)
-    
-  (* now later commuting with existentials is contradictory *)
-  Lemma no_later_existential_commuting : 
-    (∀ Φ, ▷ (ex Φ) ⊢ (ex (λ n, ▷ (Φ n))) )
-    → False.
-  Proof. 
-    intros Hcomm. apply logic_sound.  
-    assert (∃ n, ⊢ Nat.iter n later FALSE) as [ n Hf]. 
-    { apply existential. 
-      apply Löb. 
-      eapply cut. apply Hcomm. 
-      apply ex_elim. 
-      intros n. apply ex_intro. exists (S n). apply assumption. 
-    } 
-    induction n as [ | n IH]. 
-    exact Hf. 
-    apply IH. apply later_sound, Hf. 
-  Qed.
-End no_later_exists.
-
-
-From iris.algebra Require Export cmra updates.
-From iris.base_logic Require Import upred. 
-From iris.bi Require Import notation.
-Section more_counterexamples. 
-  Context {I: indexT} {M : ucmraT I}.
-  Implicit Types φ : Prop.
-  Implicit Types P Q : uPred M.
-  Implicit Types A : Type.
-  Arguments uPred_holds {_ _} !_ _ _ /.
-  Hint Immediate uPred_in_entails : core.
-
-  Notation "P ⊢ Q" := (@uPred_entails I M P%I Q%I) : stdpp_scope.
-  Notation "(⊢)" := (@uPred_entails I M) (only parsing) : stdpp_scope.
-  Notation "P ⊣⊢ Q" := (@uPred_equiv I M P%I Q%I) : stdpp_scope.
-  Notation "(⊣⊢)" := (@uPred_equiv I M) (only parsing) : stdpp_scope.
-
-  Notation "'True'" := (uPred_pure True) : bi_scope.
-  Notation "'False'" := (uPred_pure False) : bi_scope.
-  Notation "'⌜' φ '⌝'" := (uPred_pure φ%type%stdpp) : bi_scope.
-  Infix "∧" := uPred_and : bi_scope.
-  Infix "∨" := uPred_or : bi_scope.
-  Infix "→" := uPred_impl : bi_scope.
-  Notation "∀ x .. y , P" :=
-    (uPred_forall (λ x, .. (uPred_forall (λ y, P)) ..)) : bi_scope.
-  Notation "∃ x .. y , P" :=
-    (uPred_exist (λ x, .. (uPred_exist (λ y, P)) ..)) : bi_scope.
-  Infix "∗" := uPred_sep : bi_scope.
-  Infix "-∗" := uPred_wand : bi_scope.
-  Notation "□ P" := (uPred_persistently P) : bi_scope.
-  Notation "■ P" := (uPred_plainly P) : bi_scope.
-  Notation "x ≡ y" := (uPred_internal_eq x y) : bi_scope.
-  Notation "▷ P" := (uPred_later P) : bi_scope.
-  Notation "|==> P" := (uPred_bupd P) : bi_scope.
-  Notation "▷^ n P" := (Nat.iter n uPred_later P) : bi_scope.
-  Notation "▷? p P" := (Nat.iter (Nat.b2n p) uPred_later P) : bi_scope.
-  Notation "⧍ P" := (∃ n, ▷^n P)%I : bi_scope.
-  Notation "⧍^ n P" := (Nat.iter n (λ Q, ⧍ Q) P)%I : bi_scope.
-
-  Import uPred_primitive. 
-
-  Section bounded_limit_preserving_counterexample.
-
-    Definition F (P: uPred M) : uPred M := P.
-    Definition G (P: uPred M) : uPred M := (∃ n, ▷^n False)%I.
-    Definition c {α: I} : bchain (uPredO M) α := bchain_const (∃ n, ▷^n False)%I α.
-
-    Hypothesis (omega: I).
-    Hypothesis (is_limit_of_nat: ∀ n, Nat.iter n (index_succ I) zero ≺ omega).
-    Hypothesis (is_smallest: ∀ α, α ≺ omega → ∃ n, α = Nat.iter n (index_succ I) zero).
-
-    Notation "'ω'" := omega.
-    Lemma zero_omega: zero ≺ ω.
-    Proof using I is_limit_of_nat omega. eapply (is_limit_of_nat 0). Qed.
-
-    Lemma bounded_limit_preserving_entails_counterexample:
-      ¬ BoundedLimitPreserving (λ P, F P ⊢ G P).
-    Proof using I M is_limit_of_nat is_smallest omega.
-      intros H. specialize (H ω zero_omega c); simpl in H.
-      assert (∀ β : I, β ≺ ω → F (⧍ ⌜False⌝) ⊢ G (⧍ ⌜False⌝)) as H'.
-      { intros ??. destruct (entails_po (I:=I) (M:=M)) as [R _]. apply R. }
-      specialize (H H'). destruct H as [H].
-      specialize (H ω ε (ucmra_unit_validN ω)).
-      unfold F in *. assert (bcompl zero_omega c ω ε) as H''.
-      { eapply bcompl_unfold. unfold c; simpl.
-        intros n' Hn' _ Hv. eapply is_smallest in Hn'.
-        destruct Hn' as [m ->]. unseal.
-        exists (S m). clear Hv H' H. induction m; cbn.
-        - intros ? [] % index_lt_zero_is_normal.
-        - intros n' Hn' n'' Hn''. eapply uPred_mono.
-          eapply IHm; eauto.
-          eapply index_lt_le_trans. eapply Hn''.
-          eapply index_succ_iff, Hn'.
-          all: eauto.
-      }
-      specialize (H H''). unfold G in *.
-      revert H; unseal. intros [n].
-      eapply uPred_mono with (n2 := (Nat.iter (S n) (index_succ I) zero)) in H; eauto.
-      clear H' H''. induction n; simpl in *; eauto.
-    Qed.
-
-  End bounded_limit_preserving_counterexample.
-
-  Section ne_does_not_preserve_limits.
-    (* we show that, in general, non-expansive maps do not preserve limits. *)
-
-    Program Definition f : uPredO M -n> uPredO M := λne P, (P ∧ ∃ n, ▷^n False)%I.
-    Next Obligation.
-      intros α x y Heq. apply and_ne. apply Heq. reflexivity.
-    Qed.
-    Definition c0 {α: I} : bchain (uPredO M) α := bchain_const (True)%I α.
-
-    Hypothesis (omega: I).
-    Hypothesis (is_limit_of_nat: ∀ n, Nat.iter n (index_succ I) zero ≺ omega).
-    Hypothesis (is_smallest: ∀ α, α ≺ omega → ∃ n, α = Nat.iter n (index_succ I) zero).
-
-
-    Notation "'ω'" := omega.
-    Lemma zero_omega': zero ≺ ω.
-    Proof using I is_limit_of_nat omega. eapply (is_limit_of_nat 0). Qed.
-
-    Lemma test : ¬ (f (bcompl zero_omega' c0) ≡ bcompl zero_omega' (bchain_map f c0)).
-    Proof using is_smallest.
-      intros Heq. destruct Heq as [Heq]. specialize (Heq omega ε (ucmra_unit_validN _)).
-      cbn in Heq. destruct Heq as [_ H1].
-      revert H1. rewrite !bcompl_unfold; cbn. unseal. intros H. destruct H as [ _ H].
-      2: { destruct H as [n H]. eapply uPred_mono with (n2 := Nat.iter (S n) (index_succ I) zero) in H; eauto.
-        induction n as [ | n IH]; cbn in H; [tauto | ].
-        eapply IH. apply H. eapply index_succ_greater.
-      }
-      intros. split; [easy | ]. apply is_smallest in Hn' as [nn ->]. exists (S nn).
-      clear H0 H. induction nn as [ | n IH]; cbn.
-      - intros ? []%index_lt_zero_is_normal.
-      - intros n' Hn' n'' Hn''. apply IH. eapply index_lt_le_trans.
-        exact Hn''. apply index_succ_iff, Hn'.
-    Qed.
-  End ne_does_not_preserve_limits.
-
-End more_counterexamples.
diff --git a/theories/examples/keyideas/generalized_simulations.v b/theories/examples/keyideas/generalized_simulations.v
deleted file mode 100644
index 623475e5acf4f7a89c2842dc123616efb4d6f6da..0000000000000000000000000000000000000000
--- a/theories/examples/keyideas/generalized_simulations.v
+++ /dev/null
@@ -1,147 +0,0 @@
-From iris.base_logic Require Export iprop satisfiable.
-From iris.bi Require Export fixpoint.
-From iris.proofmode Require Import tactics.
-
-
-Section simulations.
-
-  Context {SI} `{LargeIndex SI} {Σ: gFunctors SI}.
-
-
-  (* We assume a source and a target language *)
-  Variable (S T: Type) (src_step: S → S → Prop) (tgt_step: T → T → Prop).
-  Variable (V: Type) (val_to_tgt: V → T) (φ: V → S → Prop).
-  Variable (val_irred: ∀ v, ¬ ∃ t', tgt_step (val_to_tgt v) t') (val_inj: Inj eq eq val_to_tgt).
-
-
-  (* refinements *)
-  Definition gtpr (t: T) (s: S) :=
-    (∀ v, rtc tgt_step t (val_to_tgt v) → ∃ s', rtc src_step s s' ∧ φ v s') ∧
-    (ex_loop tgt_step t → ex_loop src_step s).
-
-
-  Notation "S *d T" := (prodO (leibnizO SI T) (leibnizO SI S)) (at level 60).
-  Definition gsim_pre (sim: ((S *d T) → iProp Σ)) : (S *d T) → iProp Σ :=
-    (λ '(t, s),
-      (∃ v, ⌜φ v s⌝ ∧ ⌜val_to_tgt v = t⌝) ∨
-      (∃ t', ⌜tgt_step t t'⌝) ∧
-      (∀ t', ⌜tgt_step t t'⌝ → sim (t', s) ∨ ∃ s', ⌜src_step s s'⌝ ∧ ▷ sim (t', s'))
-    )%I.
-
-  Instance gsim_pre_mono: BiMonoPred gsim_pre.
-  Proof.
-    split.
-    - intros Φ Ψ. iIntros "#H" ([t s]).
-      rewrite /gsim_pre.
-      iIntros "[Hsim|Hsim]"; eauto.
-      iRight. iDestruct "Hsim" as "[Hsteps Hsim]".
-      iSplit; eauto.
-      iIntros (t' Htgt). iDestruct ("Hsim" $! t' Htgt) as "[Hsim|Hsim]".
-      + iLeft. by iApply "H".
-      + iRight. iDestruct "Hsim" as (s' Hsrc) "Hsim".
-        iExists s'. iSplit; eauto. iNext. by iApply "H".
-    - intros Φ Hdist α [t s] [t' s'] [Heq1 Heq2]; simpl in *.
-      repeat f_equiv; eauto.
-  Qed.
-
-  Definition gsim := bi_least_fixpoint gsim_pre.
-
-  Lemma sim_unfold t s:
-    (gsim (t, s) ⊣⊢ (∃ v, ⌜φ v s⌝ ∧ ⌜val_to_tgt v = t⌝) ∨
-    (∃ t', ⌜tgt_step t t'⌝) ∧
-    (∀ t', ⌜tgt_step t t'⌝ → gsim (t', s) ∨ ∃ s', ⌜src_step s s'⌝ ∧ ▷ gsim (t', s')))%I.
-  Proof.
-    fold (gsim_pre gsim (t, s)). iSplit.
-    - iApply least_fixpoint_unfold_1.
-    - iApply least_fixpoint_unfold_2.
-  Qed.
-
-
-  Lemma satisfiable_pure ψ: satisfiable (⌜ψ⌝: iProp Σ)%I → ψ.
-  Proof.
-    intros Hsat. apply satisfiable_elim in Hsat; last apply _.
-    by apply uPred.pure_soundness in Hsat.
-  Qed.
-
-  (* result preserving *)
-  Lemma gsim_execute_tgt_step t s t':
-    tgt_step t t' → satisfiable (gsim (t, s)) → ∃ s', rtc src_step s s' ∧ satisfiable (gsim (t', s')).
-  Proof.
-    intros Hstep Hsat.
-    eapply satisfiable_mono with (Q := (∃ s', ⌜rtc src_step s s'⌝ ∧ ▷ gsim (t', s'))%I) in Hsat.
-    - eapply satisfiable_exists in Hsat as [s' Hsat].
-      exists s'. split.
-      + eapply satisfiable_pure, satisfiable_mono; eauto. iIntros "[$ _]".
-      + eapply satisfiable_later, satisfiable_mono; eauto. iIntros "[_ $]".
-    - iIntros "Hsim". rewrite sim_unfold. iDestruct "Hsim" as "[Hsim|[_ Hsim]]".
-     + iDestruct "Hsim" as (v) "[_ <-]". exfalso. naive_solver.
-     + iDestruct ("Hsim" $! t' Hstep) as "[Hsim|Hsim]".
-       * iExists s. iSplit; first by iPureIntro. by iNext.
-       * iDestruct "Hsim" as (s' Hstep') "Hsim". iExists s'. iSplit; eauto.
-          iPureIntro. by eapply rtc_l.
-   Qed.
-
-  Lemma sim_execute_tgt t s t':
-    rtc tgt_step t t' → satisfiable (gsim (t, s)) → ∃ s', rtc src_step s s' ∧ satisfiable (gsim (t', s')).
-  Proof.
-    induction 1 in s.
-    - intros Hsim. exists s. by split.
-    - intros Hsim. eapply gsim_execute_tgt_step in Hsim; last eauto.
-      destruct Hsim as [s' [Hsrc Hsat]].
-      destruct (IHrtc _ Hsat) as [s'' [Hsrc' Hsat']].
-      exists s''. split; auto. by transitivity s'.
-  Qed.
-
-
-  (* termination preserving *)
-  Lemma sim_execute_tgt_step t s:
-    ex_loop tgt_step t → satisfiable (gsim (t, s)) →  ∃ t' s', src_step s s' ∧ ex_loop tgt_step t' ∧ satisfiable (gsim (t', s')).
-  Proof.
-    intros Hsteps Hsat.
-    eapply satisfiable_mono with (Q := (∃ t' s', ⌜src_step s s'⌝ ∧ ⌜ex_loop tgt_step t'⌝ ∧ ▷ gsim (t', s'))%I) in Hsat; last first.
-    iPoseProof (@least_fixpoint_strong_ind _ _ _ gsim_pre _ (λ '(t, s), ⌜ex_loop tgt_step t⌝ → ∃ (t' : T) (s' : S), ⌜src_step s s'⌝ ∧ ⌜ex_loop tgt_step t'⌝ ∧ ▷ gsim (t', s'))%I) as "Hind".
-    { intros ? [t'' s''] [t' s'] [Heq1 Heq2]; repeat f_equiv; eauto. }
-    - iIntros "Hsim". iRevert (Hsteps). iRevert "Hsim". iSpecialize ("Hind" with "[]"); last iApply ("Hind" $! (t, s)).
-      clear Hsat t s. iModIntro. iIntros ([t s]). iIntros "Hsim" (Hloop).
-      rewrite /gsim_pre. iDestruct "Hsim" as "[Hsim|Hsim]".
-      + iDestruct "Hsim" as (v) "[_ %]".
-        destruct Hloop as [t t']; subst t. naive_solver.
-      + iDestruct "Hsim" as "[_ Hsim]".
-        inversion Hloop as [t'' t' Hstep Hloop']; subst t''.
-        iDestruct ("Hsim" $! t' Hstep) as "[Hsim|Hsim]".
-        * iDestruct "Hsim" as "[Hsim _]". by iSpecialize ("Hsim" $! Hloop').
-        * iDestruct "Hsim" as (s' Hstep') "Hsim".
-          iExists t', s'. repeat iSplit; eauto.
-          iNext. iDestruct "Hsim" as "[_ $]".
-    - eapply satisfiable_exists in Hsat as [t' Hsat].
-      eapply satisfiable_exists in Hsat as [s' Hsat].
-      exists t', s'. repeat split.
-      + eapply satisfiable_pure, satisfiable_mono; eauto. iIntros "($ & _ & _)".
-      + eapply satisfiable_pure, satisfiable_mono; eauto. iIntros "(_ & $ & _)".
-      + eapply satisfiable_later, satisfiable_mono; eauto. iIntros "(_ & _ & $)".
-  Qed.
-
-  Lemma sim_divergence t s:
-    ex_loop tgt_step t → satisfiable (gsim (t, s)) → ex_loop src_step s.
-  Proof.
-    revert t s. cofix IH. intros t s Hloop Hsat.
-    edestruct sim_execute_tgt_step as (t' & s' & Hsrc & Hloop' & Hsim); [eauto..|].
-    econstructor; eauto.
-  Qed.
-
-  Lemma sim_is_tpr t s: (⊢ gsim (t, s)) → gtpr t s.
-  Proof.
-    intros Hsim. split.
-    - apply satisfiable_intro in Hsim. intros v Hsteps.
-      eapply sim_execute_tgt in Hsteps as [s' [Hsteps' Hsat]]; eauto.
-      enough (φ v s') by eauto.
-      eapply satisfiable_pure, satisfiable_mono; eauto.
-      rewrite sim_unfold. iIntros "[H|[H _]]".
-      + iDestruct "H" as (v')  "[% H]". by iDestruct "H" as %->%val_inj.
-      + iDestruct "H" as (t') "%". exfalso. naive_solver.
-    - intros Hloop. eapply sim_divergence; eauto.
-      apply satisfiable_intro, Hsim.
-  Qed.
-
-End simulations.
-
diff --git a/theories/examples/keyideas/simulations.v b/theories/examples/keyideas/simulations.v
deleted file mode 100644
index 35f5f9e38d923e01386577c392a7a57127dc25c7..0000000000000000000000000000000000000000
--- a/theories/examples/keyideas/simulations.v
+++ /dev/null
@@ -1,129 +0,0 @@
-From iris.base_logic Require Export iprop satisfiable.
-From iris.bi Require Export fixpoint.
-From iris.proofmode Require Import tactics.
-
-
-Section simulations.
-
-  Context {SI} `{LargeIndex SI} {Σ: gFunctors SI}.
-
-
-  (* We assume a source and a target language *)
-  Variable (S T: Type) (src_step: S → S → Prop) (tgt_step: T → T → Prop).
-  Variable (V: Type) (val_to_src: V → S) (val_to_tgt: V → T).
-  Variable (val_irred: ∀ v, ¬ ∃ t', tgt_step (val_to_tgt v) t') (val_inj: Inj eq eq val_to_tgt).
-
-
-  (* refinements *)
-  Definition rpr (t: T) (s: S) :=
-    (∀ v, rtc tgt_step t (val_to_tgt v) → rtc src_step s (val_to_src v)).
-
-  Definition tpr (t: T) (s: S) :=
-    (∀ v, rtc tgt_step t (val_to_tgt v) → rtc src_step s (val_to_src v)) ∧
-    (ex_loop tgt_step t → ex_loop src_step s).
-
-  Definition sim_pre (sim: (T -d> S -d> iProp Σ)) : T -d> S -d> iProp Σ :=
-    (λ t s,
-      (∃ v, ⌜val_to_src v = s⌝ ∧ ⌜val_to_tgt v = t⌝) ∨
-      (∃ t', ⌜tgt_step t t'⌝) ∧
-      (∀ t', ⌜tgt_step t t'⌝ → ∃ s', ⌜src_step s s'⌝ ∧ ▷ sim t' s')
-    )%I.
-
-  Instance sim_pre_contr: Contractive sim_pre.
-  Proof.
-    intros a sim sim' Heq. unfold sim_pre.
-    intros t s. do 8 f_equiv. apply bi.later_contractive.
-    intros ??. by apply Heq.
-  Qed.
-
-
-  Definition sim := fixpoint sim_pre.
-
-  Lemma sim_unfold':
-    sim ≡ sim_pre sim.
-  Proof. by rewrite {1}/sim fixpoint_unfold. Qed.
-
-  Lemma sim_unfold t s:
-    (sim t s ⊣⊢ ((∃ v, ⌜val_to_src v = s⌝ ∧ ⌜val_to_tgt v = t⌝) ∨
-    (∃ t', ⌜tgt_step t t'⌝) ∧
-    (∀ t', ⌜tgt_step t t'⌝ → ∃ s', ⌜src_step s s'⌝ ∧ ▷ sim t' s')))%I.
-  Proof. apply sim_unfold'. Qed.
-
-  Instance sim_plain t s: Plain (sim t s).
-  Proof.
-    unfold Plain. iRevert (t s). iLöb as "IH".
-    iIntros (t s); rewrite sim_unfold.
-    iIntros "[H1|[H1 H2]]".
-    - iLeft. iApply (plain with "H1").
-    - iRight. iSplit; first iApply (plain with "H1").
-      iIntros (t' Hstep). iDestruct ("H2" $! t' Hstep) as (s' Hstep') "Hsim".
-      iExists s'; iSplit; first (iApply plain; by iPureIntro).
-      iApply later_plainly_1. iNext. by iApply "IH".
-  Qed.
-
-  Lemma sim_valid_satisfiable t s: satisfiable (sim t s) ↔ ⊢ sim t s.
-  Proof.
-    split.
-    - intros ? % satisfiable_elim; eauto. apply _.
-    - by intros ? % satisfiable_intro.
-  Qed.
-
-
-  Lemma satisfiable_pure φ: satisfiable (⌜φ⌝: iProp Σ)%I → φ.
-  Proof.
-    intros Hsat. apply satisfiable_elim in Hsat; last apply _.
-    by apply uPred.pure_soundness in Hsat.
-  Qed.
-
-  (* result preserving *)
-  Lemma sim_execute_tgt_step t s t':
-    tgt_step t t' → satisfiable (sim t s) → ∃ s', src_step s s' ∧ satisfiable (sim t' s').
-  Proof.
-    intros Hstep Hsat.
-    eapply satisfiable_mono with (Q := (∃ s', ⌜src_step s s'⌝ ∧ ▷ sim t' s')%I) in Hsat.
-    - eapply satisfiable_exists in Hsat as [s' Hsat].
-      exists s'. split.
-      + eapply satisfiable_pure, satisfiable_mono; eauto. iIntros "[$ _]".
-      + eapply satisfiable_later, satisfiable_mono; eauto. iIntros "[_ $]".
-    - iIntros "Hsim". rewrite sim_unfold. iDestruct "Hsim" as "[Hsim|[_ Hsim]]".
-     + iDestruct "Hsim" as (v) "[<- <-]". exfalso. naive_solver.
-     + iApply ("Hsim" $! t' Hstep).
-   Qed.
-
-  Lemma sim_execute_tgt t s t':
-    rtc tgt_step t t' → satisfiable (sim t s) 
-    → ∃ s', rtc src_step s s' ∧ satisfiable (sim t' s').
-  Proof.
-    induction 1 in s.
-    - intros Hsim. exists s. by split.
-    - intros Hsim. eapply sim_execute_tgt_step in Hsim; eauto.
-      destruct Hsim as [s' [Hsrc Hsat]].
-      destruct (IHrtc _ Hsat) as [s'' [Hsrc' Hsat']].
-      exists s''. split; auto. by eapply rtc_l.
-  Qed.
-
-  (* Lemma 2.1 *)
-  Lemma sim_is_rpr t s: (⊢ sim t s) → rpr t s.
-  Proof.
-    intros Hsim % sim_valid_satisfiable v Hsteps.
-    eapply sim_execute_tgt in Hsteps as [s' [Hsteps' Hsat]]; eauto.
-    enough (s' = (val_to_src v)) as -> by eauto.
-    eapply satisfiable_pure, satisfiable_mono; eauto.
-    rewrite sim_unfold. iIntros "[H|[H _]]".
-    - iDestruct "H" as (v')  "[<- H]". by iDestruct "H" as %->%val_inj.
-    - iDestruct "H" as (t') "%". exfalso. naive_solver.
-  Qed.
-
-
-  (* Lemma 2.2 *)
-  Lemma sim_is_tpr t s: (⊢ sim t s) → tpr t s.
-  Proof.
-    intros Hsim. split.
-    - by apply sim_is_rpr.
-    - apply sim_valid_satisfiable in Hsim. revert t s Hsim.
-      cofix IH. intros t s Hsat. inversion 1 as [t'' t' Hstep Hloop]; subst t''.
-      destruct (sim_execute_tgt_step _ _ _ Hstep Hsat) as [s' [Hstep' Hsat']].
-      econstructor; eauto.
-  Qed.
-End simulations.
-
diff --git a/theories/examples/refinements/derived.v b/theories/examples/refinements/derived.v
deleted file mode 100644
index 931dfa3b6a8dce9d7d5f056e69e205367b5a8e0d..0000000000000000000000000000000000000000
--- a/theories/examples/refinements/derived.v
+++ /dev/null
@@ -1,124 +0,0 @@
-
-From iris.program_logic.refinement Require Export ref_weakestpre ref_adequacy seq_weakestpre.
-From iris.examples.refinements Require Export refinement.
-From iris.algebra Require Import auth.
-From iris.heap_lang Require Import proofmode notation.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-
-(* We illustrate here how to derive the rules shown in the paper *)
-
-
-Section derived.
-  Context {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)} `{!seqG Σ}.
-
-  Definition seq_rswp E e φ : iProp Σ := (na_own seqG_name E -∗ RSWP e at 0 ⟨⟨ v, na_own seqG_name E ∗ φ v ⟩⟩)%I.
-  Notation "⟨⟨ P ⟩ ⟩ e ⟨⟨ v , Q ⟩ ⟩" := (□ (P -∗ (seq_rswp ⊤ e (λ v, Q))))%I
-  (at level 20, P, e, Q at level 200, format "⟨⟨  P  ⟩ ⟩  e  ⟨⟨  v ,  Q  ⟩ ⟩") : stdpp_scope.
-  Notation "{{ P } } e {{ v , Q } }" := (□ (P -∗ SEQ e ⟨⟨ v, Q ⟩⟩))%I
-  (at level 20, P, e, Q at level 200, format "{{  P  } }  e  {{  v ,  Q  } }") : stdpp_scope.
-
-
-  Lemma Value (v: val): (⊢ {{True}} v {{w, ⌜v = w⌝}})%I.
-  Proof.
-    iIntros "!> _ $". by iApply rwp_value.
-  Qed.
-
-  Lemma Frame (e: expr) P R Q: ({{P}} e {{v, Q v}} ⊢ {{P ∗ R}} e {{v, Q v ∗ R}})%I.
-  Proof.
-    iIntros "#H !> [P $]". by iApply "H".
-  Qed.
-
-  Lemma Bind (e: expr) K P Q R:
-    ({{P}} e {{v, Q v}} ∗ (∀ v: val, ({{Q v}} fill K (Val v) {{w, R w}}))
-    ⊢ {{P}} fill K e {{v, R v}})%I.
-  Proof.
-    iIntros "[#H1 #H2] !> P Hna".
-    iApply rwp_bind. iSpecialize ("H1" with "P Hna").
-    iApply (rwp_strong_mono with "H1 []"); auto.
-    iIntros (v) "[Hna Q] !>". iApply ("H2" with "Q Hna").
-  Qed.
-
-  Lemma Löb (P : iPropI Σ) : (▷ P → P) ⊢ P.
-  Proof. iApply bi.löb. Qed.
-
-  Lemma TPPureT (e e': expr) P Q: pure_step e e' → ({{P}} e' {{v, Q v}} ⊢ ⟨⟨P⟩⟩ e ⟨⟨v, Q v⟩⟩)%I.
-  Proof.
-    iIntros (Hstep) "#H !> P Hna".
-    iApply (ref_lifting.rswp_pure_step_later _ _ _ _ _ True); [|done|by iApply ("H" with "P Hna")].
-    intros _. apply nsteps_once, Hstep.
-  Qed.
-
-  Lemma TPPureS (e e' et: expr) K P Q:
-    to_val et = None
-    → pure_step e e'
-    → (⟨⟨src (fill K e') ∗ P⟩⟩ et ⟨⟨v, Q v⟩⟩ ⊢ {{src (fill K e) ∗ ▷ P}} et {{v, Q v}})%I.
-  Proof.
-    iIntros (Hexp Hstep) "#H !> [Hsrc P] Hna". iApply (rwp_take_step with "[P Hna] [Hsrc]"); first done; last first.
-    - iApply step_pure; last iApply "Hsrc". apply pure_step_ctx; last done. apply _.
-    - iIntros "Hsrc'". iApply rswp_do_step. iNext. iApply ("H" with "[$P $Hsrc'] Hna").
-  Qed.
-
-  Lemma TPStoreT l (v1 v2: val): (True ⊢ ⟨⟨l ↦ v1⟩⟩ #l <- v2 ⟨⟨w, ⌜w = #()⌝ ∗ l ↦ v2⟩⟩)%I.
-  Proof.
-    iIntros "_ !> Hl $". iApply (rswp_store with "[$Hl]").
-    by iIntros "$".
-  Qed.
-
-  Lemma TPStoreS (et: expr) l v1 v2 K P Q:
-    to_val et = None
-    → (⟨⟨P ∗ src (fill K (Val #())) ∗ l ↦s v2⟩⟩ et ⟨⟨v, Q v⟩⟩
-      ⊢ {{src (fill K (#l <- v2)) ∗ l ↦s v1 ∗ ▷ P}} et {{v, Q v}})%I.
-  Proof.
-    iIntros (Hexp) "#H !> [Hsrc [Hloc P]] Hna". iApply (rwp_take_step with "[P Hna] [Hsrc Hloc]"); first done; last first.
-    - iApply step_store. iFrame.
-    - iIntros "Hsrc'". iApply rswp_do_step. iNext. iApply ("H" with "[$P $Hsrc'] Hna").
-  Qed.
-
-  Lemma TPStutterT (e: expr) P Q: to_val e = None → (⟨⟨P⟩⟩ e ⟨⟨v, Q v⟩⟩ ⊢ {{P}} e {{v, Q v}})%I.
-  Proof.
-    iIntros (H) "#H !> P Hna". iApply rwp_no_step; first done.
-    by iApply ("H" with "P Hna").
-  Qed.
-
-  Lemma TPStutterSStore (et : expr) v1 v2 K l P Q : 
-    to_val et = None
-    → {{P ∗ src (fill K (Val #())) ∗ l ↦s v2}} et {{v, Q v}} 
-    ⊢ {{l ↦s v1 ∗ src (fill K (#l <- v2)) ∗ P}} et {{v, Q v}}. 
-  Proof. 
-    iIntros (Hv) "#H !> [Hloc [Hsrc P]] Hna". 
-    iApply (rwp_weaken with "[H Hna] [P Hloc Hsrc]"); first done.
-    - instantiate (1 := (P ∗ src (fill K #()) ∗ l ↦s v2)%I). 
-      iIntros "H1". iApply ("H" with "[H1] [Hna]"); done. 
-    - iApply src_update_mono. iSplitL "Hsrc Hloc". 
-      iApply step_store. by iFrame. 
-      iIntros "[H0 H1]". by iFrame.
-  Qed. 
-
-  Lemma TPStutterSPure (et es es' : expr) P Q : 
-    to_val et = None
-    → pure_step es es'
-    → {{ P ∗ src(es') }} et {{v, Q v}}
-      ⊢ {{ P ∗ src(es)}} et {{v, Q v}}.
-  Proof. 
-    iIntros (H0 H) "#H !> [P Hsrc] Hna".
-    iApply (rwp_weaken with "[H Hna] [P Hsrc]"); first done. 
-    - instantiate (1 := (P ∗ src es')%I). iIntros "H1". 
-      by iApply ("H" with "[H1] Hna"). 
-    - iApply src_update_mono. iSplitL "Hsrc". 
-      by iApply step_pure. iIntros "?"; by iFrame. 
-  Qed.  
-
-  Lemma HoareLöb X P Q e : 
-    (∀ x :X, {{P x ∗ ▷ (∀ x, {{P x}} e {{v, Q x v}})}} e {{ v, Q x v}})
-    ⊢ ∀ x, {{ P x }} e {{v, Q x v}}. 
-  Proof. 
-    iIntros "H". iApply bi.löb. 
-    iIntros "#H1" (x). 
-    (*iIntros "H0".*)
-    (*iSpecialize ("H" with x). *)
-    (*iApply ("H"). iModIntro.*)
-  Abort. 
-
-End derived.
diff --git a/theories/examples/refinements/memoization.v b/theories/examples/refinements/memoization.v
deleted file mode 100644
index 3dc4e2476deb7ab5cebbffdb56b252559aa4b4db..0000000000000000000000000000000000000000
--- a/theories/examples/refinements/memoization.v
+++ /dev/null
@@ -1,1914 +0,0 @@
-
-From iris.program_logic.refinement Require Export ref_weakestpre ref_source seq_weakestpre.
-From iris.base_logic.lib Require Export invariants na_invariants.
-From iris.examples.refinements Require Export refinement.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation metatheory.
-From iris.algebra Require Import auth gmap excl frac agree.
-Set Default Proof Using "Type".
-
-Definition refN := nroot .@ "ref".
-
-Lemma fill_item_injective a (e e': expr): fill_item a e = fill_item a e' → e = e'.
-Proof.
-  induction a; simpl; injection 1; eauto.
-Qed.
-
-Lemma fill_injective K (e e': expr): fill K e = fill K e' → e = e'.
-Proof.
-  revert e e'; induction K; intros e e'; simpl; eauto.
-  intros ? % IHK. by eapply fill_item_injective.
-Qed.
-
-Definition eq_heaplang : val := (λ: "n1" "n2", "n1" = "n2").
-
-Notation exec := (tc (@pure_step heap_lang)).
-
-Section map_simple.
-
-  Context {SI: indexT} {A: Type} `{Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A}.
-  Context (Comparable: val → iProp Σ).
-  Context `{Comparable_timeless: ∀ v, Timeless (Comparable v)}.
-
-  Fixpoint contents (kvs: list (val * val)) (l: loc) : iProp Σ :=
-    (match kvs with
-    | nil => l ↦ NONEV
-    | (k, n) :: kvs' => ∃(l': loc), Comparable k ∗ l ↦ SOMEV ((k, n), #l') ∗ contents kvs' l'
-    end)%I.
-
-  Global Instance contents_timeless kvs l: Timeless (contents kvs l).
-  Proof using Comparable_timeless.
-    revert l; induction kvs as [|[] kvs IH]; intros l; simpl; apply _.
-  Qed.
-  Definition map : val :=
-    λ: <>, ref (ref NONE).
-
-  Definition get : val :=
-    λ: "m" "eq" "a",
-    (rec: "get" "h" "a" :=
-      match: !"h" with
-        NONE => NONE
-      | SOME "p" =>
-        let: "kv" := Fst "p" in
-        let: "next" := Snd "p" in
-        if: "eq" (Fst "kv") "a" then SOME (Snd "kv") else "get" "next" "a"
-      end) (!"m") "a".
-
-  Definition set : val :=
-    λ: "h" "a" "v",
-      "h" <- ref (SOME (("a", "v"), !"h")).
-
-  Fixpoint to_map (kvs: list (val * val)) : gmap val val :=
-    match kvs with
-    | nil => ∅
-    | (k, n) :: kvs => <[k := n]> (to_map kvs)
-    end.
-
-  Definition Map v (h: gmap val val) :=
-    (∃ (l l': loc) kvs, ⌜v = #l⌝ ∗ ⌜h = to_map kvs⌝ ∗ l ↦ #l' ∗ contents kvs l')%I.
-
-  Global Instance Map_timeless v h: Timeless (Map v h).
-  Proof using Comparable_timeless. apply _. Qed.
-
-  Lemma map_spec: ⊢ ⟨⟨⟨ True ⟩⟩⟩ map #() ⟨⟨⟨ v, RET v; Map v ∅ ⟩⟩⟩.
-  Proof.
-    iModIntro; iIntros (Φ) "_ Hpost". rewrite /map. wp_pures.
-    wp_alloc r as "Hr". wp_alloc h as "Hh".
-    iApply "Hpost".
-    iExists h, r, nil; simpl; iFrame; iSplit; done.
-  Qed.
-
-  Definition embed (o: option val) :=
-    match o with
-    | None => NONEV
-    | Some k => SOMEV k
-    end.
-
-  Definition eqfun (eq : val) (Q: val → val → iProp Σ) :=
-    (∀ n1 n2,
-    ⟨⟨⟨ Comparable n1 ∗ Comparable n2 ⟩⟩⟩ eq n1 n2
-    ⟨⟨⟨ b, RET #(b: bool); Comparable n1 ∗ Comparable n2 ∗
-        match b with
-        | true => Q n1 n2
-        | _ => Q n1 n2 -∗ False
-        end ⟩⟩⟩)%I.
-
-  Lemma get_spec h eq Q m (n: val) :
-    ⊢ ⟨⟨⟨ Map m h ∗ eqfun eq Q ∗ Comparable n ⟩⟩⟩ get m eq n
-      ⟨⟨⟨ o, RET (embed o);
-          match o with
-          | Some v => ∃ n', ⌜ h !! n' = Some v ⌝ ∗ Q n' n ∗ Map m h
-          | None => (∀ n', ⌜ n' ∈ dom (gset val) h ⌝ -∗ Q n' n -∗ False) ∗ Map m h
-          end ⟩⟩⟩.
-  Proof using Comparable_timeless.
-    iModIntro; iIntros (Φ) "(HM&#Heq&Hcompn) Hpost". rewrite /get {1}/Map.
-    wp_pures. iDestruct "HM" as (l r kvs -> ->) "[Hr Hc]".
-    wp_load.
-    (* we prepare the goal for the induction *)
-    iAssert (∀ o, contents kvs r -∗
-              match o with
-              | Some v => ∃ n' : val, ⌜to_map kvs !! n' = Some v⌝ ∗ Q n' n
-              | None => (∀ n', ⌜ n' ∈ dom (gset val) (to_map kvs) ⌝ -∗ Q n' n -∗ False)
-              end -∗ Φ (embed o))%I with "[Hr Hpost]" as "Hpost".
-    { iIntros (o) "H1 H2". iApply "Hpost". destruct o.
-      - iDestruct "H2" as (n') "(?&?)".
-        iExists n'. iFrame. iExists l, r, kvs; iFrame; done.
-      - iFrame. iExists l, r, kvs; iFrame; done.
-    }
-    wp_pure _. iInduction kvs as [|[k n'] kvs] "IH" forall (r) "Hc"; simpl.
-    - wp_pures. wp_load. wp_pures.
-      iApply ("Hpost" $! None with "[$]").
-      iIntros (? Hin) "_". iPureIntro. set_solver.
-    - iDestruct "Hc" as (l') "[Hcompk [Hr Hc]]". wp_pures.
-      wp_load. wp_pures.
-      wp_bind (eq k n).
-      wp_apply ("Heq" with "[$Hcompk $Hcompn]").
-      iIntros (b) "(Hcompk&Hcompn&Hif)".
-      destruct b.
-      + wp_pures. subst.
-        iApply ("Hpost" $! (Some n') with "[Hcompk Hr Hc]").
-        { iExists _; iFrame. }
-        iExists k. rewrite lookup_insert.
-        eauto.
-      + wp_pure _. iApply ("IH" $! l' with "[$] [Hpost Hr Hcompk Hif] Hc").
-        iIntros (o) "Hc H". iApply ("Hpost" with "[Hr Hcompk Hc] [H Hif]").
-        { iExists _. iFrame. }
-        { destruct o.
-          * iDestruct "H" as (k') "(Heq'&HQ)".
-            iAssert (⌜k' ≠ k⌝)%I with "[-]" as %Hneq.
-            { iIntros (->). by iApply "Hif". }
-            iExists k'. rewrite lookup_insert_ne //. iFrame.
-          * iIntros (? Hin) "HQ".
-            set_unfold in Hin. destruct Hin as [->|Hin].
-            + by iApply "Hif".
-            + by iApply "H".
-        }
-  Qed.
-
-  Lemma set_spec h m (n k: val) :
-    ⊢ ⟨⟨⟨ Map m h ∗ Comparable k ⟩⟩⟩ set m k n ⟨⟨⟨ RET #(); Map m (<[k := n]> h) ⟩⟩⟩.
-  Proof.
-    iModIntro; iIntros (Φ) "(HM&Hcomp) Hpost". rewrite /set /Map.
-    wp_pures. iDestruct "HM" as (l r kvs -> ->) "[Hr Hc]".
-    wp_load. wp_alloc r' as "Hr'". wp_store.
-    iApply "Hpost". iExists l, r', ((k, n) :: kvs); simpl; iFrame; repeat iSplit; auto.
-    iExists r. iFrame.
-  Qed.
-
-End map_simple.
-
-
-Section memoization_functions.
-  Definition memoize: val :=
-    λ: "eq" "f",
-      let: "h" := map #() in
-      λ: "a",
-      match: get "h" "eq" "a" with
-        NONE => let: "y" := "f" "a" in set "h" "a" "y";; "y"
-      | SOME "y" => "y"
-      end.
-
-
-  Definition mem_rec: val :=
-    λ: "eq" "F",
-    let: "h" := map #() in
-    rec: "mem_rec" "a" :=
-      match: get "h" "eq" "a" with
-        NONE =>
-          let: "y" := "F" "mem_rec" "a" in
-          set "h" "a" "y";; "y"
-      | SOME "y" => "y"
-      end.
-End memoization_functions.
-
-
-
-
-
-Section timeless_memoization.
-  Context {SI: indexT} {A: Type} `{Σ: gFunctors SI} `{Heap: !rheapG Σ} `{Cred: !auth_sourceG Σ (natA SI)} `{Seq: !seqG Σ}.
-
-
-  Implicit Types (c: nat).
-  Implicit Types (f g m v: val).
-  Implicit Types (e: expr).
-  Implicit Types (h: gmap val val).
-
-
-  Variable (R: expr → val → iProp Σ).
-  Variable (Pre Post: val → val → iProp Σ).
-  Variable (Comparable: val → iProp Σ).
-  Variable (Eq: val → val → iProp Σ).
-  Context `{TL: !∀ e v, Timeless (R e v)}.
-  Context `{TLPost: !∀ v v', Timeless (Post v v')}.
-  Context `{PPre: !∀ v v', Persistent (Pre v v')}.
-  Context `{PPost: !∀ v v', Persistent (Post v v')}.
-  Context `{PEq: !∀ v v', Persistent (Eq v v')}.
-  Context `{Comparable_timeless: ∀ v, Timeless (Comparable v)}.
-  Variable (Pre_Comparable : ∀ v v', Pre v v' -∗ Comparable v).
-  Variable (Pre_Eq_Proper: ∀ v1 v1' v2, Eq v1 v1' -∗ Pre v1' v2 -∗ Pre v1 v2).
-
-  (* we allow arbitrary stutter *)
-  Definition eval e v := (∀ K, src (fill K e) -∗ src_update ⊤ (src (fill K v)))%I.
-  Definition mem_inv (m f: val) : iProp Σ :=
-    (∃ h, Map Comparable m h ∗
-          [∗ map] k ↦ v ∈ h, □ (∀ k', Pre k k' -∗ ∃ v', □ R (f (of_val k')) v' ∗ Post v v'))%I.
-
-  Definition implements (g: val) (f: val) : iProp Σ :=
-    (□ ∀ x x' K,
-          Pre x x' -∗
-          src (fill K (f x')) -∗
-          SEQ (g x) ⟨⟨v, ∃ v': val, Post v v' ∗ src (fill K v') ∗
-                                    □ (∀ x', Pre x x' -∗ ∃ v', □ R (f x') v' ∗ Post v v') ⟩⟩)%I.
-
-
-  Lemma memoization_core (eq: val) (f: val) e (n n' : val) m K :
-    SEQ e ⟨⟨ h, implements h f ⟩⟩ ∗
-    se_inv refN (mem_inv m f) ∗
-    □ (∀ e v, R e v -∗ eval e v) ∗
-    Pre n n' ∗
-    eqfun Comparable eq Eq ∗
-    src (fill K (f n')) ⊢
-    SEQ (match: get m eq n with
-      NONE => let: "y" := e n in set m n "y";; "y"
-    | SOME "y" => "y"
-    end) ⟨⟨v, ∃ v': val, Post v v' ∗ src (fill K v') ∗ □ (∀ n', Pre n n' -∗ ∃ v', □ R (f n') v' ∗ Post v v') ⟩⟩.
-  Proof using Comparable Comparable_timeless Cred Eq Heap PEq PPost PPre Post Pre Pre_Comparable Pre_Eq_Proper R SI
-        Seq TL TLPost Σ.
-    iIntros "(Spec & #I & #IEval & #HPre & #Heqfun & Hsrc) Hna".
-    (* we open the timeless invariant for the get *)
-    iMod (na_inv_acc_open_timeless with "I Hna") as "(Hc & Hna & Hclose)"; auto.
-    iDestruct "Hc" as (h) "(HM & #Hupd)".
-    wp_bind (get m eq n). wp_apply (get_spec with "[$HM $Heqfun]").
-    { by iApply Pre_Comparable. }
-    iIntros (o) "HM".
-    destruct o as [k|] eqn: Heq.
-    - (* we have stored this result before *)
-      iDestruct "HM" as (n0 Hlookup) "(#Heq&HM)".
-      iDestruct (big_sepM_lookup with "Hupd") as "#Hk"; first done.
-      iDestruct (Pre_Eq_Proper with "[$] [$]") as "#HPre'".
-      iDestruct ("Hk" with "[$]") as (?) "(#HR&#HP)".
-      iApply (rwp_weaken with "[-Hsrc] [Hsrc]"); first done; last by iApply "IEval".
-      iIntros "Hsrc".
-      iApply fupd_rwp. iMod ("Hclose" with "[HM $Hna]") as "Hna".
-      { iNext. iExists h. by iFrame. }
-      iModIntro. wp_pures.
-      iFrame. iExists _. iFrame "# ∗".
-      iIntros "!>" (n'') "HPre''".
-      iApply "Hk". iApply (Pre_Eq_Proper with "[$] [$]").
-    - (* we close the invariant again for the recursive call *)
-      iDestruct "HM" as "(Hnin&HM)".
-      iMod ("Hclose" with "[HM $Hna]") as "Hna".
-      { iNext. iExists _. iFrame "# ∗". }
-      wp_pures. wp_bind e.
-      iApply (rwp_strong_mono with "[Spec Hna]");[eauto..| by iApply "Spec" |].
-      iIntros (g) "[Hna Hres] !>"; simpl.
-      iSpecialize ("Hres" with "HPre Hsrc Hna").
-      wp_bind (g _). iApply (rwp_wand with "Hres []").
-      iIntros (v) "[Hna Hres]". iDestruct "Hres" as (k) "(#HPost & Hsrc & #Hk)".
-      iMod (na_inv_acc_open_timeless with "I Hna") as "(Hc & Hna & Hclose)"; auto.
-      iDestruct "Hc" as (h2) "(HM & #Hupd')".
-      wp_pures. wp_apply (set_spec with "[$HM]").
-      { by iApply Pre_Comparable. }
-      iIntros "HM".
-      iApply fupd_rwp. iMod ("Hclose" with "[HM $Hna]") as "Hna".
-      { iNext. iExists (<[n:=_]> h2). iFrame.
-        iApply big_sepM_insert_2; simpl; auto.
-      }
-      iModIntro. wp_pures. iFrame.
-      iExists k. iFrame. iFrame "#".
-  Qed.
-
-
-  Lemma memoize_spec eq (f g: val):
-    eqfun Comparable eq Eq ∗
-    implements g f ∗
-    □ (∀ (e : expr) (v : val), R e v -∗ eval e v)
-    ⊢ SEQ (memoize eq g) ⟨⟨ h, implements h f ⟩⟩.
-  Proof using Comparable Comparable_timeless Cred Eq Heap PEq PPost PPre Post Pre Pre_Comparable Pre_Eq_Proper R SI
-        Seq TL TLPost Σ.
-    iIntros "[#Heq [#H #R]] Hna". rewrite /memoize. wp_pures. iFrame.
-    wp_apply map_spec; first done. iIntros (m) "Hm".
-    iMod (na_inv_alloc seqG_name ⊤ refN (mem_inv m f) with "[Hm]") as "#IM".
-    { iNext. iExists ∅. iFrame. rewrite big_sepM_empty; done. }
-    wp_pures. iFrame.
-
-    iModIntro; iIntros (n n' K) "#HPre Hsrc Hna".
-    wp_pure _.
-    iDestruct (Pre_Comparable with "HPre") as "Hcomp".
-    iApply (memoization_core with "[-Hna] [$Hna]").
-      iFrame "IM Hsrc R HPre Heq". iIntros "Hna". wp_value_head. iFrame.
-      iApply "H".
-  Qed.
-
-  Lemma mem_rec_spec eq (F f: val):
-      eqfun Comparable eq Eq ∗
-      (□ ∀ g, ▷ implements g f -∗ SEQ (F g) ⟨⟨h, implements h f⟩⟩) ∗
-      □ (∀ (e : expr) (v : val), R e v -∗ eval e v) ⊢
-      SEQ (mem_rec eq F) ⟨⟨ h, implements h f ⟩⟩.
-  Proof using Comparable Comparable_timeless Cred Eq Heap PEq PPost PPre Post Pre Pre_Comparable Pre_Eq_Proper R SI
-        Seq TL TLPost Σ.
-    iIntros "[#Heq [#H #R]] Hna". rewrite /mem_rec. wp_pures. iFrame.
-    wp_apply map_spec; first done. iIntros (m) "Hm".
-    iMod (na_inv_alloc seqG_name ⊤ refN (mem_inv m f) with "[Hm]") as "#IM".
-    { iNext. iExists ∅. iFrame. rewrite big_sepM_empty; done. }
-    wp_pures. iFrame.
-
-    iLöb as "IH". iModIntro. iIntros (n n' K) "#HPre Hsrc Hna".
-    wp_pure _.
-    iDestruct (Pre_Comparable with "HPre") as "Hcomp".
-    iApply (memoization_core with "[-Hna] [$Hna]").
-    iFrame "IM Hsrc R HPre Heq". iApply "H". iApply "IH".
-  Qed.
-
-End timeless_memoization.
-
-Section pure_nat_memoization.
-  Context {SI: indexT} {A: Type} `{Σ: gFunctors SI} `{Heap: !rheapG Σ} `{Cred: !auth_sourceG Σ (natA SI)} `{Seq: !seqG Σ}.
-
-
-  Implicit Types (c: nat).
-  Implicit Types (f g m v: val).
-  Implicit Types (e: expr).
-  Implicit Types (h: gmap val val).
-
-  Definition natRel (v1 v2: val) : iProp Σ :=
-    (∃ n : nat, ⌜ v1 = #n ∧ v2 = #n ⌝)%I.
-
-  Lemma lookup_O {X: Type} (l: list X) (x: X):
-    l !! O = Some x →
-    ∃ l', l = x :: l'.
-  Proof.
-    destruct l as [| a l']; rewrite ?lookup_nil; try congruence => //=.
-    rewrite /=. intros. exists l'. congruence.
-  Qed.
-
-  Definition execV (e: expr) (v: val) : iProp Σ := (⌜exec e v⌝)%I.
-
-  Lemma pure_exec_exec e1 e2 n φ: PureExec φ (S n) e1 e2 → φ → exec e1 e2.
-  Proof.
-    intros HP Hφ. specialize (HP Hφ); remember (S n) as m; revert n Heqm.
-    induction HP as [|n e1 e2 e3 Hstep Hsteps]; first naive_solver.
-    injection 1 as <-. destruct n as [|n].
-    - inversion Hsteps; subst. eapply tc_once, Hstep.
-    - eapply tc_l; naive_solver.
-  Qed.
-
-  Lemma exec_frame e1 e2 K: exec e1 e2 → exec (fill K e1) (fill K e2).
-  Proof.
-    induction 1.
-    - eapply tc_once, pure_step_ctx; eauto. apply _.
-    - etrans; eauto.
-      eapply tc_once, pure_step_ctx; eauto. apply _.
-  Qed.
-
-  Lemma exec_src_update e1 e2 j E: exec e1 e2 → j ⤇ e1 ⊢ src_update E (j ⤇ e2).
-  Proof.
-    induction 1.
-    - by apply step_pure.
-    - iIntros "H". iApply src_update_bind. iSplitL.
-      + iApply step_pure; eauto.
-      + iApply IHtc.
-  Qed.
-
-  Lemma rtc_r_or_tc {X: Type} (R: relation X) x y:
-    rtc R x y → x = y ∨ tc R x y.
-  Proof.
-    induction 1.
-    - by left.
-    - right. destruct IHrtc.
-      * subst. by apply tc_once.
-      * eapply tc_l; eauto.
-  Qed.
-
-  Definition natfun_refines (g: val) (f: val) : iProp Σ :=
-    (□ ∀ (n : nat) K,
-          src (fill K (f #n)) -∗
-          SEQ (g #n) ⟨⟨v, ∃ n': nat, ⌜ v = #n' ⌝ ∗ src (fill K v) ⟩⟩)%I.
-
-  Definition natfun_pure (f: val) :=
-    ∀ (n1 n2 : nat) tp1 tp2 σ1 σ2 K,
-      rtc erased_step (fill K (f #n1) :: tp1, σ1) (fill K (#n2) :: tp2, σ2) →
-      (∀ K', rtc pure_step (fill K' (f #n1)) (fill K' (#n2))).
-
-  Lemma natfun_mem_rec_spec (F f: val):
-      natfun_pure f →
-      (□ ∀ g, ▷ natfun_refines g f -∗ SEQ (F g) ⟨⟨h, natfun_refines h f⟩⟩) ⊢
-      SEQ (mem_rec eq_heaplang F) ⟨⟨ h, natfun_refines h f ⟩⟩.
-  Proof.
-    iIntros (Hpure) "#Href".
-    iIntros "Hna".
-    iPoseProof (mem_rec_spec
-                  (λ e v, ∃ K (n1 n2: nat) tp1 tp2 σ1 σ2, ⌜ e = (f #n1) ∧ v = #n2 ∧
-                    rtc erased_step (fill K (f #n1) :: tp1, σ1) (fill K (#n2) :: tp2, σ2)⌝)%I
-                  natRel natRel
-                  (λ x, ⌜ val_is_unboxed x ⌝)%I (λ x1 x2, ⌜ x1 = x2 ⌝)%I
-                  with "[] [$Hna]") as "H"; last first.
-    { iApply (rwp_mono with "H").
-      iIntros  (?) "($&#H)". rewrite /implements /natfun_refines.
-      iIntros "!>" (n K) "Hsrc Hna".
-      iSpecialize ("H" $! #n with "[] [$] [$]"); first eauto.
-      iApply (rwp_mono with "H").
-      iIntros (?) "($&Hrel)".
-      iDestruct "Hrel" as (? (n'&->&->)) "(Hsrc&_)".
-      iExists n'. eauto.
-    }
-    { iSplit.
-      {
-        rewrite /eqfun. iIntros (??) "!>". iIntros (Φ) "(%&%) H".
-        rewrite /eq_heaplang. wp_pures.
-        wp_pure _; first (rewrite /vals_compare_safe; eauto).
-        iApply "H". iFrame "%". rewrite /bool_decide. destruct (decide_rel _); eauto.
-      }
-      iSplit.
-      * iModIntro.
-        iIntros (g) "Himpl Hna".
-        iSpecialize ("Href" $! g with "[Himpl] [$]").
-        {
-          iNext. iDestruct "Himpl" as "#Himpl". iIntros (n K) "!> H Hna".
-          iSpecialize ("Himpl" with "[] [$] [$]"); eauto.
-          iApply (rwp_wand with "Himpl").
-          iIntros (?) "($&H)".
-          iDestruct "H" as (? (n'&Heq1&Heq2)) "(Hsrc&_)".
-          subst; eauto.
-        }
-        iApply (rwp_wand with "Href").
-        iIntros (?) "($&#Hnatfun)".
-        rewrite /implements.
-        iIntros (?? K) "!> H Hsrc Hna".
-        iApply (rwp_weaken' with "[-Hsrc]"); first done; last first.
-        { iApply (src_log with "[$]"). }
-        iIntros "(Hsrc&Hlog)".
-        iDestruct "Hlog" as (tp σ i Hlookup) "#Hfmlist".
-        iDestruct "H" as %[n [-> ->]].
-        iSpecialize ("Hnatfun" with "[$] [$]").
-        iApply rwp_fupd'.
-        iApply (rwp_wand with "Hnatfun").
-        iIntros (?) "($&H)".
-        iIntros (???) "(Hinterp&Hstate)".
-        iDestruct "H" as (n' ?) "Hsrc".
-        iDestruct (src_get_trace' with "[$]") as "(Hsrc&Hinterp&Hin)".
-        iDestruct "Hin" as %(?&σ'&Hlookup'&Hrtc).
-        iFrame. iModIntro.
-        iExists #n'.
-        subst.
-        iSplit; first eauto.
-        iSplit; first eauto.
-        iModIntro. iIntros (?) "H".
-        iDestruct "H" as %(?&Heq1&Heq2); subst.
-        inversion Heq1 as [Heq].
-        iExists #n'. iSplit; eauto.
-        iModIntro.
-        apply lookup_O in Hlookup as (tp1'&->).
-        apply lookup_O in Hlookup' as (tp2'&->).
-        iExists _, _, _, _, _,
-        {| heap := fst σ; used_proph_id := {| mapset.mapset_car := snd σ |}|},
-        {| heap := fst σ'; used_proph_id := {| mapset.mapset_car := snd σ' |}|}.
-        iPureIntro.
-        split_and!; eauto. rewrite /to_cfg in Hrtc. destruct σ, σ'. eapply Hrtc.
-      * iModIntro. iIntros (e v) "H".
-        iDestruct "H" as (K n1 n2 tp1 tp2 σ1 σ2) "H".
-        iDestruct "H" as %(Heq1&Heq2&Hrtc).
-        rewrite /eval.
-        iIntros (K') "Hsrc".
-        iApply (exec_src_update with "[$]").
-        subst.
-        apply Hpure in Hrtc. specialize (Hrtc K').
-        apply rtc_r_or_tc in Hrtc as [Hr|Htc]; last eauto.
-        { apply fill_injective in Hr. congruence. }
-    }
-    { iIntros (??? -> Hrel). iPureIntro. destruct Hrel as (x&->&->). eauto. }
-    { iIntros (?? (n'&->&->)). eauto. }
-  Qed.
-
-End pure_nat_memoization.
-
-Section repeatable_refinements.
-  Context {SI: indexT} {A: Type} `{Σ: gFunctors SI} `{Heap: !rheapG Σ} `{Cred: !auth_sourceG Σ (natA SI)} `{Sync: !inG Σ (authR (optionUR (exclR (gmapO val (valO SI)))))} `{Seq: !seqG Σ}.
-
-
-  Implicit Types (c: nat).
-  Implicit Types (f g m v: val).
-  Implicit Types (e: expr).
-  Implicit Types (h: gmap val val).
-  Variable (Pre Post: val → val → iProp Σ).
-  Variable (Comparable: val → iProp Σ).
-  Variable (Eq: val → val → iProp Σ).
-  Context `{PPre: !∀ v v', Persistent (Pre v v')}.
-  Context `{PPost: !∀ v v', Persistent (Post v v')}.
-  Context `{PEq: !∀ v v', Persistent (Eq v v')}.
-  Context `{Comparable_timeless: ∀ v, Timeless (Comparable v)}.
-  Variable (Pre_Comparable : ∀ v v', Pre v v' ={⊤}=∗ Comparable v).
-  Variable (Pre_Eq_Proper: ∀ v1 v1' v2, Eq v1 v1' -∗ Pre v1' v2 -∗ Pre v1 v2).
-
-
-  (* we allow arbitrary stutter *)
-  Definition mem_rec_tl_inv γ m : iProp Σ := (∃ h, Map Comparable m h ∗ own γ (● Excl' h) ∗ $ (1%nat))%I.
-  Definition mem_rec_tf_inv γ (f: val) : iProp Σ :=
-    (∃ h, own γ (◯ Excl' h) ∗ [∗ map] k ↦ v ∈ h, □ (∀ k', Pre k k' -∗ ∃ v', □ eval (f k') v' ∗ Post v v'))%I.
-
-  Definition tf_implements (g: val) (f: val) : iProp Σ :=
-    (□ ∀ x x' c K,
-          Pre x x' -∗
-          src (fill K (f x')) -∗
-          SEQ (g x) ⟨⟨v, ∃ v': val, Post v v' ∗ $c ∗ src (fill K v') ∗
-                                    □ (∀ x', Pre x x' -∗ ∃ v', □ eval (f x') v' ∗ Post v v') ⟩⟩)%I.
-
-  Lemma tf_memoization_core `{FiniteBoundedExistential SI} (eq: val) (f: val) e c γ (n n' : val) m K :
-    SEQ e ⟨⟨ h, tf_implements h f ⟩⟩ ∗
-    se_inv (refN .@ "tl") (mem_rec_tl_inv γ m) ∗
-    se_inv (refN .@ "tf") (mem_rec_tf_inv γ f) ∗
-    Pre n n' ∗
-    eqfun Comparable eq Eq ∗
-    src (fill K (f n')) ⊢
-    SEQ (match: get m eq n with
-      NONE => let: "y" := e n in set m n "y";; "y"
-    | SOME "y" => "y"
-    end) ⟨⟨v, ∃ v': val, Post v v' ∗ $c ∗ src (fill K v') ∗ □ (∀ n', Pre n n' -∗ ∃ v', □ eval (f n') v' ∗ Post v v') ⟩⟩.
-  Proof using Comparable Comparable_timeless Cred Eq Heap PEq PPost PPre Post Pre Pre_Comparable Pre_Eq_Proper SI
-              Seq Sync Σ.
-    iIntros "(Spec & #IM & #IC & #HPre & #Heqfun & Hsrc) Hna".
-    (* we open the timeless invariant for the get *)
-    iMod (na_inv_acc_open_timeless with "IM Hna") as "(Hc & Hna & Hclose1)"; auto.
-    iDestruct "Hc" as (h) "(HM & H● & Hone)".
-    wp_bind (get m eq n).
-    iMod (Pre_Comparable with "HPre") as "HComp".
-    wp_apply (get_spec with "[$HM $Heqfun $HComp]").
-    iIntros (o) "HM".
-    destruct o as [k|] eqn: Heq.
-    - (* we have stored this result before *)
-      iDestruct "HM" as (n0 Hlookup) "(#Heq&HM)".
-      iMod (na_inv_acc_open with "IC Hna") as "Hcache"; auto; first solve_ndisj.
-      iApply (rwp_take_step with "[-Hone] [Hone]"); first done; last first.
-      { iApply step_stutter. iFrame. } iIntros "_".
-      iApply rswp_do_step. iNext; simpl. iDestruct "Hcache" as "(HsrcI & Hna & Hclose2)".
-      iDestruct "HsrcI" as (h') "[H◯ #Hupd]".
-      iDestruct (own_valid_2 with "H● H◯") as % [->%Excl_included%leibniz_equiv _]%auth_both_valid.
-      wp_pure _.
-      iDestruct (big_sepM_lookup with "Hupd") as "#Hk"; first done.
-      iDestruct ("Hk" with "[]") as (?) "(#Heval&#HP)".
-      { iApply (Pre_Eq_Proper with "[$] [$]"). }
-      iApply (rwp_weaken with "[-Hsrc] [Hsrc]"); first done; last first.
-      { iApply (step_inv_alloc (S c) with "[] Hsrc"); iSplitL; first iApply "Heval".
-        iIntros "Hsrc". iExists (fill K _). iFrame. iPureIntro. intros ? % fill_injective; discriminate. }
-      rewrite nat_srcF_succ. iIntros "(Hsrc & Hone & Hc)".
-      iApply fupd_rwp. iMod ("Hclose2" with "[H◯ $Hna]") as "Hna".
-      { iNext. iExists h. iFrame. done. }
-      iMod ("Hclose1" with "[H● HM $Hna Hone]") as "Hna".
-      { iNext. iExists h. iFrame. }
-      iModIntro. wp_pures.
-      iFrame. iExists _. iFrame "# ∗".
-      iIntros "!>" (n'') "HPre''".
-      iApply "Hk". iApply (Pre_Eq_Proper with "[$] [$]").
-    - (* we close the invariant again for the recursive call *)
-      iDestruct "HM" as "(Hnin&HM)".
-      iMod ("Hclose1" with "[H● HM $Hna Hone]") as "Hna".
-      { iNext. iExists _. iFrame. }
-      wp_pures. wp_bind e.
-      iApply (rwp_strong_mono with "[Spec Hna]");[eauto..| by iApply "Spec" |].
-      iIntros (g) "[Hna Hres] !>"; simpl.
-      iSpecialize ("Hres" $! _ _ (S c) with "[$] Hsrc Hna").
-      wp_bind (g _). iApply (rwp_wand with "Hres []").
-      iIntros (v) "[Hna Hres]". iDestruct "Hres" as (k) "(HPost & Hcred & Hsrc & #Hk)".
-      rewrite nat_srcF_succ. iDestruct ("Hcred") as "[Hone Hcred]".
-      iMod (na_inv_acc_open_timeless with "IM Hna") as "(Hc & Hna & Hclose1)"; auto.
-      iDestruct "Hc" as (h2) "(HM & H● & Hone')".
-      iMod (na_inv_acc_open with "IC Hna") as "Hcache"; auto; first solve_ndisj.
-      iApply (rwp_take_step with "[-Hone] [Hone]"); first done; last first.
-      { iApply step_stutter. iFrame. } iIntros "_".
-      iApply rswp_do_step. iNext; simpl. iDestruct "Hcache" as "(HsrcI & Hna & Hclose2)".
-      iDestruct "HsrcI" as (h2') "[H◯ #Hupd]".
-      iDestruct (own_valid_2 with "H● H◯") as % [->%Excl_included%leibniz_equiv _]%auth_both_valid.
-      wp_pures.
-      iMod (Pre_Comparable with "HPre") as "HComp".
-      wp_apply (set_spec with "[$HM $HComp]").
-      iIntros "HM".
-      iMod (own_update_2 with "H● H◯") as "[H● H◯]".
-      { apply auth_update, option_local_update, (exclusive_local_update _ (Excl (<[n := v]> h2))); done. }
-      iApply fupd_rwp. iMod ("Hclose2" with "[H◯ $Hna]") as "Hna".
-      { iNext. iExists (<[n:=_]> h2). iFrame.
-        iApply big_sepM_insert_2; simpl; eauto. }
-      iMod ("Hclose1" with "[H● HM $Hna Hone']") as "Hna".
-      { iNext. iExists _. iFrame. }
-      iModIntro. wp_pures. iFrame.
-      iExists k. iFrame. iFrame "#".
-  Qed.
-
-  Lemma tf_memoize_spec `{FiniteBoundedExistential SI} eq (f g: val):
-    eqfun Comparable eq Eq ∗
-    tf_implements g f ∗
-    $ (1%nat)
-    ⊢ SEQ (memoize eq g) ⟨⟨ h, tf_implements h f ⟩⟩.
-  Proof using Comparable Comparable_timeless Cred Eq Heap PEq PPost PPre Post Pre Pre_Comparable Pre_Eq_Proper SI
-        Seq Sync Σ.
-    iIntros "(#Heq&#H&Hcred) Hna". rewrite /memoize. wp_pures. iFrame.
-    wp_apply map_spec; first done. iIntros (m) "Hm".
-    iMod (own_alloc (● (Excl' ∅) ⋅ ◯ (Excl' ∅))) as (γ) "[H● H◯]".
-    { apply auth_both_valid_2; done. }
-    iMod (na_inv_alloc seqG_name ⊤ (refN .@ "tl") (mem_rec_tl_inv γ m) with "[H● Hm Hcred]") as "#IM".
-    { iNext. iExists ∅. iFrame. }
-    iMod (na_inv_alloc seqG_name ⊤ (refN .@ "tf") (mem_rec_tf_inv γ f) with "[H◯]") as "#IS".
-    { iNext. iExists ∅. iFrame. rewrite big_sepM_empty; done. }
-    wp_pures. iFrame.
-    iIntros (n n' c K) "!> #HPre Hsrc Hna".
-    wp_pure _.
-    iDestruct (Pre_Comparable with "HPre") as "Hcomp".
-    iApply (tf_memoization_core with "[-Hna] [$Hna]").
-    iFrame "IM IS Hsrc HPre Heq". iIntros "Hna". wp_value_head. iFrame.
-    iApply "H".
-  Qed.
-
-  Lemma tf_mem_rec_spec `{FiniteBoundedExistential SI} eq (F f: val):
-      eqfun Comparable eq Eq ∗
-      (□ ∀ g, ▷ tf_implements g f -∗ SEQ (F g) ⟨⟨h, tf_implements h f⟩⟩) ∗ $ (1%nat) ⊢
-      SEQ (mem_rec eq F) ⟨⟨ h, tf_implements h f ⟩⟩.
-  Proof using Comparable Comparable_timeless Cred Eq Heap PEq PPost PPre Post Pre Pre_Comparable Pre_Eq_Proper SI
-        Seq Sync Σ.
-      iIntros "[#Heq [#HF Hcred]] Hna". rewrite /mem_rec. wp_pures. iFrame.
-      wp_apply map_spec; first done. iIntros (m) "Hm".
-      iMod (own_alloc (● (Excl' ∅) ⋅ ◯ (Excl' ∅))) as (γ) "[H● H◯]".
-      { apply auth_both_valid_2; done. }
-      iMod (na_inv_alloc seqG_name ⊤ (refN .@ "tl") (mem_rec_tl_inv γ m) with "[H● Hm Hcred]") as "#IM".
-      { iNext. iExists ∅. iFrame. }
-      iMod (na_inv_alloc seqG_name ⊤ (refN .@ "tf") (mem_rec_tf_inv γ f) with "[H◯]") as "#IS".
-      { iNext. iExists ∅. iFrame. rewrite big_sepM_empty; done. }
-      wp_pures. iFrame.
-
-      iLöb as "IH". iModIntro; iIntros (n n' c K) "#HPre Hsrc Hna".
-      wp_pure _.
-      iDestruct (Pre_Comparable with "HPre") as "Hcomp".
-      iApply (tf_memoization_core with "[-Hna] Hna").
-      iFrame "IM IS Hsrc HPre Heq". iApply "HF". iApply "IH".
-  Qed.
-
-End repeatable_refinements.
-
-
-Section fibonacci.
-  Context {SI: indexT} {A: Type} `{Σ: gFunctors SI} `{Heap: !rheapG Σ} `{Cred: !auth_sourceG Σ (natA SI)}  `{Seq: !seqG Σ}.
-
-  (* we define the body to reduce the number of lemmas we need to prove*)
-  Definition Fib (fib : val) (n : expr): expr :=
-    if: n = #0 then #0
-      else if: n = #1 then #1
-      else
-        let: "n'" := n - #1 in
-        let: "n''" := n - #2 in
-        fib "n'" + fib "n''".
-
-
-  Lemma Fib_zero fib: exec (Fib fib #0) (#0).
-  Proof.
-    eapply pure_exec_exec.
-    - rewrite /Fib; pure_exec.
-    - repeat split; solve_vals_compare_safe.
-  Qed.
-
-  Lemma Fib_one fib: exec (Fib fib #1) (#1).
-  Proof.
-    eapply pure_exec_exec.
-    - rewrite /Fib; pure_exec.
-    - repeat split; solve_vals_compare_safe.
-  Qed.
-
-  Lemma Fib_rec fib n: exec (Fib fib #(S (S n))) ((fib #(S n)) + (fib #n))%E.
-  Proof.
-    eapply pure_exec_exec.
-    - rewrite /Fib; pure_exec.
-      rewrite bool_decide_eq_false_2; last (injection 1; lia).
-      pure_exec.
-    - repeat split; try solve_vals_compare_safe.
-      + rewrite /bin_op_eval //=. by replace (S (S n) - 1) with (S n: Z) by lia.
-      + rewrite /bin_op_eval //=. by replace (S (S n) - 2) with (n: Z) by lia.
-  Qed.
-
-  Definition fib : val :=
-    rec: "fib" "n" :=
-      if: "n" = #0 then #0
-      else if: "n" = #1 then #1
-      else
-        let: "n'" := "n" - #1 in
-        let: "n''" := "n" - #2 in
-        "fib" "n'" + "fib" "n''".
-
-  Lemma fib_Fib (v: val): exec (fib v) (Fib fib v).
-  Proof.
-    eapply pure_exec_exec.
-    - rewrite /Fib /fib; pure_exec.
-    - repeat split.
-  Qed.
-
-  Definition fib_template : val :=
-    λ: "fib" "n",
-      if: "n" = #0 then #0
-      else if: "n" = #1 then #1
-      else
-        let: "n'" := "n" - #1 in
-        let: "n''" := "n" - #2 in
-        "fib" "n'" + "fib" "n''".
-
-  Tactic Notation "exec_bind" open_constr(efoc) :=
-    match goal with
-    | [|- exec ?e1 ?e2] =>
-      src_bind_core e1 efoc ltac:(fun K e' => change (exec (fill K e') e2))
-    end.
-
-  Lemma fib_fundamental_core g K (n: nat):
-    (▷ implements execV natRel natRel g fib) ∗
-    src (fill K (fib #n)) ⊢
-    SEQ (Fib g #n) ⟨⟨v, ∃ m: nat, ⌜v = #m⌝ ∗ src (fill K #m) ∗ □ execV (fib #n) #m ⟩⟩.
-  Proof.
-  iIntros "[#IH Hsrc] Hna".
-  destruct n as [|[|n]]; (iApply (rwp_take_step with "[-Hsrc] [Hsrc]"); first done; last first).
-  - iApply exec_src_update; eauto. eapply exec_frame.
-    etrans; first apply fib_Fib. eapply Fib_zero.
-  - iIntros "Hsrc".  iApply rswp_do_step. iNext. rewrite /Fib.
-    wp_pure _; first solve_vals_compare_safe. wp_pures. iFrame.
-    iExists 0%nat. iFrame. iSplitL; eauto.
-    iModIntro. iPureIntro. etrans; first apply fib_Fib. eapply Fib_zero.
-  - iApply exec_src_update; eauto. eapply exec_frame.
-    etrans; first apply fib_Fib. eapply Fib_one.
-  - iIntros "Hsrc".  iApply rswp_do_step. iNext. rewrite /Fib.
-    wp_pure _; first solve_vals_compare_safe. wp_pures.
-    wp_pure _; first solve_vals_compare_safe. wp_pures.
-    iFrame. iExists 1%nat. iFrame. iSplitL; eauto.
-    iModIntro. iPureIntro.
-    etrans; first apply fib_Fib. eapply Fib_one.
-  - iApply exec_src_update; eauto. eapply exec_frame.
-    etrans; first apply fib_Fib. eapply Fib_rec.
-  - iIntros "Hsrc".  iApply rswp_do_step. iNext. rewrite /Fib.
-    wp_pure _; first solve_vals_compare_safe. wp_pures.
-    wp_pure _; first solve_vals_compare_safe.
-    rewrite bool_decide_eq_false_2; last (injection 1; lia).
-    do 7 wp_pure _.
-    (* recursion for n *)
-    wp_bind (g  _)%E. replace (S (S n) - 2) with (n: Z) by lia.
-    src_bind (fib #n) in "Hsrc".
-    iApply (rwp_wand with "[Hna Hsrc]").
-    { iApply ("IH" with "[] Hsrc Hna"); first eauto. }
-    iIntros (v) "[Hna H]". iDestruct "H" as (m) "(HPre & Hsrc & #Hev1)"; simpl.
-    iDestruct "HPre" as %[m' [Heq1 Heq2]]. subst.
-    (* recursion for (n + 1) *)
-    wp_bind (g  _)%E. replace (S (S n) - 1) with (S n: Z) by lia.
-    src_bind (fib _) in "Hsrc".
-    iApply (rwp_wand with "[Hna Hsrc]").
-    { iApply ("IH" with "[] Hsrc Hna"). eauto. }
-    iIntros (v) "[Hna H]". iDestruct "H" as (v') "(HPre & Hsrc & #Hev2)"; simpl.
-    iDestruct "HPre" as %[m [Heq1 Heq2]]. subst.
-    iFrame. iApply (rwp_weaken with "[-Hsrc] [Hsrc]"); first done; last first.
-    { iApply (steps_pure_exec with "Hsrc"). reflexivity. }
-    simpl; iIntros "Hsrc"; wp_pure _.
-    replace (m + m') with ((m' + m)%nat: Z) by lia.
-    iExists (m' + m)%nat; iFrame; iSplitR; auto.
-    iModIntro.
-    iDestruct "Hev1" as % Hev1. iDestruct "Hev2" as % Hev2. iPureIntro.
-    etrans; first eapply fib_Fib.
-    etrans; first eapply Fib_rec.
-    edestruct Hev1 as (?&Hexec1&?&Heq1&?); eauto.
-    edestruct Hev2 as (?&Hexec2&?&Heq2&?); eauto; subst.
-    inversion Heq1; subst.
-    inversion Heq2; subst.
-    exec_bind (fib _); etrans; first eapply exec_frame; eauto; simpl.
-    exec_bind (fib _); etrans; first eapply exec_frame; eauto; simpl.
-    eapply pure_exec_exec. apply _.
-    rewrite /bin_op_eval. destruct (decide _) => //=.
-    repeat f_equal. lia.
-  Qed.
-
-  Lemma fib_sound:
-    ⊢ implements execV natRel natRel fib fib.
-  Proof.
-    iLöb as "IH".
-    iModIntro; iIntros (v v' K) "HPre Hsrc Hna".
-    iDestruct "HPre" as %[n [Heq1 Heq2]]. subst.
-    rewrite {4}/fib. wp_pure _.
-    fold fib. fold (Fib fib #n).
-    iApply rwp_mono; last first.
-    { iApply (fib_fundamental_core fib K n with "[$Hsrc $IH] Hna"). }
-    iIntros (v) "($&H)".
-    iDestruct "H" as (m ->) "(Hsrc&#Hexec)". iExists _. iFrame.
-    iSplitR; first eauto.
-    iModIntro. iIntros (x) "Hrel". iDestruct "Hrel" as %[? [-> ->]]. iExists _. iSplit; eauto.
-  Qed.
-
-  Lemma fib_template_sound g:
-    ▷ implements execV natRel natRel g fib ⊢ SEQ (fib_template g) ⟨⟨h, implements execV natRel natRel h fib⟩⟩.
-  Proof.
-    iIntros "#H Hna". rewrite /fib_template. wp_pures. iFrame.
-    iModIntro; iIntros (n n' K) "HPre Hsrc Hna".
-    wp_pure _. fold (Fib g n).
-    iDestruct "HPre" as %[n0 [-> ->]].
-    iApply rwp_mono; last first.
-    { by iApply (fib_fundamental_core g K n0 with "[$Hsrc] Hna"). }
-    iIntros (v) "($&H)".
-    iDestruct "H" as (m ->) "(Hsrc&#Hexec)". iExists _. iFrame.
-    iSplitR; first eauto.
-    iModIntro. iIntros (x) "Hrel". iDestruct "Hrel" as %[? [-> ->]]. iExists _. iSplit; eauto.
-  Qed.
-
-
-  (* memoized versions *)
-  Lemma fib_memoized: ⊢ SEQ (memoize eq_heaplang fib) ⟨⟨ h, implements execV natRel natRel h fib ⟩⟩.
-  Proof.
-    (* XXX: the iApply fails over typeclass resolution (?) if we don't do iStartProof *)
-    iStartProof.
-    iApply (memoize_spec _ _ _ (λ x, ⌜ val_is_unboxed x ⌝)%I (λ x1 x2, ⌜ x1 = x2 ⌝)%I);
-      [| | iSplit; [| iSplit]].
-    - iIntros (??) "H". iDestruct "H" as %[? [-> ->]]. eauto.
-    - iIntros (??? ->). auto.
-    - rewrite /eqfun. iIntros (??) "!>". iIntros (Φ) "(%&%) H".
-      rewrite /eq_heaplang. wp_pures.
-      wp_pure _; first (rewrite /vals_compare_safe; eauto).
-      iApply "H". iFrame "%". rewrite /bool_decide. destruct (decide_rel _); eauto.
-    - iApply fib_sound.
-    - iModIntro. iIntros (e v Hexec K).
-      iApply exec_src_update. apply exec_frame, Hexec.
-  Qed.
-
-  Lemma fib_deep_memoized: ⊢ SEQ (mem_rec eq_heaplang fib_template) ⟨⟨ h, implements execV natRel natRel h fib ⟩⟩.
-  Proof.
-    iStartProof.
-    iApply (mem_rec_spec _ _ _ (λ x, ⌜ val_is_unboxed x ⌝)%I (λ x1 x2, ⌜ x1 = x2 ⌝)%I);
-      [| | iSplit; [| iSplit]].
-    - iIntros (??) "H". iDestruct "H" as %[? [-> ->]]. eauto.
-    - iIntros (??? ->). auto.
-    - rewrite /eqfun. iIntros (??) "!>". iIntros (Φ) "(%&%) H".
-      rewrite /eq_heaplang. wp_pures.
-      wp_pure _; first (rewrite /vals_compare_safe; eauto).
-      iApply "H". iFrame "%". rewrite /bool_decide. destruct (decide_rel _); eauto.
-    - iModIntro. iIntros (g). iApply fib_template_sound.
-    - iModIntro. iIntros (e v Hexec K).
-      iApply exec_src_update. apply exec_frame, Hexec.
-  Qed.
-End fibonacci.
-
-Section levenshtein.
-  Context {SI: indexT} {A: Type} `{Σ: gFunctors SI} `{Heap: !rheapG Σ} `{Cred: !auth_sourceG Σ (natA SI)}  `{Seq: !seqG Σ}.
-
-  Definition eqstr : val :=
-    rec: "eqstr" "s1" "s2" :=
-      let: "c1" := !"s1" in
-      let: "c2" := !"s2" in
-      if: "c1" = "c2" then
-        if: "c1" = #0 then
-          #true
-        else
-          "eqstr" ("s1" +ₗ #1) ("s2" +ₗ #1)
-      else
-        #false.
-
-  Definition Strlen (strlen : val) (l : expr): expr :=
-      let: "c" := !l in
-      if: "c" = #0 then #0
-      else
-        let: "r" := strlen (l +ₗ #1) in
-        #1 + "r".
-
-  Definition strlen_template : val :=
-    λ: "strlen" "l",
-      let: "c" := !"l" in
-      if: "c" = #0 then #0
-      else
-        let: "r" := "strlen" ("l" +ₗ #1) in
-        #1 + "r".
-
-  Definition strlen : val :=
-    rec: "strlen" "l" := strlen_template "strlen" "l".
-
-  Definition min2 : val :=
-    λ: "n1" "n2",
-    if: "n1" ≤ "n2" then "n1" else "n2".
-
-  Definition min3 : val :=
-    λ: "n1" "n2" "n3",
-    min2 (min2 "n1" "n2") ("n3").
-
-  (*
-  Fixpoint gallina_lev (s1 : list nat) (s2 : list nat) : nat :=
-    match s1 with
-    | [] => length s2
-    | c1 :: s1' =>
-      match s2 with
-      |  [] => length s1
-      | c2 :: s2' =>
-        if decide (c1 = c2) then
-          gallina_lev s1' s2'
-        else
-          let r1 := gallina_lev s1 s2' in
-          let r2 := gallina_lev s1' s2 in
-          let r3 := gallina_lev s1' s2' in
-          (1 + min (min r1 r2) r3)%nat
-      end
-    end.
-  *)
-
-  Definition Lev (strlen : val) (lev : val) (s12 : expr): expr :=
-      let: "s1" := Fst s12 in
-      let: "s2" := Snd s12 in
-      let: "c1" := !"s1" in
-      if: "c1" = #0 then strlen "s2" else
-      let: "c2" := !"s2" in
-      if: "c2" = #0 then strlen "s1" else
-      if: "c1" = "c2" then lev ("s1" +ₗ #1, "s2" +ₗ #1)
-      else
-        let: "r1" := lev ("s1", "s2" +ₗ #1) in
-        let: "r2" := lev ("s1" +ₗ #1, "s2") in
-        let: "r3" := lev ("s1" +ₗ #1, "s2" +ₗ #1) in
-        #1 + min3 "r1" "r2" "r3".
-
-  Definition lev_template : val :=
-    λ: "strlen" "lev" "s12",
-      let: "s1" := Fst "s12" in
-      let: "s2" := Snd "s12" in
-      let: "c1" := !"s1" in
-      if: "c1" = #0 then "strlen" "s2" else
-      let: "c2" := !"s2" in
-      if: "c2" = #0 then "strlen" "s1" else
-      if: "c1" = "c2" then "lev" ("s1" +ₗ #1,"s2" +ₗ #1)
-      else
-        let: "r1" := "lev" ("s1", "s2" +ₗ #1) in
-        let: "r2" := "lev" ("s1" +ₗ #1, "s2") in
-        let: "r3" := "lev" ("s1" +ₗ #1, "s2" +ₗ #1) in
-        #1 + min3 "r1" "r2" "r3".
-
-  Definition lev_template' (slen : expr) : val :=
-    λ: "lev" "s12",
-      let: "s1" := Fst "s12" in
-      let: "s2" := Snd "s12" in
-      let: "c1" := !"s1" in
-      if: "c1" = #0 then slen "s2" else
-      let: "c2" := !"s2" in
-      if: "c2" = #0 then slen "s1" else
-      if: "c1" = "c2" then "lev" ("s1" +ₗ #1,"s2" +ₗ #1)
-      else
-        let: "r1" := "lev" ("s1", "s2" +ₗ #1) in
-        let: "r2" := "lev" ("s1" +ₗ #1, "s2") in
-        let: "r3" := "lev" ("s1" +ₗ #1, "s2" +ₗ #1) in
-        #1 + min3 "r1" "r2" "r3".
-
-  Definition lev : val :=
-    rec: "lev" "s12" := lev_template strlen "lev" "s12".
-
-  Notation exec := (tc (@pure_step heap_lang)).
-
-  Tactic Notation "exec_bind" open_constr(efoc) :=
-    match goal with
-    | [|- exec ?e1 ?e2] =>
-      src_bind_core e1 efoc ltac:(fun K e' => change (exec (fill K e') e2))
-    end.
-
-  Lemma strlen_Strlen (v: val): exec (strlen v) (Strlen strlen v).
-  Proof.
-    eapply pure_exec_exec.
-    - rewrite /Strlen /strlen /strlen_template; repeat pure_exec.
-    - repeat split.
-  Qed.
-
-  Lemma lev_Lev (v: val): exec (lev v) (Lev strlen lev v).
-  Proof.
-    eapply pure_exec_exec.
-    - rewrite /Lev /lev /lev_template; repeat pure_exec.
-    - repeat split.
-  Qed.
-
-  (* C-style null terminated strings *)
-
-  Fixpoint string_is (l: loc) (s: list nat) :=
-    match s with
-      | [] => (∃ q, l ↦{q} #0)
-      | n1 :: s' => ⌜ n1 ≠ O ⌝ ∗ (∃ q, l ↦{q} #n1) ∗ string_is (l +ₗ 1) s'
-    end%I.
-
-  Fixpoint src_string_is (l: loc) (s: list nat) :=
-    match s with
-      | [] => (∃ q, l ↦s{q} #0)
-      | n1 :: s' => ⌜ n1 ≠ O ⌝ ∗ (∃ q, l ↦s{q} #n1) ∗ src_string_is (l +ₗ 1) s'
-    end%I.
-
-  Lemma string_is_dup l s :
-    string_is l s -∗ string_is l s ∗ string_is l s.
-  Proof.
-    iInduction s as [| n s] "IH" forall (l).
-    - iDestruct 1 as (q) "H". iDestruct "H" as "(H1&H2)".
-      iSplitL "H1"; iExists _; iFrame.
-    - simpl string_is. iDestruct 1 as (Hneq) "(H&Htl)".
-      iDestruct "H" as (q) "(H1&H2)".
-      iDestruct ("IH" with "Htl") as "(Htl1&Htl2)".
-      iSplitL "H1 Htl1"; iFrame "% ∗"; iExists _; iFrame.
-  Qed.
-
-  Instance string_is_timeless l s : Timeless (string_is l s).
-  Proof. revert l. induction s; apply _. Qed.
-
-  Lemma src_string_is_dup l s :
-    src_string_is l s -∗ src_string_is l s ∗ src_string_is l s.
-  Proof.
-    iInduction s as [| n s] "IH" forall (l).
-    - iDestruct 1 as (q) "H". iDestruct "H" as "(H1&H2)".
-      iSplitL "H1"; iExists _; iFrame.
-    - simpl src_string_is. iDestruct 1 as (Hneq) "(H&Htl)".
-      iDestruct "H" as (q) "(H1&H2)".
-      iDestruct ("IH" with "Htl") as "(Htl1&Htl2)".
-      iSplitL "H1 Htl1"; iFrame "% ∗"; iExists _; iFrame.
-  Qed.
-
-  Instance src_string_is_timeless l s : Timeless (src_string_is l s).
-  Proof. revert l. induction s; apply _. Qed.
-
-  Definition stringRel_is (v1 v2: val) (s: list nat) : iProp Σ :=
-    (∃ (l1 l2 : loc), ⌜ v1 = #l1 ∧ v2 = #l2 ⌝ ∗ string_is l1 s ∗ src_string_is l2 s)%I.
-
-  Definition strN := nroot.@"str".
-
-  Definition imm_stringRel (v1 v2: val) : iProp Σ :=
-    (∃ s, inv strN (stringRel_is v1 v2 s))%I.
-
-  Lemma stringRel_inv_acc (v1 v2 : val) s :
-    inv strN (stringRel_is v1 v2 s) ={⊤}=∗
-    stringRel_is v1 v2 s.
-  Proof.
-    iIntros "Hinv". iInv "Hinv" as ">H" "Hclo".
-    iDestruct "H" as (?? (Heq1&Heq2)) "(His1&His2)".
-    iDestruct (string_is_dup with "His1") as "(His1&His1')".
-    iDestruct (src_string_is_dup with "His2") as "(His2&His2')".
-    iMod ("Hclo" with "[His1' His2']"); iModIntro; iExists _, _; iFrame; eauto.
-  Qed.
-
-  Definition pairRel Pa Pb (v1 v2 : val) : iProp Σ :=
-    (∃ v1a v1b v2a v2b, ⌜ v1 = PairV v1a v1b⌝ ∗ ⌜v2 = PairV v2a v2b ⌝ ∗ Pa v1a v2a ∗ Pb v1b v2b)%I.
-
-  Definition pair_imm_stringRel := pairRel imm_stringRel imm_stringRel.
-
-  Lemma rwp_strlen l s:
-    string_is l s -∗
-    RWP (strlen #l) ⟨⟨v, ⌜v = #(length s)⌝ ⟩⟩.
-  Proof.
-    iIntros "Hstr".
-    iInduction s as [| n s] "IH" forall (l).
-    - rewrite /strlen/strlen_template. wp_pures.
-      iDestruct "Hstr" as (?) "H".
-      wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe.
-      wp_pures. iFrame. eauto.
-    - rewrite /strlen/strlen_template. wp_pures. simpl string_is.
-      iDestruct "Hstr" as (?) "(H1&Htl)".
-      iDestruct "H1" as (?) "Hl".
-      wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe.
-      case_bool_decide; wp_pure _; eauto.
-      { exfalso. eapply H. inversion H1. lia. }
-
-      wp_bind ((rec: "strlen" "l" :=
-                     (λ: "strlen" "l",
-                        let: "c" := ! "l" in
-                        if: "c" = #0 then #0 else let: "r" := "strlen" ("l" +ₗ #1) in #1 + "r")%V "strlen" "l")%V
-                 (#l +ₗ #1))%E.
-      wp_pure _.
-      iApply (rwp_wand with "[Htl]").
-      { iApply ("IH" with "[$]"). }
-      iIntros (v) "%". subst. wp_pures. iFrame. iPureIntro.
-      do 2 f_equal. simpl. lia.
-  Qed.
-
-  Lemma eval_strlen l s:
-    src_string_is l s -∗
-    eval (strlen #l) #(length s).
-  Proof.
-    iIntros "Hstr" (K) "H".
-    iInduction s as [| n s] "IH" forall (K l).
-    - rewrite /strlen/strlen_template.
-      do 4 src_pure _ in "H".
-      iDestruct "Hstr" as (?) "Hstr".
-      src_load in "H". do 4 src_pure _ in "H". iApply weak_src_update_return. by iFrame.
-    - rewrite /strlen/strlen_template. do 4 src_pure _ in "H". simpl src_string_is.
-      iDestruct "Hstr" as (?) "(H1&Htl)".
-      iDestruct "H1" as (?) "Hl".
-      src_load in "H".
-      do 3 src_pure _ in "H".
-      case_bool_decide; src_pure _ in "H"; eauto.
-      { exfalso. eapply H. inversion H1. lia. }
-      src_pure _ in "H".
-      src_bind ((rec: "strlen" "l" :=
-                             (λ: "strlen" "l",
-                                let: "c" := ! "l" in
-                                if: "c" = #0 then #0 else let: "r" := "strlen" ("l" +ₗ #1) in #1 + "r")%V "strlen"
-                               "l")%V
-                 #(l +ₗ 1))%E in "H".
-      iDestruct ("IH" with "Htl H") as "H".
-      simpl fill.
-      iApply src_update_weak_src_update.
-      iApply weak_src_update_bind_r. iFrame.
-      iIntros "H".
-      do 3 src_pure _ in "H".
-      iApply weak_src_update_return.
-      replace (S (length s) : Z)%Z with (1 + length s)%Z; first by iFrame.
-      rewrite Nat2Z.inj_succ //=. lia.
-  Qed.
-
-  Lemma stringRel_is_tl (l1 l2 : loc) n s:
-    stringRel_is #l1 #l2 (n :: s) -∗
-    stringRel_is #(l1 +ₗ 1) #(l2 +ₗ 1) s ∗
-    (stringRel_is #(l1 +ₗ 1) #(l2 +ₗ 1) s -∗ stringRel_is #l1 #l2 (n :: s)).
-  Proof.
-    rewrite /stringRel_is.
-    iDestruct 1 as (?? (Heq1&Heq2)) "(H1&H2)".
-    inversion Heq1; subst.
-    inversion Heq2; subst.
-    simpl string_is. simpl src_string_is.
-    iDestruct "H1" as (?) "(H1&Htl1)".
-    iDestruct "H2" as (?) "(H2&Htl2)".
-    iSplitL "Htl1 Htl2".
-    { iExists _, _. iSplit; first eauto. iFrame. }
-    iIntros "H". iExists _, _. iSplit; first eauto.
-    iDestruct "H" as (?? (Heq1'&Heq2')) "(Htl1&Htl2)".
-    iSplitL "H1 Htl1".
-    { iSplit; eauto. iFrame. inversion Heq1'. subst. eauto. }
-    { iSplit; eauto. iFrame. inversion Heq2'. subst. eauto. }
-  Qed.
-
-  Lemma inv_stringRel_is_tl N (l1 l2 : loc) n s:
-    inv N (stringRel_is #l1 #l2 (n :: s)) -∗
-    inv N (stringRel_is #(l1 +ₗ 1) #(l2 +ₗ 1) s).
-  Proof.
-    iIntros "Hinv". iApply (inv_alter_timeless with "Hinv").
-    iIntros "!> H1".
-    iDestruct (stringRel_is_tl with "H1") as "($&$)".
-  Qed.
-
-  Lemma min2_spec (n1 n2: nat) :
-    ⊢ ⟨⟨⟨ True ⟩⟩⟩ min2 #n1 #n2 ⟨⟨⟨ RET #(min n1 n2) ; True ⟩⟩⟩.
-  Proof.
-    iIntros "!>" (Φ) "_ HΦ".
-    rewrite /min2. wp_pures.
-    case_bool_decide; wp_pures.
-    - rewrite ->min_l by lia. by iApply "HΦ".
-    - rewrite ->min_r by lia. by iApply "HΦ".
-  Qed.
-
-  Lemma min3_spec (n1 n2 n3: nat) :
-    ⊢ ⟨⟨⟨ True ⟩⟩⟩ min3 #n1 #n2 #n3 ⟨⟨⟨ RET #(min (min n1 n2) n3) ; True ⟩⟩⟩.
-  Proof.
-    iIntros "!>" (Φ) "_ HΦ".
-    rewrite /min3. wp_pures.
-    repeat (wp_apply min2_spec; auto; iIntros "_").
-  Qed.
-
-  Lemma eval_min2 (n1 n2: nat) :
-    eval (min2 #n1 #n2) #(min n1 n2).
-  Proof.
-    rewrite /eval. iIntros (K) "Hsrc".
-    rewrite /min2. do 4 src_pure _ in "Hsrc".
-    case_bool_decide; do 1 src_pure _ in "Hsrc".
-    - rewrite ->min_l by lia. by iApply weak_src_update_return.
-    - rewrite ->min_r by lia. by iApply weak_src_update_return.
-  Qed.
-
-  Lemma eval_min3 (n1 n2 n3: nat) :
-    eval (min3 #n1 #n2 #n3) #(min (min n1 n2) n3).
-  Proof.
-    rewrite /eval. iIntros (K) "Hsrc".
-    rewrite /min3/min2. do 9 src_pure _ in "Hsrc".
-    case_bool_decide; do 1 src_pure _ in "Hsrc".
-    - do 4 src_pure _ in "Hsrc".
-      case_bool_decide; do 1 src_pure _ in "Hsrc".
-      * do 2 rewrite ->min_l by lia. by iApply weak_src_update_return.
-      * rewrite ->min_r by lia. by iApply weak_src_update_return.
-    - do 4 src_pure _ in "Hsrc".
-      case_bool_decide; do 1 src_pure _ in "Hsrc".
-      * rewrite ->min_l by lia. rewrite ->min_r by lia. by iApply weak_src_update_return.
-      * rewrite ->min_r by lia. by iApply weak_src_update_return.
-  Qed.
-
-  Lemma string_is_functional va s s' :
-    string_is va s -∗
-    string_is va s' -∗
-    ⌜s = s'⌝.
-  Proof.
-    iIntros "Hrel1 Hrel2".
-    iInduction s as [| n s] "IH" forall (va s').
-    { destruct s'; first auto.
-      simpl string_is.
-      iDestruct "Hrel1" as (?) "Hva".
-      iDestruct "Hrel2" as (Hneq) "(Hva'&?)".
-      iDestruct "Hva'" as (?) "Hva'".
-      iDestruct (mapsto_agree with "[$] [$]") as %Hfalse.
-      iPureIntro. exfalso. inversion Hfalse. lia. }
-    destruct s'; first auto.
-    - simpl string_is.
-      iDestruct "Hrel1" as (Hneq) "(Hva&?)".
-      iDestruct "Hva" as (?) "Hva".
-      iDestruct "Hrel2" as (?) "Hva'".
-      iDestruct (mapsto_agree with "[$] [$]") as %Hfalse.
-      iPureIntro. exfalso. inversion Hfalse. lia.
-    - simpl string_is.
-      iDestruct "Hrel1" as (Hneq) "(Hva&?)".
-      iDestruct "Hva" as (?) "Hva".
-      iDestruct "Hrel2" as (Hneq') "(Hva'&?)".
-      iDestruct "Hva'" as (?) "Hva'".
-      iDestruct (mapsto_agree with "[$] [$]") as %Heq1.
-      iDestruct ("IH" with "[$] [$]") as %Heq2.
-      iPureIntro. subst. inversion Heq1; subst. f_equal; lia.
-  Qed.
-
-  Lemma stringRel_is_functional va vb vb' s s' :
-    stringRel_is va vb s -∗
-    stringRel_is va vb' s' -∗
-    ⌜s = s'⌝.
-  Proof.
-    iIntros "Hrel1 Hrel2".
-    iDestruct "Hrel1" as (?? (->&->)) "(His1&?)".
-    iDestruct "Hrel2" as (?? (Heq&?)) "(His2&?)".
-    inversion Heq; subst. iApply (string_is_functional with "His1 [$]").
-  Qed.
-
-  Lemma strlen_fundamental_core slen c K (va vb: val):
-    (▷ tf_implements imm_stringRel natRel slen strlen) ∗
-    imm_stringRel va vb ∗
-    src (fill K (strlen vb)) ⊢
-    SEQ (Strlen slen va) ⟨⟨v, ∃ m: nat, ⌜v = #m⌝ ∗ $ c ∗ src (fill K #m) ∗ □ (∀ vb', imm_stringRel va vb' -∗ eval (strlen vb') #m) ⟩⟩.
-  Proof.
-  iIntros "[#IH [HPre Hsrc]] Hna".
-  iDestruct "HPre" as (s) "#Hinv1".
-  iApply (rwp_take_step with "[-Hsrc] [Hsrc]"); first done; last first.
-  { iApply (step_inv_alloc c with "[] [$Hsrc]").
-    iSplitL.
-    { iApply exec_src_update; eauto. eapply exec_frame. apply strlen_Strlen. }
-    iIntros "H". iExists _. iFrame. iPureIntro.
-    rewrite /Strlen/strlen. intros Heq%fill_inj. congruence. }
-  iIntros "(Hsrc&$)".  iApply rswp_do_step. iNext. rewrite /Strlen.
-  iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-  iDestruct "Hstr1" as (l1a l1b (->&->)) "(Hl1a&Hl1b)".
-  destruct s as [| n s].
-  {
-    iDestruct "Hl1a" as (q1a) "Hl1a".
-    iDestruct "Hl1b" as (q1b) "Hl1b".
-    wp_load.
-    src_load in "Hsrc".
-    do 4 src_pure _ in "Hsrc".
-     wp_pures. wp_pure _; first solve_vals_compare_safe. wp_pures.
-     iFrame. iExists O. iSplit; first eauto. iFrame.
-    iModIntro. rewrite /eval. iIntros (vb') "#HPre". iIntros (K') "H".
-    iDestruct "HPre" as (s') "#Hinv1'".
-    iApply fupd_src_update.
-    iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-    iMod (stringRel_inv_acc with "Hinv1'") as "Hstr1'".
-    iDestruct (stringRel_is_functional with "Hstr1' Hstr1") as %->.
-    iModIntro.
-    iClear "Hstr1".
-    iRename "Hstr1'" into "Hstr1".
-    iDestruct "Hstr1" as (?? (->&->)) "(Hl1a&Hl1b)".
-    iDestruct "Hl1a" as (q1a') "Hl1a".
-    iDestruct "Hl1b" as (q1b') "Hl1b".
-    rewrite /strlen/strlen_template.
-    do 4 src_pure _ in "H".
-    src_load in "H".
-    do 4 src_pure _ in "H".
-    iApply weak_src_update_return; by iFrame.
-  }
-  simpl string_is. simpl src_string_is.
-  iDestruct "Hl1a" as (H1neq0) "(Hpts1a&Hl1a)".
-  iDestruct "Hpts1a" as (?) "Hpts1a".
-  iDestruct "Hl1b" as (H1neq0') "(Hpts1b&Hl1b)".
-  iDestruct "Hpts1b" as (?) "Hpts1b".
-  wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe.
-  src_load in "Hsrc".
-  do 3 src_pure _ in "Hsrc".
-  rewrite bool_decide_false; last first.
-  { intros Heq. inversion Heq. lia. }
-  wp_pures.
-  do 2 src_pure _ in "Hsrc".
-  src_bind (strlen _)%E in "Hsrc".
-  iSpecialize ("IH" $! #(l1a +ₗ 1) _ O with "[] Hsrc [$]").
-  { iExists _. iApply inv_stringRel_is_tl. eauto. }
-  wp_bind (slen _).
-  iApply (rwp_wand with "[IH]").
-  { wp_apply "IH". }
-  iIntros (v) "($&H)".
-  iDestruct "H" as (? (m&Heq1&Heq2)) "(_&Hsrc&#Heval')".
-  subst. simpl fill. do 3 src_pure _ in "Hsrc". wp_pures. iExists (1 + m)%nat.
-  iSplit.
-  { iPureIntro. do 2 f_equal. lia. }
-  simpl.
-  iFrame.
-  replace (1 + Z.of_nat m) with (Z.of_nat (S m)) by lia. iFrame.
-  iModIntro. rewrite /eval. iIntros (vb') "#HPre". iIntros (K') "H".
-  iDestruct "HPre" as (s') "#Hinv1'".
-  iApply fupd_src_update.
-  iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-  iMod (stringRel_inv_acc with "Hinv1'") as "Hstr1'".
-  iDestruct (stringRel_is_functional with "Hstr1' Hstr1") as %->.
-  iModIntro.
-  iClear "Hstr1".
-  iRename "Hstr1'" into "Hstr1".
-  iDestruct "Hstr1" as (?? (Heq1a&Heq1b)) "(Hl1a&Hl1b)".
-  simpl src_string_is.
-  iDestruct "Hl1b" as (H1neq0'') "(Hpts1b&Hl1b)".
-  iDestruct "Hpts1b" as (?) "Hpts1b".
-  rewrite /strlen/strlen_template.
-  do 4 src_pure _ in "H".
-  rewrite Heq1b.
-  src_load in "H".
-  do 3 src_pure _ in "H".
-  rewrite bool_decide_false; last first.
-  { intros Heq. inversion Heq. lia. }
-  do 2 src_pure _ in "H".
-  src_bind (_ (#_)%V)%E in "H".
-  rewrite fill_cons. simpl ectxi_language.fill_item.
-  iApply src_update_weak_src_update.
-  iDestruct ("Heval'" with "[]") as (r2') "(Heval''&Hrel)"; [|
-  iDestruct "Hrel" as %[? (Heq2&->)]; iDestruct ("Heval''" with "H") as "H"].
-  { iExists _. iApply inv_stringRel_is_tl. eauto. }
-  simpl fill.
-  iApply (src_update_bind with "[$H]").
-  iIntros "H".
-  simpl.
-  rewrite -Heq2.
-  do 3 src_pure _ in "H".
-  replace (1 + Z.of_nat m) with (Z.of_nat (S m)) by lia.
-  iApply weak_src_update_return; by iFrame.
-  Qed.
-
-  Lemma lev_fundamental_core g slen c K (va vb: val):
-    (▷ tf_implements imm_stringRel natRel slen strlen) ∗
-    (▷ tf_implements pair_imm_stringRel natRel g lev) ∗
-    pair_imm_stringRel va vb ∗
-    src (fill K (lev vb)) ⊢
-    SEQ (Lev slen g va) ⟨⟨v, ∃ m: nat, ⌜v = #m⌝ ∗ $ c ∗ src (fill K #m) ∗ □ (∀ vb', pair_imm_stringRel va vb' -∗ eval (lev vb') #m) ⟩⟩.
-  Proof.
-  iIntros "[#Hstrlen [#IH [HPre Hsrc]]] Hna".
-  iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-  iDestruct "Hs1" as (s1) "#Hinv1".
-  iDestruct "Hs2" as (s2) "#Hinv2".
-  iApply (rwp_take_step with "[-Hsrc] [Hsrc]"); first done; last first.
-  { iApply (step_inv_alloc c with "[] [$Hsrc]").
-    iSplitL.
-    { iApply exec_src_update; eauto. eapply exec_frame. apply lev_Lev. }
-    iIntros "H". iExists _. iFrame. iPureIntro.
-    rewrite /Lev/lev. intros Heq%fill_inj. congruence. }
-  iIntros "(Hsrc&$)".  iApply rswp_do_step. iNext. rewrite /Lev.
-  wp_pures.
-  iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-  iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-  destruct s1 as [| n1 s1].
-  {
-    iDestruct "Hstr1" as (l1a l1b (->&->)) "(Hl1a&Hl1b)".
-    iDestruct "Hstr2" as (l2a l2b (->&->)) "(Hl2a&Hl2b)".
-    iDestruct "Hl1a" as (q1a) "Hl1a".
-    iDestruct "Hl1b" as (q1b) "Hl1b".
-    do 6 src_pure _ in "Hsrc".
-    src_load in "Hsrc".
-    do 4 src_pure _ in "Hsrc".
-    iDestruct ("Hstrlen" $! _ _ O with "[] [$Hsrc]") as "Hstr1".
-    { rewrite /imm_stringRel. iExists _; eauto. }
-    wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe. wp_pures.
-    iApply (rwp_wand with "[Hstr1 Hna]").
-    { wp_apply ("Hstr1" with "[$]"). }
-    iIntros (v) "(Hna&H)".
-    iDestruct "H" as (? (r1&Heq1&Heq2)) "(_&Hsrc&#Heval1)".
-    iFrame.
-    subst. wp_pures.
-    simpl fill. iExists _. iSplit; first eauto. iFrame.
-    iModIntro. rewrite /eval. iIntros (vb') "#HPre". iIntros (K') "H".
-    iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-    symmetry in Heq1. inversion_clear Heq1. subst.
-    iDestruct "Hs1" as (s1') "#Hinv1'".
-    iDestruct "Hs2" as (s2') "#Hinv2'".
-    iApply fupd_src_update.
-    iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-    iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-    iMod (stringRel_inv_acc with "Hinv1'") as "Hstr1'".
-    iMod (stringRel_inv_acc with "Hinv2'") as "Hstr2'".
-    iDestruct (stringRel_is_functional with "Hstr1' Hstr1") as %->.
-    iDestruct (stringRel_is_functional with "Hstr2' Hstr2") as %->.
-    iClear "Hstr1 Hstr2".
-    iRename "Hstr1'" into "Hstr1".
-    iRename "Hstr2'" into "Hstr2".
-    iDestruct "Hstr1" as (?? (->&->)) "(Hl1a&Hl1b)".
-    iDestruct "Hstr2" as (?? (->&->)) "(Hl2a&Hl2b)".
-    iDestruct "Hl1a" as (q1a') "Hl1a".
-    iDestruct "Hl1b" as (q1b') "Hl1b".
-    iModIntro.
-    rewrite /Lev/lev/lev_template.
-    do 12 src_pure _ in "H".
-    src_load in "H".
-    do 4 src_pure _ in "H".
-    iApply src_update_weak_src_update.
-    iDestruct ("Heval1" with "[]") as (v') "(Heval1'&Hrel)"; last first.
-    { iDestruct "Hrel" as %[? (->&->)]. iApply "Heval1'". eauto. }
-    rewrite /imm_stringRel. eauto.
-  }
-  iDestruct "Hstr1" as (l1a l1b (->&->)) "(Hl1a&Hl1b)".
-  iDestruct "Hstr2" as (l2a l2b (->&->)) "(Hl2a&Hl2b)".
-  simpl string_is.
-  iDestruct "Hl1a" as (H1neq0) "(Hpts1a&Hl1a)".
-  iDestruct "Hpts1a" as (?) "Hpts1a".
-  wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe.
-  rewrite bool_decide_false //; last first.
-  { intros Heq. inversion Heq. lia. }
-  wp_pures.
-  destruct s2 as [| n2 s2].
-  {
-    simpl src_string_is.
-    iDestruct "Hl2a" as (q2a) "Hl2a".
-    iDestruct "Hl1b" as (H1neq0') "(Hpts1b&Hl1b)".
-    iDestruct "Hpts1b" as (?) "Hpts1b".
-    wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe.
-    wp_pure _.
-    do 6 src_pure _ in "Hsrc".
-    src_load in "Hsrc".
-    do 3 src_pure _ in "Hsrc".
-    rewrite bool_decide_false //; last first.
-    { intros Heq. inversion Heq. lia. }
-    do 1 src_pure _ in "Hsrc".
-    iDestruct "Hl2b" as (q2b) "Hl2b".
-    src_load in "Hsrc".
-    do 4 src_pure _ in "Hsrc".
-    iDestruct ("Hstrlen" $! _ _ O with "[] [$Hsrc]") as "Hstr2".
-    { rewrite /imm_stringRel. iExists _; eauto. }
-    iApply (rwp_wand with "[Hstr2 Hna]").
-    { wp_apply ("Hstr2" with "[$]"). }
-    iIntros (v) "(Hna&H)".
-    iDestruct "H" as (? (r1&Heq1&Heq2)) "(_&Hsrc&#Heval1)".
-    iFrame.
-    subst. wp_pures.
-    simpl fill. iExists _. iSplit; first eauto. iFrame.
-    iModIntro. rewrite /eval. iIntros (vb') "#HPre". iIntros (K') "H".
-    iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-    symmetry in Heq1. inversion_clear Heq1. subst.
-    iDestruct "Hs1" as (s1') "#Hinv1'".
-    iDestruct "Hs2" as (s2') "#Hinv2'".
-    iApply fupd_src_update.
-    iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-    iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-    iMod (stringRel_inv_acc with "Hinv1'") as "Hstr1'".
-    iMod (stringRel_inv_acc with "Hinv2'") as "Hstr2'".
-    iDestruct (stringRel_is_functional with "Hstr1' Hstr1") as %->.
-    iDestruct (stringRel_is_functional with "Hstr2' Hstr2") as %->.
-    iClear "Hstr1 Hstr2".
-    iRename "Hstr1'" into "Hstr1".
-    iRename "Hstr2'" into "Hstr2".
-    iDestruct "Hstr1" as (?? (->&->)) "(Hl1a&Hl1b)".
-    iDestruct "Hstr2" as (?? (->&->)) "(Hl2a&Hl2b)".
-    simpl src_string_is.
-    iDestruct "Hl1b" as (H1neq0'') "(Hpts1b&Hl1b)".
-    iDestruct "Hpts1b" as (?) "Hpts1b".
-    rewrite /Lev/lev/lev_template.
-    iModIntro.
-    do 12 src_pure _ in "H".
-    src_load in "H".
-    do 3 src_pure _ in "H".
-    rewrite bool_decide_false //; last first.
-    { intros Heq. inversion Heq. lia. }
-    do 1 src_pure _ in "H".
-    iDestruct "Hl2b" as (q2b') "Hl2b".
-    src_load in "H".
-    do 4 src_pure _ in "H".
-    iApply src_update_weak_src_update.
-    iDestruct ("Heval1" with "[]") as (v') "(Heval1'&Hrel)"; last first.
-    { iDestruct "Hrel" as %[? (->&->)]. iApply "Heval1'". eauto. }
-    rewrite /imm_stringRel. eauto.
-  }
-  simpl string_is.
-  iDestruct "Hl2a" as (H2neq0) "(Hpts2a&Hl2a)".
-  iDestruct "Hpts2a" as (q2a) "Hpts2a".
-  wp_load. wp_pures. wp_pure _; first solve_vals_compare_safe.
-  rewrite bool_decide_false //; last first.
-  { intros Heq. inversion Heq. lia. }
-  wp_pures. wp_pure _; first solve_vals_compare_safe.
-  rewrite /tf_implements.
-  simpl src_string_is.
-  iDestruct "Hl1b" as (H1neq0') "(Hpts1b&Hl1b)".
-  iDestruct "Hpts1b" as (?) "Hpts1b".
-  iDestruct "Hl2b" as (H2neq0') "(Hpts2b&Hl2b)".
-  iDestruct "Hpts2b" as (?) "Hpts2b".
-  do 6 src_pure _ in "Hsrc".
-  src_load in "Hsrc".
-  do 3 src_pure _ in "Hsrc".
-  rewrite bool_decide_false //; last first.
-  { intros Heq. inversion Heq. lia. }
-  do 1 src_pure _ in "Hsrc".
-  src_load in "Hsrc".
-  do 3 src_pure _ in "Hsrc".
-  rewrite bool_decide_false //; last first.
-  { intros Heq. inversion Heq. lia. }
-  do 2 src_pure _ in "Hsrc".
-  iAssert (pair_imm_stringRel (#(l1a +ₗ 1), #(l2a +ₗ 1)) (#(l1b +ₗ 1), #(l2b +ₗ 1))) as "#Hshift_both".
-  {
-    iExists #(l1a +ₗ 1), #(l2a +ₗ 1), _, _.
-    rewrite /imm_stringRel.
-    iSplit; first eauto.
-    iSplit; first eauto.
-    iSplitL "Hinv1".
-    { iExists _. iApply inv_stringRel_is_tl. iApply "Hinv1". }
-    { iExists _. iApply inv_stringRel_is_tl. iApply "Hinv2". }
-  }
-  iAssert (pair_imm_stringRel ((#l1a, #(l2a +ₗ 1)))%V ((#l1b, #(l2b +ₗ 1)))%V) as "#Hshift_right".
-  {
-    iExists #(l1a), #(l2a +ₗ 1), _, _.
-    rewrite /imm_stringRel.
-    iSplit; first eauto.
-    iSplit; first eauto.
-    iSplitL "Hinv1".
-    { iExists _. iApply "Hinv1". }
-    { iExists _. iApply inv_stringRel_is_tl. iApply "Hinv2". }
-  }
-  iAssert (pair_imm_stringRel (#(l1a +ₗ 1), #l2a) (#(l1b +ₗ 1), #l2b)) as "#Hshift_left".
-  {
-    iExists #(l1a +ₗ 1), #(l2a), _, _.
-    rewrite /imm_stringRel.
-    iSplit; first eauto.
-    iSplit; first eauto.
-    iSplitL "Hinv1".
-    { iExists _. iApply inv_stringRel_is_tl. iApply "Hinv1". }
-    { iExists _. iApply "Hinv2". }
-  }
-  case_bool_decide.
-  {
-    do 2 wp_pure _.
-    do 4 src_pure _ in "Hsrc".
-    rewrite /tf_implements.
-    iSpecialize ("IH" $! (#(l1a +ₗ 1), #(l2a +ₗ 1))%V _ O with "[$] Hsrc [$]").
-    iApply (rwp_wand with "[IH]").
-    { wp_apply "IH". }
-    iIntros (v) "($&H)".
-    iDestruct "H" as (? (m&Heq1&Heq2)) "(_&Hsrc&#Heval')".
-    subst. iExists m. iSplit; first done.
-    iFrame.
-    iModIntro. rewrite /eval. iIntros (vb') "#HPre". iIntros (K') "H".
-    iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-    symmetry in Heq1. inversion_clear Heq1. subst.
-    iDestruct "Hs1" as (s1') "#Hinv1'".
-    iDestruct "Hs2" as (s2') "#Hinv2'".
-    iApply fupd_src_update.
-    iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-    iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-    iMod (stringRel_inv_acc with "Hinv1'") as "Hstr1'".
-    iMod (stringRel_inv_acc with "Hinv2'") as "Hstr2'".
-    iDestruct (stringRel_is_functional with "Hstr1' Hstr1") as %->.
-    iDestruct (stringRel_is_functional with "Hstr2' Hstr2") as %->.
-    iClear "Hstr1 Hstr2".
-    iRename "Hstr1'" into "Hstr1".
-    iRename "Hstr2'" into "Hstr2".
-    iModIntro.
-    rewrite /Lev/lev/lev_template.
-    do 12 src_pure _ in "H".
-    iDestruct "Hstr1" as (?? (Heq1a&Heq1b)) "(Hl1a&Hl1b)".
-    iDestruct "Hstr2" as (?? (Heq2a&Heq2b)) "(Hl2a&Hl2b)".
-    simpl src_string_is.
-    iDestruct "Hl1b" as (H1neq0'') "(Hpts1b&Hl1b)".
-    iDestruct "Hpts1b" as (?) "Hpts1b".
-    rewrite ?Heq1a ?Heq1b ?Heq2a ?Heq2b.
-    src_load in "H".
-    do 3 src_pure _ in "H".
-    rewrite bool_decide_false //; last first.
-    { intros Heq. inversion Heq. lia. }
-    do 1 src_pure _ in "H".
-    iDestruct "Hl2b" as (H2neq0'') "(Hpts2b&Hl2b)".
-    iDestruct "Hpts2b" as (?) "Hpts2b".
-    src_load in "H".
-    do 3 src_pure _ in "H".
-    rewrite bool_decide_false //; last first.
-    { intros Heq. inversion Heq. lia. }
-    do 2 src_pure _ in "H".
-    rewrite bool_decide_true //; [].
-    do 4 src_pure _ in "H".
-    rewrite -?Heq1a -?Heq1b -?Heq2a -?Heq2b.
-    iApply src_update_weak_src_update.
-    iDestruct ("Heval'" with "[]") as (v') "(Heval1&Hrel)"; last first.
-    { iDestruct "Hrel" as %[? (->&->)]. iApply "Heval1". eauto. }
-    {
-      iExists _, _, _, _; repeat (iSplit; try iExists _; eauto).
-      { iApply inv_stringRel_is_tl. rewrite Heq1b. eauto. }
-      { iApply inv_stringRel_is_tl. rewrite Heq2b. eauto. }
-    }
-  }
-  do 3 wp_pure _.
-  do 3 src_pure _ in "Hsrc".
-  src_bind (lev _) in "Hsrc".
-  iDestruct ("IH" $! _ _ O with "Hshift_right Hsrc [$]") as "IH1".
-  wp_bind (g _).
-  iApply (rwp_wand with "[IH1]").
-  { wp_apply "IH1". }
-  iIntros (v) "(Hna&H)".
-  iDestruct "H" as (? (r1&Heq1&Heq2)) "(_&Hsrc&#Heval1)".
-  subst. wp_pures.
-  simpl fill.
-  do 1 src_pure _ in "Hsrc".
-
-  do 3 src_pure _ in "Hsrc".
-  src_bind (lev _) in "Hsrc".
-  iDestruct ("IH" $! _ _ O with "Hshift_left Hsrc [$]") as "IH2".
-  wp_bind (g _).
-  iApply (rwp_wand with "[IH2]").
-  { wp_apply "IH2". }
-  iIntros (v) "(Hna&H)".
-  iDestruct "H" as (? (r2&Heq1&Heq2)) "(_&Hsrc&#Heval2)".
-  subst. wp_pures.
-  simpl fill.
-  do 2 src_pure _ in "Hsrc".
-
-  do 3 src_pure _ in "Hsrc".
-  src_bind (lev _) in "Hsrc".
-  iDestruct ("IH" $! _ _ O with "Hshift_both Hsrc [$]") as "IH2".
-  wp_bind (g _).
-  iApply (rwp_wand with "[IH2]").
-  { wp_apply "IH2". }
-  iIntros (v) "(Hna&H)".
-  iDestruct "H" as (? (r3&Heq1&Heq2)) "(_&Hsrc&#Heval3)".
-  subst. wp_pures.
-  simpl fill.
-  do 2 src_pure _ in "Hsrc".
-
-  wp_bind (min3 _ _ _).
-  wp_apply (min3_spec with "[//]").
-  iIntros "_".
-  src_bind (min3 _ _ _) in "Hsrc".
-  iDestruct (eval_min3 with "Hsrc") as "Hsrc".
-  iApply (rwp_weaken with "[-Hsrc] Hsrc"); first done.
-  iIntros "Hsrc".
-  simpl fill.
-  src_pure _ in "Hsrc".
-  wp_pures. iFrame. iExists (1 + (min (min r1 r2) r3)%nat)%nat.
-  iSplit.
-  { iPureIntro. do 2 f_equal. lia. }
-  assert (#(1 + (r1 `min` r2) `min` r3)%nat =
-          #(1 + ((r1 `min` r2) `min` r3)%nat)) as ->.
-  { do 2 f_equal. lia. }
-  iFrame.
-  iModIntro. rewrite /eval. iIntros (vb') "#HPre". iIntros (K') "H".
-  iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-  symmetry in Heq1. inversion_clear Heq1. subst.
-  iDestruct "Hs1" as (s1') "#Hinv1'".
-  iDestruct "Hs2" as (s2') "#Hinv2'".
-  iApply fupd_src_update.
-  iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-  iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-  iMod (stringRel_inv_acc with "Hinv1'") as "Hstr1'".
-  iMod (stringRel_inv_acc with "Hinv2'") as "Hstr2'".
-  iDestruct (stringRel_is_functional with "Hstr1' Hstr1") as %->.
-  iDestruct (stringRel_is_functional with "Hstr2' Hstr2") as %->.
-  iClear "Hstr1 Hstr2".
-  iRename "Hstr1'" into "Hstr1".
-  iRename "Hstr2'" into "Hstr2".
-  iModIntro.
-  rewrite /Lev/lev/lev_template.
-  do 12 src_pure _ in "H".
-  iDestruct "Hstr1" as (?? (Heq1a&Heq1b)) "(Hl1a&Hl1b)".
-  iDestruct "Hstr2" as (?? (Heq2a&Heq2b)) "(Hl2a&Hl2b)".
-  simpl src_string_is.
-  iDestruct "Hl1b" as (H1neq0'') "(Hpts1b&Hl1b)".
-  iDestruct "Hpts1b" as (?) "Hpts1b".
-  rewrite ?Heq1a ?Heq1b ?Heq2a ?Heq2b.
-  src_load in "H".
-  do 3 src_pure _ in "H".
-  rewrite bool_decide_false //; last first.
-  { intros Heq. inversion Heq. lia. }
-  do 1 src_pure _ in "H".
-  iDestruct "Hl2b" as (H2neq0'') "(Hpts2b&Hl2b)".
-  iDestruct "Hpts2b" as (?) "Hpts2b".
-  src_load in "H".
-  do 3 src_pure _ in "H".
-  rewrite bool_decide_false //; last first.
-  { intros Heq. inversion Heq. lia. }
-  do 2 src_pure _ in "H".
-  rewrite bool_decide_false //; [].
-  do 1 src_pure _ in "H".
-  do 1 src_pure _ in "H".
-  do 1 src_pure _ in "H".
-  src_bind (_ (#_, #_)%V)%E in "H".
-  (* TODO: can't seem to bind this properly otherwise *)
-  rewrite fill_cons. simpl ectxi_language.fill_item.
-  iApply src_update_weak_src_update.
-  iDestruct ("Heval1" with "[]") as (r1') "(Heval1'&Hrel)"; [|
-  iDestruct "Hrel" as %[? (Heq1&->)]; iDestruct ("Heval1'" with "H") as "H"].
-  {
-      iExists _, _, _, _; repeat (iSplit; try iExists _; eauto).
-      { iApply inv_stringRel_is_tl. rewrite Heq1b Heq2a. eauto. }
-  }
-  iApply (src_update_bind with "[$H]").
-  iIntros "H".
-  simpl.
-  do 2 src_pure _ in "H".
-
-  do 2 src_pure _ in "H".
-  src_bind (_ (#_, #_)%V)%E in "H".
-  (* TODO: can't seem to bind this properly otherwise *)
-  rewrite fill_cons. simpl ectxi_language.fill_item.
-  iApply src_update_weak_src_update.
-  iDestruct ("Heval2" with "[]") as (r2') "(Heval2'&Hrel)"; [|
-  iDestruct "Hrel" as %[? (Heq2&->)]; iDestruct ("Heval2'" with "H") as "H"].
-  {
-      iExists _, _, _, _; repeat (iSplit; try iExists _; eauto).
-      { iApply inv_stringRel_is_tl. rewrite Heq1a Heq2b. eauto. }
-  }
-  iApply (src_update_bind with "[$H]").
-  iIntros "H".
-  simpl.
-  do 2 src_pure _ in "H".
-
-  do 3 src_pure _ in "H".
-  src_bind (_ (#_, #_)%V)%E in "H".
-  (* TODO: can't seem to bind this properly otherwise *)
-  rewrite fill_cons. simpl ectxi_language.fill_item.
-  iApply src_update_weak_src_update.
-  iDestruct ("Heval3" with "[]") as (r3') "(Heval3'&Hrel)"; [|
-    iDestruct "Hrel" as %[? (Heq3&->)]; iDestruct ("Heval3'" with "H") as "H"].
-  {
-      iExists _, _, _, _; repeat (iSplit; try iExists _; eauto).
-      { iApply inv_stringRel_is_tl. rewrite Heq1a Heq2b. eauto. }
-      { iApply inv_stringRel_is_tl. rewrite Heq1b Heq2a. eauto. }
-  }
-  iApply (src_update_bind with "[$H]").
-  iIntros "H".
-  simpl.
-  do 2 src_pure _ in "H".
-  rewrite -Heq1 -Heq2 -Heq3.
-
-  src_bind (min3 _ _ _) in "H".
-  iDestruct (eval_min3 with "[$]") as "H".
-  iApply src_update_weak_src_update.
-  iApply (src_update_bind with "[$H]").
-  iIntros "H". simpl.
-  do 1 src_pure _ in "H".
-  iApply weak_src_update_return.
-  iApply "H".
-  Qed.
-
-  Definition eq_pair : val := (λ: "n1" "n2", BinOp AndOp (Fst "n1" = Fst "n2") (Snd "n1" = Snd "n2")).
-
-  Lemma strlen_sound :
-    ⊢ tf_implements imm_stringRel natRel strlen strlen.
-  Proof.
-    iLöb as "IH".
-    iModIntro. iIntros (?? c K) "#HPre Hsrc Hna".
-    iDestruct "HPre" as (s) "#Hinv1".
-    rewrite {4}/strlen. wp_pure _. rewrite {1}/strlen_template. do 3 wp_pure _.
-    iPoseProof (strlen_fundamental_core strlen c K _ with "[Hsrc IH] Hna") as "H".
-    { iFrame "Hsrc IH". iExists _. eauto. }
-    iApply (rwp_wand with "H").
-    iIntros (v) "($&H)".
-    iDestruct "H" as (m ->) "(Hsrc&Hc&#Hexec)". iExists _. iFrame.
-    iSplitR; first eauto.
-    iModIntro. iIntros (x) "#Hrel". iExists #m. iSplit; last eauto.
-    iModIntro. iApply "Hexec". eauto.
-  Qed.
-
-  Lemma strlen_template_sound g:
-    ▷ tf_implements imm_stringRel natRel g strlen ⊢
-      SEQ (strlen_template g) ⟨⟨h, tf_implements imm_stringRel natRel h strlen⟩⟩.
-  Proof.
-    iIntros "#IH Hna". rewrite /strlen_template. wp_pures. iFrame.
-    iModIntro; iIntros (? ? c K) "HPre Hsrc Hna".
-    wp_pure _.
-    iDestruct "HPre" as (s1) "#Hinv1".
-    iPoseProof (strlen_fundamental_core g c K _ with "[$Hsrc $IH] Hna") as "H".
-    { iExists _. repeat iSplit; try iExists _; eauto. }
-    rewrite /Strlen.
-    iApply (rwp_wand with "H").
-    iIntros (v) "($&H)".
-    iDestruct "H" as (m ->) "(Hsrc&Hc&#Hexec)". iExists _. iFrame.
-    iSplitR; first eauto.
-    iModIntro. iIntros (x) "#Hrel". iExists #m. iSplit; last eauto.
-    iModIntro. iApply "Hexec". eauto.
-  Qed.
-
-  Lemma lev_sound:
-    ⊢ tf_implements pair_imm_stringRel natRel lev lev.
-  Proof.
-    iLöb as "IH".
-    iModIntro. iIntros (v v' c K) "#HPre Hsrc Hna".
-    iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-    iDestruct "Hs1" as (s1) "#Hinv1".
-    iDestruct "Hs2" as (s2) "#Hinv2".
-    rewrite {4}/lev. wp_pure _. rewrite {1}/lev_template. do 3 wp_pure _.
-    iPoseProof (lev_fundamental_core lev strlen c K (v1a, v2a)%V with "[Hsrc IH] Hna") as "H".
-    { iFrame "Hsrc". iSplitL.
-      { iNext. iApply strlen_sound. }
-      iFrame "IH".
-      { iExists _, _, _, _. repeat iSplit; try iExists _; eauto. }
-    }
-    rewrite /Lev/lev.
-    do 2 wp_pure _.
-    iApply (rwp_wand with "H").
-    iIntros (v) "($&H)".
-    iDestruct "H" as (m ->) "(Hsrc&Hc&#Hexec)". iExists _. iFrame.
-    iSplitR; first eauto.
-    iModIntro. iIntros (x) "#Hrel". iExists #m. iSplit; last eauto.
-    iModIntro. iApply "Hexec". eauto.
-  Qed.
-
-  Lemma lev_template'_sound g slen:
-    ▷ tf_implements imm_stringRel natRel slen strlen ∗
-    ▷ tf_implements pair_imm_stringRel natRel g lev ⊢
-      SEQ (lev_template' slen g) ⟨⟨h, tf_implements pair_imm_stringRel natRel h lev⟩⟩.
-  Proof.
-    iIntros "[#Hslen #IH] Hna". rewrite /lev_template'. wp_pures. iFrame.
-    iModIntro; iIntros (n n' c K) "HPre Hsrc Hna".
-    wp_pure _.
-    iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-    iDestruct "Hs1" as (s1) "#Hinv1".
-    iDestruct "Hs2" as (s2) "#Hinv2".
-    iPoseProof (lev_fundamental_core g slen c K (v1a, v2a)%V with "[$Hslen $Hsrc $IH] Hna") as "H".
-    { iExists _, _, _, _. repeat iSplit; try iExists _; eauto. }
-    rewrite /Lev.
-    iApply (rwp_wand with "H").
-    iIntros (v) "($&H)".
-    iDestruct "H" as (m ->) "(Hsrc&Hc&#Hexec)". iExists _. iFrame.
-    iSplitR; first eauto.
-    iModIntro. iIntros (x) "#Hrel". iExists #m. iSplit; last eauto.
-    iModIntro. iApply "Hexec". eauto.
-  Qed.
-
-  (* memoized versions *)
-  Context `{Sync: !inG Σ (authR (optionUR (exclR (gmapO val (valO SI)))))}.
-  Context `{Fin: FiniteBoundedExistential SI}.
-
-  Lemma lev_memoized:
-    $ (1%nat) ⊢ SEQ (memoize eq_pair lev) ⟨⟨ h, tf_implements pair_imm_stringRel natRel h lev ⟩⟩.
-  Proof using Sync Fin.
-    (* XXX: the iApply fails over typeclass resolution (?) if we don't do iStartProof *)
-    iStartProof. iIntros "Hc".
-    iApply (tf_memoize_spec _ _ (λ x, ∃ (l1 l2: loc), ⌜ x = (#l1, #l2)%V ⌝)%I (λ x1 x2, ⌜ x1 = x2 ⌝)%I);
-      [| | iSplit].
-    - iIntros (??) "HPre".
-      iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-      iDestruct "Hs1" as (s1) "#Hinv1".
-      iDestruct "Hs2" as (s2) "#Hinv2".
-      iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-      iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-      iDestruct "Hstr1" as (?? (->&->)) "(Hl1a&Hl1b)".
-      iDestruct "Hstr2" as (?? (->&->)) "(Hl2a&Hl2b)".
-      eauto.
-    - iIntros (??? ->); auto.
-    - rewrite /eqfun.  iIntros (??). iModIntro. iIntros (Φ) "(H1&H2) H".
-      iDestruct "H1" as %[l1 [l2 ->]].
-      iDestruct "H2" as %[l1' [l2' ->]].
-      rewrite /eq_pair.
-      wp_pures.
-      wp_pure _; first solve_vals_compare_safe.
-      wp_pure _.
-      case_bool_decide;
-       (wp_pures; wp_pure _; first solve_vals_compare_safe;
-        case_bool_decide; (wp_pures; iApply "H"; iSplitL; [| iSplitL]; eauto; iPureIntro; congruence)).
-    - iFrame. iApply lev_sound.
-  Qed.
-
-  Lemma lev_deep_memoized:
-    $ (1%nat) ∗ $ (1%nat) ⊢
-      SEQ (let: "strlen" := mem_rec eq_heaplang strlen_template in
-                 mem_rec eq_pair (lev_template "strlen"))
-      ⟨⟨ h, tf_implements pair_imm_stringRel natRel h lev ⟩⟩.
-  Proof using Sync Fin.
-    iStartProof. iIntros "(Hc1&Hc2) Hna".
-    wp_bind (mem_rec _ _).
-    iPoseProof (tf_mem_rec_spec imm_stringRel natRel
-                                (λ x, ∃ l1 : loc, ⌜ x = #l1%V ⌝)%I (λ x1 x2, ⌜ x1 = x2 ⌝)%I with "[Hc1] [$Hna]")
-    as "IH"; last (iApply (rwp_wand with "IH")).
-    { iIntros (??) "HPre". iDestruct "HPre" as (s1) "#Hinv1".
-      iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-      iDestruct "Hstr1" as (?? (->&->)) "(Hl1a&Hl1b)". eauto. }
-    { iIntros (??? ->); auto. }
-    {  iSplit.
-      { rewrite /eqfun.  iIntros (??). iModIntro. iIntros (Φ) "(H1&H2) H".
-        iDestruct "H1" as %[l1 ->].
-        iDestruct "H2" as %[l1' ->].
-        rewrite /eq_heaplang.
-        wp_pures.
-        wp_pure _; first solve_vals_compare_safe.
-        case_bool_decide; eauto; iApply "H"; eauto. }
-      iFrame.
-      iModIntro. iIntros.
-      iApply strlen_template_sound. eauto.
-    }
-    iIntros (h) "(Hna&#Himpl)".
-    wp_pures.
-    rewrite /lev_template. wp_pure _. wp_pure _.
-    iApply (tf_mem_rec_spec _ _ (λ x, ∃ (l1 l2: loc), ⌜ x = (#l1, #l2)%V ⌝)%I (λ x1 x2, ⌜ x1 = x2 ⌝)%I with "[Hc2] [$Hna]"); [| | iSplit].
-    - iIntros (??) "HPre".
-      iDestruct "HPre" as (v1a v2a v1b v2b Heq1 Heq2) "(Hs1&Hs2)". subst.
-      iDestruct "Hs1" as (s1) "#Hinv1".
-      iDestruct "Hs2" as (s2) "#Hinv2".
-      iMod (stringRel_inv_acc with "Hinv1") as "Hstr1".
-      iMod (stringRel_inv_acc with "Hinv2") as "Hstr2".
-      iDestruct "Hstr1" as (?? (->&->)) "(Hl1a&Hl1b)".
-      iDestruct "Hstr2" as (?? (->&->)) "(Hl2a&Hl2b)".
-      eauto.
-    - iIntros (??? ->); auto.
-    - rewrite /eqfun.  iIntros (??). iModIntro. iIntros (Φ) "(H1&H2) H".
-      iDestruct "H1" as %[l1 [l2 ->]].
-      iDestruct "H2" as %[l1' [l2' ->]].
-      rewrite /eq_pair.
-      wp_pures.
-      wp_pure _; first solve_vals_compare_safe.
-      wp_pure _.
-      case_bool_decide;
-       (wp_pures; wp_pure _; first solve_vals_compare_safe;
-        case_bool_decide; (wp_pures; iApply "H"; iSplitL; [| iSplitL]; eauto; iPureIntro; congruence)).
-    - iFrame. iModIntro. iIntros (g) "H".
-      iPoseProof (lev_template'_sound with "[H]") as "H".
-      { iSplitR.
-        * iApply "Himpl".
-        * iApply "H".
-      }
-      iApply "H".
-  Qed.
-End levenshtein.
-
diff --git a/theories/examples/refinements/refinement.v b/theories/examples/refinements/refinement.v
deleted file mode 100644
index 9adc3df8fea11a88347b6184bf1bf954fb321297..0000000000000000000000000000000000000000
--- a/theories/examples/refinements/refinement.v
+++ /dev/null
@@ -1,842 +0,0 @@
-From iris.program_logic.refinement Require Export ref_weakestpre ref_source seq_weakestpre.
-From iris.base_logic.lib Require Export invariants na_invariants.
-From iris.heap_lang Require Export lang lifting.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation metatheory.
-From iris.algebra Require Import auth gmap excl frac agree mlist.
-Set Default Proof Using "Type".
-
-Inductive rtc_list {A : Type} (R : relation A) : list A → Prop :=
-| rtc_list_nil : rtc_list R nil
-| rtc_list_once : ∀ x, rtc_list R [x]
-| rtc_list_l : ∀ x y l, R x y → rtc_list R (y :: l) → rtc_list R (x :: y :: l).
-
-Lemma rtc_list_r {A : Type} (R : relation A) (x y: A) (l: list A) :
-  R x y →
-  rtc_list R (l ++ [x]) →
-  rtc_list R (l ++ [x] ++ [y]).
-Proof.
-  rewrite app_assoc.
-  intros HR Hrtc.
-  remember (l ++ [x]) as l' eqn:Heql. revert x y HR l Heql; induction Hrtc; intros.
-  - apply rtc_list_once.
-  - symmetry in Heql. apply app_singleton in Heql as [(?&Heq)|(?&?)]; last by congruence.
-    apply rtc_list_l; last apply rtc_list_once.
-    inversion Heq; subst; eauto.
-  - destruct l0; first by (simpl in Heql; congruence).
-    inversion Heql; subst.
-    simpl; apply rtc_list_l; first done.
-    rewrite app_comm_cons. eapply IHHrtc; eauto.
-Qed.
-
-Lemma rtc_list_app_r {A: Type} (R: relation A) l1 l2:
-    rtc_list R (l1 ++ l2) → rtc_list R l2.
-Proof.
-  revert l2. induction l1; first done.
-  intros l2 Hrtc. inversion Hrtc as [| | ???? Hrtc' [Heq1 Heq2]].
-  - assert (l2 = []) as -> by (eapply app_eq_nil; eauto).
-    constructor.
-  - apply IHl1. rewrite -Heq2; eauto.
-Qed.
-
-Lemma rtc_list_rtc {A: Type} (R: relation A) (x y : A) (l : list A):
-  rtc_list R ([x] ++ l ++ [y]) →
-  rtc R x y.
-Proof.
-  revert x y.
-  induction l as [| a l IHl]; intros x y Hrtc.
-  - inversion Hrtc; subst; eauto using rtc_l, rtc_refl.
-  - inversion Hrtc; subst.
-    apply (rtc_l _ _ a); auto.
-Qed.
-
-Lemma rtc_list_lookup_last_rtc {A: Type} (R: relation A) (x y : A) (l : list A) (i: nat) :
-  (l ++ [y]) !! i = Some x →
-  rtc_list R (l ++ [y]) →
-  rtc R x y.
-Proof.
-  rewrite lookup_app_Some.
-  intros [Hl|Hr].
-  * apply elem_of_list_split_length in Hl.
-    destruct Hl as (l1&l2&Heq&Hlen). subst.
-    rewrite -app_assoc => Hrtc. apply rtc_list_app_r in Hrtc.
-    rewrite -app_comm_cons in Hrtc. eapply rtc_list_rtc; eauto.
-    simpl; eauto.
-  * destruct Hr as (_&Hlookup). intros.
-    destruct (i - length l)%nat.
-    ** rewrite /= in Hlookup. inversion Hlookup. apply rtc_refl.
-    ** exfalso. rewrite /= lookup_nil in Hlookup. congruence.
-Qed.
-
-(* HeapLang <={log} HeapLang *)
-Definition tpoolUR SI : ucmraT SI := gmapUR nat (exclR (exprO SI)).
-Definition cfgUR SI := prodUR (tpoolUR SI) (gen_heapUR SI loc val).
-
-Class rheapPreG {SI} (Σ: gFunctors SI) := RHeapPreG {
-  rheapPreG_heapG :> heapPreG Σ;
-  rheapPreG_ghost_repr :> inG Σ (authR (cfgUR SI)); (* the source ghost state *)
-  rheapPreG_fmlistG :> fmlistG (cfg heap_lang) Σ;
-}.
-
-Class rheapG {SI} (Σ: gFunctors SI) := RHeapG {
-  rheapG_heapG :> heapG Σ;
-  rheapG_ghost_repr :> inG Σ (authR (cfgUR SI)); (* the source ghost state *)
-  rheapG_ghost_name: gname;
-  rheapG_fmlistG :> fmlistG (cfg heap_lang) Σ;
-  rheapG_fmlist_name: gname;
-}.
-
-Section source_ghost_state.
-  Context {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ}.
-
-  Fixpoint to_tpool_go (i : nat) (tp : list expr) : tpoolUR SI :=
-    match tp with
-    | [] => ∅
-    | e :: tp => <[i:=Excl e]>(to_tpool_go (S i) tp)
-    end.
-  Definition to_tpool : list expr → tpoolUR SI := to_tpool_go 0.
-
-  Definition heapS_mapsto (l : loc) (q : Qp) (v: val) : iProp Σ :=
-    own rheapG_ghost_name (◯ (∅, {[ l := (q, to_agree v) ]})).
-
-  Definition tpool_mapsto (j : nat) (e: expr) : iProp Σ :=
-    own rheapG_ghost_name (◯ ({[ j := Excl e ]}, ∅)).
-
-  Global Instance heapS_mapsto_timeless l q v : Timeless (heapS_mapsto l q v).
-  Proof. apply _. Qed.
-
-  Typeclasses Opaque heapS_mapsto tpool_mapsto.
-
-
-  Section thread_pool_conversion.
-  Open Scope nat.
-  (** Conversion to tpools and back *)
-  Lemma to_tpool_valid es : ✓ to_tpool es.
-  Proof.
-    rewrite /to_tpool. move: 0.
-    induction es as [|e es]=> n //; simpl. by apply insert_valid.
-  Qed.
-
-  Lemma tpool_lookup tp j : to_tpool tp !! j = Excl <$> tp !! j.
-  Proof.
-    cut (∀ i, to_tpool_go i tp !! (i + j) = Excl <$> tp !! j).
-    { intros help. apply (help 0). }
-    revert j. induction tp as [|e tp IH]=> //= -[|j] i /=.
-    - by rewrite Nat.add_0_r lookup_insert.
-    - by rewrite -Nat.add_succ_comm lookup_insert_ne; last lia.
-  Qed.
-  Lemma tpool_lookup_Some tp j e : to_tpool tp !! j = Excl' e → tp !! j = Some e.
-  Proof. rewrite tpool_lookup fmap_Some. naive_solver. Qed.
-  Hint Resolve tpool_lookup_Some : core.
-
-  Lemma to_tpool_insert tp j e :
-    j < length tp →
-    to_tpool (<[j:=e]> tp) = <[j:=Excl e]> (to_tpool tp).
-  Proof.
-    intros. apply: map_eq=> i. destruct (decide (i = j)) as [->|].
-    - by rewrite tpool_lookup lookup_insert list_lookup_insert.
-    - rewrite tpool_lookup lookup_insert_ne // list_lookup_insert_ne //.
-      by rewrite tpool_lookup.
-  Qed.
-  Lemma to_tpool_insert' tp j e :
-    is_Some (to_tpool tp !! j) →
-    to_tpool (<[j:=e]> tp) = <[j:=Excl e]> (to_tpool tp).
-  Proof.
-    rewrite tpool_lookup fmap_is_Some lookup_lt_is_Some. apply to_tpool_insert.
-  Qed.
-
-  Lemma to_tpool_snoc tp e :
-    to_tpool (tp ++ [e]) = <[length tp:=Excl e]>(to_tpool tp).
-  Proof.
-    intros. apply: map_eq=> i.
-    destruct (lt_eq_lt_dec i (length tp)) as [[?| ->]|?].
-    - rewrite lookup_insert_ne; last lia. by rewrite !tpool_lookup lookup_app_l.
-    - by rewrite lookup_insert tpool_lookup lookup_app_r // Nat.sub_diag.
-    - rewrite lookup_insert_ne; last lia.
-      rewrite !tpool_lookup ?lookup_ge_None_2 ?app_length //=;
-      change (ofe_car _ (exprO SI)) with expr; lia.
-  Qed.
-
-  Lemma tpool_singleton_included tp j e :
-    {[j := Excl e]} ≼ to_tpool tp → tp !! j = Some e.
-  Proof.
-    move=> /singleton_included [ex [/leibniz_equiv_iff]].
-    rewrite tpool_lookup fmap_Some=> [[e' [-> ->]] /Excl_included ?]. by f_equal.
-  Qed.
-  Lemma tpool_singleton_included' tp j e :
-    {[j := Excl e]} ≼ to_tpool tp → to_tpool tp !! j = Excl' e.
-  Proof. rewrite tpool_lookup. by move=> /tpool_singleton_included=> ->. Qed.
-
-End thread_pool_conversion.
-
-End source_ghost_state.
-Notation "l '↦s{' q } v" := (heapS_mapsto l q v) (at level 20, q at level 50, format "l  '↦s{' q }  v") : bi_scope.
-Notation "l '↦s' v" := (heapS_mapsto l 1 v) (at level 20) : bi_scope.
-Notation "j ⤇ e" := (tpool_mapsto j e) (at level 20) : bi_scope.
-Notation src e := (0 ⤇ e)%I.
-
-
-Definition heap_srcT : Set := (list expr * (gmap loc val * gmap proph_id unit)).
-Definition to_cfg '(es, (h, m)): cfg heap_lang := (es, {| heap := h; used_proph_id := {| mapset.mapset_car := m |} |}).
-Global Instance heap_lang_source {SI} {Σ: gFunctors SI} `{!rheapG Σ}: source Σ heap_srcT := {|
-  source_rel := λ s s', erased_step (to_cfg s) (to_cfg s');
-  source_interp := (λ '(tp, (h, proph)), own rheapG_ghost_name (● ((to_tpool tp, to_gen_heap SI h): cfgUR SI)) ∗
-                                             ∃ l, let l' := (l ++ [to_cfg (tp, (h, proph))]) in
-                                                  ⌜rtc_list (erased_step) l'⌝ ∗
-                                                  fmlist rheapG_fmlist_name 1 l')%I
-|}.
-
-
-Section heap_lang_source_steps.
-
-    Context {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)}.
-
-    (* we use stuttering heap lang as a source *)
-    Global Instance: source Σ (heap_srcT * nat) | 0 := _.
-
-    Lemma step_insert tp j (e: expr) σ e' σ' efs κ:
-      tp !! j = Some e → prim_step e σ κ e' σ' efs →
-      erased_step (tp, σ) (<[j:= e']> tp ++ efs, σ').
-    Proof.
-      intros. rewrite -(take_drop_middle tp j e) //.
-      rewrite insert_app_r_alt take_length_le ?Nat.sub_diag /=;
-        eauto using lookup_lt_Some, Nat.lt_le_incl.
-      rewrite -(assoc_L (++)) /=. exists κ.
-      eapply step_atomic; eauto.
-    Qed.
-
-
-    Lemma pure_step_prim_step (e1 e2: expr) σ:
-      pure_step e1 e2 → prim_step e1 σ [] e2 σ [].
-    Proof.
-      destruct 1 as [safe det]. destruct (safe σ) as (e' & σ' & efs & step).
-      by specialize (det σ [] e' σ' efs step) as (_ & -> & -> & ->).
-    Qed.
-
-
-    (* allocate stuttering budget post-hoc *)
-    Lemma step_frame (c1 c2: heap_srcT) (n m k: nat):
-      (c1, n) ↪ (c2, m) → (c1, (n + k)%nat) ↪ (c2, (m + k)%nat).
-    Proof.
-      inversion 1; subst.
-      - by apply lex_left.
-      - apply lex_right, auth_source_step_frame; eauto; done.
-    Qed.
-
-    Lemma steps_frame (c1 c2: heap_srcT) (n m k: nat):
-      (c1, n) ↪⁺ (c2, m) → (c1, (n + k)%nat) ↪⁺ (c2, (m + k)%nat).
-    Proof.
-      intros Hsteps.
-      remember (c1, n) as p. revert n c1 Heqp.
-      remember (c2, m) as q. revert m c2 Heqq.
-      induction Hsteps as [? ? Hstep|p [c' m'] q Hstep Hsteps]; intros n c2 -> m c1 ->.
-      - apply tc_once, step_frame, Hstep.
-      - eapply tc_l; first eapply step_frame, Hstep.
-        by eapply IHHsteps.
-    Qed.
-
-    Lemma step_add_stutter (c1 c2: heap_srcT) (n m: nat) c:
-      (c1, n) ↪⁺ (c2, m) → c1 ≠ c2 → (c1, n) ↪⁺ (c2, (m + c)%nat).
-    Proof.
-      intros Hsteps.
-      remember (c1, n) as p. revert n c1 Heqp.
-      remember (c2, m) as q. revert m c2 Heqq.
-      induction Hsteps as [? ? Hstep|p [c2 m] q Hstep Hsteps]; intros k c3 -> n c1 -> Hneq.
-      - inversion Hstep; subst.
-        + by eapply tc_once, lex_left.
-        + naive_solver.
-      - inversion Hstep; subst.
-        + eapply tc_l; first apply lex_left; eauto.
-          eapply steps_frame, Hsteps.
-        + eapply tc_l; first apply lex_right; eauto.
-    Qed.
-
-
-    Lemma step_inv_alloc c E P j e1:
-      (j ⤇ e1 -∗ src_update E P) ∗ (P -∗ ∃ e2, j ⤇ e2 ∗ ⌜e2 ≠ e1⌝)
-      ⊢ j ⤇ e1 -∗ src_update E (P ∗ $ c).
-    Proof.
-      rewrite /src_update. iIntros "[Hupd HP] Hj".
-      iIntros ([[tp [h m]] n]) "[Hsrc Hcred]".
-      iDestruct "Hsrc" as "(Hsrc&Hl)".
-      iDestruct (own_valid_2 with "Hsrc Hj") as %[[Htp%tpool_singleton_included'%tpool_lookup_Some _]%prod_included _]%auth_both_valid.
-      iSpecialize ("Hupd" with "Hj"). iMod ("Hupd" $! (tp, (h, m), n) with "[$Hsrc $Hl $Hcred]") as ([[tp' [h' m']] m''] Hsteps) "[[[Hsrc Hsrcl] Hcred] P]".
-      iAssert (⌜∃ e2, tp' !! j = Some e2 ∧ e2 ≠ e1⌝)%I as %Htp'; last destruct Htp' as [e2 [Htp' Hneq]].
-      { iDestruct ("HP" with "P") as (e2) "[Hj %]".
-        iDestruct (own_valid_2 with "Hsrc Hj") as %[[Htp'%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-        iPureIntro; exists e2. split; first eapply tpool_lookup_Some, Htp'. done.
-      }
-      iMod (own_update _ (● m'')  (● (m'' + c)%nat ⋅ ◯ c) with "Hcred") as "[Hnat Hc]".
-      { eapply auth_update_alloc, nat_local_update. rewrite /ε //= /nat_unit. }
-      iModIntro. iExists (tp', (h', m'), (m'' + c)%nat). iFrame.
-      iPureIntro. apply step_add_stutter; eauto.
-      injection 1 as -> ->.
-      eapply Hneq. eapply Some_inj. rewrite -Htp -Htp' //=.
-    Qed.
-
-
-    (* stuttering rule *)
-    Lemma step_stutter E c:
-      srcF (natA SI) (S c) ⊢ src_update E (srcF (natA SI) c).
-    Proof.
-      rewrite /src_update.
-      iIntros "Hf" ([[tp σ] n]) "[H● Hnat]".
-      iDestruct (own_valid_2 with "Hnat Hf") as %[Hle%nat_included _]%auth_both_valid.
-      destruct n as [|n]; first lia.
-      iMod (own_update_2 _ (● (S n))  (◯ (S c)) (● n ⋅ ◯ c) with "Hnat Hf") as "[Hnat Hc]".
-      { eapply auth_update, nat_local_update. lia. }
-      iModIntro. iExists (tp, σ, n); iFrame.
-      iPureIntro. apply tc_once, lex_right; simpl; lia.
-    Qed.
-
-    Lemma src_log E j (e: expr) :
-      j ⤇ e ⊢ weak_src_update E (j ⤇ e ∗
-              ∃ tp σ i, ⌜ tp !! j = Some e ⌝ ∗ fmlist_idx rheapG_fmlist_name i (to_cfg (tp, σ))).
-    Proof.
-      iIntros "Hj".
-      rewrite /weak_src_update /tpool_mapsto /source_interp //=.
-      iIntros ([[tp [h m]] n]) "[[H● Hl] Hnat]".
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iDestruct "Hl" as (l Htrace) "Hfmlist".
-      iMod (fmlist_get_lb with "Hfmlist") as "(Hfmlist&Hlb)".
-      iDestruct (fmlist_lb_to_idx _ _ (length l) with "Hlb") as "Hidx".
-      { rewrite lookup_app_r; last lia. replace (length l - length l)%nat with O by lia. rewrite //. }
-      iModIntro. iExists (tp, (h, m), n). iFrame.
-      iSplit; first eauto. iSplit.
-      { iExists _. iFrame. eauto. }
-      iExists tp, (h, m), (length l).
-      iSplit; eauto.
-      iPureIntro. eapply (tpool_lookup_Some (SI:=SI)); auto.
-    Qed.
-
-    Lemma src_get_trace' j (e: expr) i cfg σ :
-      j ⤇ e ∗ fmlist_idx rheapG_fmlist_name i cfg ∗ source_interp σ -∗
-              j ⤇ e ∗
-              source_interp σ ∗
-              ∃ tp σ, ⌜ tp !! j = Some e ∧ rtc erased_step cfg (to_cfg (tp, σ)) ⌝.
-    Proof.
-      iIntros "(Hj&Hidx&Hinterp)".
-      rewrite /tpool_mapsto /source_interp //=.
-      destruct σ as [[tp [h m]] n].
-      iDestruct "Hinterp" as "[[H● Hl] Hnat]".
-      iDestruct "Hl" as (l Htrace) "Hfmlist".
-      iDestruct (fmlist_idx_agree_2 with "[$] [$]") as %Hlookup.
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iFrame.
-      iSplit; first eauto.
-      iExists tp, (h, m).
-      iPureIntro. split.
-      * eapply (tpool_lookup_Some (SI:=SI)); auto.
-      * eapply rtc_list_lookup_last_rtc; eauto.
-    Qed.
-
-    Lemma src_get_trace E j (e: expr) i cfg :
-      j ⤇ e ∗ fmlist_idx rheapG_fmlist_name i cfg ⊢ weak_src_update E (j ⤇ e ∗
-              ∃ tp σ, ⌜ tp !! j = Some e ∧ rtc erased_step cfg (to_cfg (tp, σ)) ⌝).
-    Proof.
-      iIntros "(Hj&Hidx)".
-      rewrite /weak_src_update /tpool_mapsto /source_interp //=.
-      iIntros ([[tp [h m]] n]) "[[H● Hl] Hnat]".
-      iDestruct "Hl" as (l Htrace) "Hfmlist".
-      iDestruct (fmlist_idx_agree_2 with "[$] [$]") as %Hlookup.
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iModIntro. iExists (tp, (h, m), n). iFrame.
-      iSplit; first eauto. iSplit.
-      { iExists _. iFrame. eauto. }
-      iExists tp, (h, m).
-      iPureIntro. split.
-      * eapply (tpool_lookup_Some (SI:=SI)); auto.
-      * eapply rtc_list_lookup_last_rtc; eauto.
-    Qed.
-
-    (* operational rules *)
-    Lemma step_pure E j (e1 e2: expr):
-      pure_step e1 e2 → j ⤇ e1 ⊢ src_update E (j ⤇ e2).
-    Proof.
-      iIntros (Hp) "Hj"; rewrite /src_update /tpool_mapsto /source_interp //=.
-      iIntros ([[tp [h m]] n]) "[[H● Hl] Hnat]".
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iMod (own_update_2 with "H● Hj") as "[H● Hj]".
-      { eapply auth_update, prod_local_update_1, singleton_local_update; eauto.
-        by eapply (exclusive_local_update) with (x' := Excl e2). }
-      iDestruct "Hl" as (l Htrace) "Hfmlist".
-      iMod (fmlist_update_snoc (to_cfg (<[j:= e2]> tp, (h, m))) with "[$]") as "(Hfmlist&_)".
-      iFrame "Hj". iModIntro. iExists (((<[j:= e2]> tp), (h, m)), n).
-      rewrite to_tpool_insert'; eauto; iFrame.
-      iSplit.
-      - iPureIntro.
-        replace (<[j:=e2]> tp) with (<[j:=e2]> tp ++ []) by rewrite right_id_L //=.
-        eapply tc_once, lex_left, step_insert; first by eapply tpool_lookup_Some.
-        apply pure_step_prim_step, Hp.
-      - iExists _. iFrame. iPureIntro. rewrite -app_assoc. apply rtc_list_r; auto.
-        replace (<[j:=e2]> tp) with (<[j:=e2]> tp ++ []) by rewrite right_id_L //=.
-        eapply step_insert; first by eapply tpool_lookup_Some.
-        apply pure_step_prim_step, Hp.
-    Qed.
-
-    Lemma steps_pure n E j (e1 e2: expr):
-      nsteps pure_step (S n) e1 e2 → j ⤇ e1 ⊢ src_update E (j ⤇ e2).
-    Proof.
-      remember (S n) as m. intros H; revert n Heqm; induction H as [|? e1 e2 e3 Hstep Hsteps]; intros m.
-      - discriminate 1.
-      - injection 1 as ->. destruct m.
-        + inversion Hsteps; subst. by apply step_pure.
-        + iIntros "P". iApply src_update_bind; iSplitL.
-          * iApply step_pure; eauto.
-          * by iApply IHHsteps.
-    Qed.
-
-    Lemma steps_pure_exec E j e1 e2 φ n:
-      PureExec φ (S n) e1 e2 → φ → j ⤇ e1 ⊢ src_update E (j ⤇ e2).
-    Proof.
-      intros Hp Hφ. specialize (pure_exec Hφ); eapply steps_pure.
-    Qed.
-
-    Lemma step_load E j K (l: loc) q v:
-      j ⤇ fill K (Load #l) ∗ l ↦s{q} v ⊢ src_update E (j ⤇ fill K (of_val v) ∗ l ↦s{q} v).
-    Proof.
-      iIntros "[Hj Hl]"; rewrite /src_update /tpool_mapsto /source_interp //=.
-      iIntros ([[tp [h m]] n]) "[[H● Hfmlist] Hnat]".
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iDestruct (own_valid_2 with "H● Hl") as %[[_ ?%gen_heap_singleton_included]%prod_included ?]%auth_both_valid.
-      iMod (own_update_2 with "H● Hj") as "[H● Hj]".
-      { by eapply auth_update, prod_local_update_1, singleton_local_update,
-          (exclusive_local_update _ (Excl (fill K (of_val v)))). }
-      iDestruct "Hfmlist" as (tr Htrace) "Hfmlist".
-      iMod (fmlist_update_snoc (to_cfg (<[j:= fill K (of_val v)]> tp, (h, m))) with "[$]") as "(Hfmlist&_)".
-      iFrame "Hj Hl". iModIntro. iExists (((<[j:=fill K (of_val v)]> tp), (h, m)), n).
-      rewrite to_tpool_insert'; last eauto. iFrame. iSplit.
-      - iPureIntro.
-        replace (<[j:=fill K v]> tp) with (<[j:=fill K v]> tp ++ []) by rewrite right_id_L //=.
-        eapply tc_once, lex_left, step_insert; first by eapply tpool_lookup_Some.
-        apply fill_prim_step, head_prim_step.
-        econstructor; eauto.
-      - iExists _. iFrame. iPureIntro. rewrite -app_assoc. apply rtc_list_r; auto.
-        replace (<[j:=fill K v]> tp) with (<[j:=fill K v]> tp ++ []) by rewrite right_id_L //=.
-        eapply step_insert; first by eapply tpool_lookup_Some.
-        apply fill_prim_step, head_prim_step.
-        econstructor; eauto.
-    Qed.
-
-    Lemma step_store E j K (l: loc) (v v': val):
-      j ⤇ fill K (Store #l v) ∗ l ↦s v' ⊢ src_update E (j ⤇ fill K #() ∗ l ↦s v).
-    Proof.
-      iIntros "[Hj Hl]"; rewrite /src_update /tpool_mapsto /heapS_mapsto /source_interp //=.
-      iIntros ([[tp [h m]] n]) "[[H● Hfmlist] Hnat]".
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iDestruct (own_valid_2 with "H● Hl") as %[[_ Hl%gen_heap_singleton_included]%prod_included ?]%auth_both_valid.
-      iMod (own_update_2 with "H● Hj") as "[H● Hj]".
-      { by eapply auth_update, prod_local_update_1, singleton_local_update,
-          (exclusive_local_update _ (Excl (fill K (of_val #())))). }
-      iMod (own_update_2 with "H● Hl") as "[H● Hl]".
-      { eapply auth_update, prod_local_update_2, singleton_local_update,
-        (exclusive_local_update _ (1%Qp, to_agree v)); last done.
-      by rewrite /to_gen_heap lookup_fmap Hl. }
-      iDestruct "Hfmlist" as (tr Htrace) "Hfmlist".
-      iMod (fmlist_update_snoc (to_cfg (<[j:= fill K (of_val #())]> tp, (<[l:=v]>h, m))) with "[$]") as
-          "(Hfmlist&_)".
-      iFrame "Hj Hl". iExists (((<[j:=fill K (of_val #())]> tp), (<[l:=v]> h, m)), n).
-      rewrite -to_gen_heap_insert -to_tpool_insert' //=; eauto.
-      iModIntro. iFrame. iSplit.
-      - iPureIntro.
-        replace (<[j:=fill K #()]> tp) with (<[j:=fill K #()]> tp ++ []) by rewrite right_id_L //=.
-        eapply tc_once, lex_left, step_insert; first by eapply tpool_lookup_Some.
-        apply fill_prim_step, head_prim_step.
-        econstructor; eauto.
-      - iExists _. iFrame. iPureIntro. rewrite -app_assoc. apply rtc_list_r; auto.
-        replace (<[j:=fill K #()]> tp) with (<[j:=fill K #()]> tp ++ []) by rewrite right_id_L //=.
-        eapply step_insert; first by eapply tpool_lookup_Some.
-        apply fill_prim_step, head_prim_step.
-        econstructor; eauto.
-    Qed.
-
-    Lemma step_alloc E j K (v : val):
-      j ⤇ fill K (Alloc v)  ⊢ src_update E (∃ l: loc, j ⤇ fill K #l ∗ l ↦s v).
-    Proof.
-      iIntros "Hj"; rewrite /src_update /tpool_mapsto /heapS_mapsto /source_interp //=.
-      iIntros ([[tp [h m]] n]) "[[H● Hfmlist] Hnat]".
-      destruct (exist_fresh (dom (gset loc) h)) as [l Hl%not_elem_of_dom].
-      iDestruct (own_valid_2 with "H● Hj") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      iMod (own_update_2 with "H● Hj") as "[H● Hj]".
-      { by eapply auth_update, prod_local_update_1, singleton_local_update,
-          (exclusive_local_update _ (Excl (fill K (of_val #l)))). }
-      iMod (own_update with "H●") as "[H● Hl]".
-      { eapply auth_update_alloc, prod_local_update_2, (alloc_singleton_local_update _ l (1%Qp,to_agree v)); last done.
-        by apply lookup_to_gen_heap_None. }
-      iDestruct "Hfmlist" as (tr Htrace) "Hfmlist".
-      iMod (fmlist_update_snoc (to_cfg (<[j:= fill K (of_val #l)]> tp, (<[l:=v]>h, m))) with "[$]") as
-          "(Hfmlist&_)".
-      iModIntro. iExists (((<[j:=fill K (of_val #l)]> tp), (<[l:=v]> h, m)), n).
-      rewrite -to_gen_heap_insert to_tpool_insert' //=; eauto. iFrame.
-      iSplitR; [| iSplitL "Hfmlist"]; last by iExists l; iFrame.
-      - iPureIntro.
-        replace (<[j:=fill K #l]> tp) with (<[j:=fill K #l]> tp ++ []) by rewrite right_id_L //=.
-        eapply tc_once, lex_left, step_insert; first by eapply tpool_lookup_Some.
-        apply fill_prim_step, head_prim_step.
-        pose proof (AllocNS 1 v {| heap := h; used_proph_id := {| mapset.mapset_car := m |} |} l) as H.
-        rewrite state_init_heap_singleton in H; simpl in H. apply H; first lia.
-        intros i ??; assert (i = 0) as -> by lia; simpl; rewrite loc_add_0 //=.
-      - iExists _. iFrame. iPureIntro. rewrite -app_assoc. apply rtc_list_r; auto.
-        replace (<[j:=fill K #l]> tp) with (<[j:=fill K #l]> tp ++ []) by rewrite right_id_L //=.
-        eapply step_insert; first by eapply tpool_lookup_Some.
-        apply fill_prim_step, head_prim_step.
-        pose proof (AllocNS 1 v {| heap := h; used_proph_id := {| mapset.mapset_car := m |} |} l) as H.
-        rewrite state_init_heap_singleton in H; simpl in H. apply H; first lia.
-        intros i ??; assert (i = 0) as -> by lia; simpl; rewrite loc_add_0 //=.
-    Qed.
-
-End heap_lang_source_steps.
-
-
-(* some proof automation for source languages *)
-From iris.proofmode Require Import tactics coq_tactics reduction.
-Ltac strip_ectx e cb :=
-  match e with
-  | fill ?K ?e' => strip_ectx e' ltac:(fun K' e'' => match K' with nil => cb K e'' | _ => cb (K ++ K') e'' end)
-  | _ => cb (@nil ectx_item) e
-  end.
-
-Ltac src_bind_core e efoc cb :=
-    strip_ectx e ltac:(fun K e' => reshape_expr e' ltac:(fun K' e'' => unify e'' efoc; cb (K' ++ K) e'')).
-
-Ltac src_bind_core' e cb :=
-    strip_ectx e ltac:(fun K e' => reshape_expr e' ltac:(fun K' e'' => cb (K' ++ K) e'')).
-
-Lemma src_change e1 e2 {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)} j Δ (G: iProp Σ):
-  e1 = e2 →
-  envs_entails Δ (j ⤇ e2 -∗ G) →
-  envs_entails Δ (j ⤇ e1 -∗ G).
-Proof. by intros ->. Qed.
-
-Tactic Notation "src_bind" open_constr(efoc) :=
-  match goal with
-  | [|- envs_entails ?Δ (?j ⤇ ?e -∗ ?G)] =>
-    src_bind_core e efoc ltac:(fun K e' => apply (src_change e (fill K e')); first reflexivity)
-  end.
-
-Tactic Notation "src_bind" open_constr(efoc) "in" constr(H) :=
-  iRevert H;
-  src_bind efoc;
-  last iIntros H.
-
-Lemma tac_src_pures_rwp e1 e2 {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)}
-      φ e Δ j E s Φ:
-  PureExec φ 1 e1 e2 →
-  to_val e = None →
-  φ →
-  envs_entails Δ (j ⤇ e2 -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (j ⤇ e1 -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ? ? ? ->.
-  iIntros "H Hj".  iApply (rwp_weaken with "H"); auto.
-  by iApply @steps_pure_exec.
-Qed.
-
-Lemma tac_src_pures e1 e2 {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)}
-      φ Δ j E P:
-  PureExec φ 1 e1 e2 →
-  φ →
-  envs_entails Δ (j ⤇ e2 -∗ weak_src_update E P) →
-  envs_entails Δ (j ⤇ e1 -∗ src_update E P).
-Proof.
-  rewrite envs_entails_eq=> ? ? ->.
-  iIntros "H Hj".
-  iApply (weak_src_update_bind_r with "[$H Hj]").
-  by iApply @steps_pure_exec.
-Qed.
-
-Lemma tac_src_load_rwp {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)}
-      e s Φ Δ E i j K l q v:
-  to_val e = None →
-  envs_lookup i Δ = Some (false, l ↦s{q} v)%I →
-  envs_entails Δ (j ⤇ fill K (Val v) -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (j ⤇ fill K (Load (LitV l)) -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ?? Henvs.
-  iIntros "H Hj".
-  rewrite envs_lookup_split //.
-  iDestruct "H" as "(Hl&Hw)".
-  iApply (rwp_weaken with "[Hw] [Hl Hj]"); first done; last first.
-  { iApply step_load. iFrame. }
-  iIntros "(Hj&Hl)".
-  iSpecialize ("Hw" with "[$]"). iApply (Henvs with "[$] [$]").
-Qed.
-
-Lemma tac_src_load {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)}
-      Δ E P i j K l q v:
-  envs_lookup i Δ = Some (false, l ↦s{q} v)%I →
-  envs_entails Δ (j ⤇ fill K (Val v) -∗ weak_src_update E P) →
-  envs_entails Δ (j ⤇ fill K (Load (LitV l)) -∗ src_update E P).
-Proof.
-  rewrite envs_entails_eq=> ? Henvs.
-  iIntros "H Hj".
-  rewrite envs_lookup_split //.
-  iDestruct "H" as "(Hl&Hw)".
-  iApply (weak_src_update_bind_r with "[-]").
-  iSplitL "Hl Hj".
-  { iApply step_load. iFrame. }
-  iIntros "(Hj&Hl)".
-  iApply (Henvs with "[Hw Hl] Hj").
-  by iApply "Hw".
-Qed.
-
-Lemma tac_src_store {SI: indexT} `{Σ: gFunctors SI} `{!rheapG Σ} `{!auth_sourceG Σ (natA SI)}
-      Δ Δ' E P i j K l v v':
-  envs_lookup i Δ = Some (false, l ↦s v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦s v')) Δ = Some Δ' →
-  envs_entails Δ' (j ⤇ fill K (Val $ LitV LitUnit) -∗ weak_src_update E P) →
-  envs_entails Δ (j ⤇ fill K (Store (LitV l) (Val v')) -∗ src_update E P).
-Proof.
-  rewrite envs_entails_eq=> ?? Henvs.
-  iIntros "H Hj".
-  rewrite envs_simple_replace_sound //.
-  iDestruct "H" as "(Hl&Hw)".
-  iApply (weak_src_update_bind_r with "[-]").
-  iSplitL "Hl Hj".
-  { iApply step_store. iFrame. }
-  iIntros "(Hj&Hl)".
-  iApply (Henvs with "[Hw Hl] Hj").
-  iApply "Hw". simpl. rewrite right_id. eauto.
-Qed.
-
-Ltac weak_to_src_update :=
-  lazymatch goal with
-  | [|- envs_entails ?Δ (weak_src_update _ _)] =>
-     iApply src_update_weak_src_update
-  | _ => idtac
-  end.
-
-Tactic Notation "src_pure" open_constr(efoc) :=
-  match goal with
-  | [|- envs_entails ?Δ (?j ⤇ ?e -∗ src_update _ _)] =>
-      src_bind_core e efoc ltac:(fun K e' => eapply (tac_src_pures (fill K e'));
-                                             [iSolveTC|try solve_vals_compare_safe| simpl ectx_language.fill])
-  | [|- envs_entails ?Δ (?j ⤇ ?e -∗ rwp _ _ _ _)] =>
-        src_bind_core e efoc ltac:(fun K e' => eapply (tac_src_pures_rwp (fill K e'));
-                                               [iSolveTC|done|try solve_vals_compare_safe|simpl])
-  end.
-
-Tactic Notation "src_pure" open_constr(efoc) "in" constr(H) :=
-  weak_to_src_update;
-  iRevert H;
-  src_pure efoc;
-  last iIntros H.
-
-Tactic Notation "src_load" open_constr (efoc) :=
-  lazymatch goal with
-  | [|- envs_entails ?Δ (?j ⤇ ?e -∗ rwp _ _ _ _)] =>
-        src_bind_core e efoc ltac:(fun K e' => eapply (tac_src_load_rwp _ _ _ _ _ _ _ K);
-                                               [done|iAssumptionCore| simpl fill])
-  | [|- envs_entails ?Δ (?j ⤇ ?e -∗ weak_src_update _ _)] =>
-     iApply src_update_weak_src_update;
-     src_bind_core e efoc ltac:(fun K e' => eapply (tac_src_load _ _ _ _ _ K);
-                                        [iAssumptionCore| simpl fill])
-  | [|- envs_entails ?Δ (?j ⤇ ?e -∗ src_update _ _)] =>
-     src_bind_core e efoc ltac:(fun K e' => eapply (tac_src_load _ _ _ _ _ K);
-                                        [iAssumptionCore| simpl fill])
-  end.
-
-Tactic Notation "src_load" "in" constr(H) :=
-  weak_to_src_update;
-  iRevert H;
-  src_bind (! _)%E;
-  src_load _;
-  last iIntros H.
-
-Tactic Notation "pattern" open_constr(e) "in" tactic(f) := f e.
-
-Ltac single_pure_exec :=
-  match goal with
-  | [|- PureExec ?φ 1 ?e1 ?e2] => apply _
-  | [|- PureExec ?φ 1 (fill ?K1 ?e1) (fill ?K2 ?e2)] =>
-    unify K1 K2; eapply pure_exec_fill; single_pure_exec
-  | [|- PureExec ?φ 1 ?e1 ?e2 ] =>
-    reshape_expr e1 ltac:(fun K e1 =>
-    pattern (_: expr) in ltac:(fun e2' =>
-      unify e2 (fill K e2');
-      change (PureExec φ 1 (fill K e1) (fill K e2'));
-      apply pure_exec_fill, _
-    ))
-  end.
-
-
-Lemma pure_exec_cons φ ψ n (e1 e2 e3: expr):
-  PureExec φ 1 e1 e2 → PureExec ψ n e2 e3 → PureExec (φ ∧ ψ) (S n) e1 e3.
-Proof.
-  intros H1 H2 [Hφ Hψ]; econstructor; eauto.
-  specialize (H1 Hφ).
-  by inversion H1 as [|x y z a Hpure Hstep]; subst; inversion Hstep; subst.
-Qed.
-
-
-Lemma pure_exec_zero (e: expr): PureExec True 0 e e.
-Proof.
-  intros ?. econstructor.
-Qed.
-
-Ltac pure_exec_cons :=
-  match goal with
-  | [|- PureExec ?φ 0 ?e1 ?e2] =>
-    apply pure_exec_zero
-  | [|- PureExec ?φ ?n ?e1 ?e2] =>
-    unify e1 e2; apply pure_exec_zero
-  | [|- PureExec ?φ ?n ?e1 ?e2] =>
-    (eapply pure_exec_cons; [single_pure_exec|]); simpl
-  end.
-
-Ltac pure_exec := repeat pure_exec_cons.
-
-
-
-
-Arguments satisfiable_at {_ _ _} _ _%I.
-
-Lemma satisfiable_update_alloc {SI} {Σ: gFunctors SI} `{LargeIndex SI} `{!invG Σ} {E} {P} Q:
-   satisfiable_at E P → (⊢ |==> ∃ γ: gname, Q γ) → ∃ γ, satisfiable_at E (P ∗ Q γ).
-Proof.
-  intros Hsat Hent. apply satisfiable_at_exists; first done.
-  eapply satisfiable_at_fupd with (E1 := E).
-  eapply satisfiable_at_mono; first apply Hsat.
-  iIntros "$". iMod (Hent) as "$"; eauto.
-Qed.
-
-Lemma satisfiable_update_alloc_2 {SI} {Σ: gFunctors SI} `{LargeIndex SI} `{!invG Σ} {E} {P} Φ:
-   satisfiable_at E P → (⊢ |==> ∃ γ1 γ2: gname, Φ γ1 γ2) → ∃ γ1 γ2, satisfiable_at E (P ∗ Φ γ1 γ2).
-Proof.
-  intros Hsat Hent.
-  eapply satisfiable_at_mono with (Q := (|==> ∃ γ1 γ2, P ∗ Φ γ1 γ2)%I) in Hsat.
-  - eapply satisfiable_at_bupd in Hsat as Hsat.
-    apply satisfiable_at_exists in Hsat as [γ1 Hsat]; auto.
-    apply satisfiable_at_exists in Hsat as [γ2 Hsat]; eauto.
-  - iIntros "$". by iMod Hent.
-Qed.
-
-Lemma satisfiable_at_alloc {SI A} {Σ: gFunctors SI} `{LargeIndex SI} `{!inG Σ A} `{!invG Σ} {E} {P} (a: A):
-   satisfiable_at E P → ✓ a → ∃ γ, satisfiable_at E (P ∗ own γ a).
-Proof.
-  intros Hsat Hent. apply satisfiable_update_alloc; first done.
-  by eapply own_alloc.
-Qed.
-
-Lemma satisfiable_at_add {SI} (Σ: gFunctors SI) `{!invG Σ} E P Q: satisfiable_at E P → sbi_emp_valid Q → satisfiable_at E (P ∗ Q).
-Proof.
-  intros Hsat Hval. eapply satisfiable_at_mono; first eauto.
-  iIntros "$". iApply Hval.
-Qed.
-
-Lemma satisfiable_at_add' {SI} (Σ: gFunctors SI) `{!invG Σ} E Q: satisfiable_at E True → sbi_emp_valid Q → satisfiable_at E Q.
-Proof.
-  intros Hsat Hval. eapply satisfiable_at_mono; first eauto.
-  iIntros "_". iApply Hval.
-Qed.
-
-Lemma satisfiable_at_gen_heap {SI} {Σ: gFunctors SI} `{LargeIndex SI} `{!heapPreG Σ} κ σ:
-  ∃ Hheap: heapG Σ, satisfiable_at ⊤ ((gen_heap_ctx (heap σ)) ∗ proph_map_ctx κ (used_proph_id σ)).
-Proof.
-  (* allocate invariants *)
-  edestruct satisfiable_at_intro as [Hinv Hsat].
-  eapply satisfiable_update_alloc_2 in Hsat as (γ_gen_heap & γ_gen_heap_meta & Hsat); last eapply (alloc_gen_heap _ _ σ.(heap)).
-  pose (Hgen := GenHeapG SI loc val _ _ _ _ _ _ γ_gen_heap γ_gen_heap_meta).
-
-  (* TODO: prophecies are not really included in the refinement version *)
-  (* allocate prophecies *)
-  eapply satisfiable_update_alloc in Hsat as (γ_proph_map & Hsat); last apply (proph_map_init' κ σ.(used_proph_id)).
-  pose (Hproph := ProphMapG SI proph_id (val * val) Σ _ _ _ γ_proph_map).
-  exists (HeapG _ _ _ _ _).
-  eapply satisfiable_at_mono; first apply Hsat.
-  by iIntros "[[_ $] $]".
-Qed.
-
-
-Lemma satisfiable_at_ref_heapG {SI} {Σ: gFunctors SI} `{LargeIndex SI} `{!heapPreG Σ} n σ:
-  ∃ Hheap: heapG Σ, satisfiable_at ⊤ (ref_state_interp n σ).
-Proof.
-  edestruct (satisfiable_at_gen_heap nil) as [Hheap Hsat].
-  exists Hheap. eapply satisfiable_at_mono; first eauto.
-  iIntros "($ & _)".
-Qed.
-
-Lemma satisfiable_at_rheapG {SI} {Σ: gFunctors SI} `{LargeIndex SI} `{!rheapPreG Σ} n σ h m tp:
-  ∃ Hheap: rheapG Σ, satisfiable_at ⊤ (ref_state_interp σ n ∗ source_interp (tp, (h, m)) ∗ own rheapG_ghost_name (◯ (to_tpool tp, to_gen_heap SI h))).
-Proof.
-  edestruct (satisfiable_at_ref_heapG) as [Hheap Hsat].
-  eapply (satisfiable_at_alloc (● (to_tpool tp, to_gen_heap SI h) ⋅ ◯ (to_tpool tp, to_gen_heap SI h))) in Hsat as [γ Hsat]; last first.
-  { apply auth_both_valid; repeat split; eauto using to_tpool_valid, to_gen_heap_valid. }
-  eapply (satisfiable_at_alloc ((●{1} (MList [to_cfg (tp, (h, m))])))) in Hsat as [γ' Hsat]; last first.
-  { apply auth_auth_valid.
-    cbv; auto. }
-  exists (RHeapG _ _ _ _ γ _ γ').
-  eapply satisfiable_at_mono; first apply Hsat.
-  iIntros "(($&($&$))&H3)".
-  iExists nil. simpl. rewrite /fmlist. iFrame.
-  iPureIntro. apply rtc_list_once.
-Qed.
-
-Lemma rtc_to_cfg {SI} {Σ: gFunctors SI} `{!rheapG Σ} x y: rtc source_rel x y → rtc erased_step (to_cfg x) (to_cfg y).
-Proof.
-  induction 1; first done.
-  econstructor; by eauto.
-Qed.
-
-Lemma sn_to_cfg {SI} {Σ: gFunctors SI} `{!rheapG Σ} x: sn erased_step (to_cfg x) → sn source_rel x.
-Proof.
-  remember (to_cfg x) as σ; intros Hsn; revert x Heqσ.
-  induction Hsn as [x _ IH]; intros [ts [h m]] ->.
-  constructor. intros [ts' [h' m']] Hstep.
-  eapply IH; eauto. apply Hstep.
-Qed.
-
-From iris.program_logic Require Import ref_adequacy.
-(* Adequacy Theorem *)
-Section adequacy.
-  Context {SI: indexT} `{C: Classical}  `{LI: LargeIndex SI} {Σ: gFunctors SI}.
-  Context `{Hpre: !rheapPreG Σ} `{Hna: !na_invG Σ} `{Hauth: !inG Σ (authR (natA SI))}.
-
-  Theorem heap_lang_ref_adequacy (φ: val → val → Prop) (s t: expr) σ σ_src:
-    (∀ `{!rheapG Σ} `{!seqG Σ} `{!auth_sourceG Σ (natA SI)}, src s ⊢ SEQ t ⟨⟨ v, ∃ v': val, src v' ∗ ⌜φ v v'⌝ ⟩⟩) →
-    (∀ σ' v, rtc erased_step ([t], σ) ([Val v], σ') → ∃ v': val, ∃ σ_src' ts, rtc erased_step ([s], σ_src) (Val v' :: ts, σ_src') ∧ φ v v') ∧
-    (sn erased_step ([s], σ_src) → sn erased_step ([t], σ)).
-  Proof using SI C LI Σ Hpre Hna Hauth.
-    intros Hobj.
-    (* allocate the heap *)
-    edestruct (satisfiable_at_rheapG 0 σ (heap σ_src) (mapset.mapset_car (used_proph_id σ_src)) [s]) as [Hheap Hsat].
-    (* allocate sequential invariants *)
-    eapply satisfiable_update_alloc in Hsat as [seqG_name Hsat]; last apply na_alloc.
-    pose (seq := {| seqG_na_invG := _; seqG_name := seqG_name |}).
-    (* allocte stuttering credits *)
-    eapply (satisfiable_at_alloc (● 0%nat ⋅ ◯ 0%nat)) in Hsat as [authG_name Hsat]; last first.
-    { apply auth_both_valid; by split. }
-    pose (stutter := {| sourceG_inG := _; sourceG_name := authG_name |}).
-    specialize (Hobj Hheap seq stutter).
-    eapply satisfiable_at_mono in Hsat as Hsat; last first; [|split].
-    - iIntros "[[(SI & Hsrc & Hsrc') Hna] [Hc Hc']]".
-      iPoseProof (Hobj with "[Hsrc'] Hna") as "Hwp".
-      + assert ((◯ (to_tpool [s], to_gen_heap SI (heap σ_src))) ≡ (◯ (to_tpool [s], ∅) ⋅ ◯ (∅, to_gen_heap SI (heap σ_src)))) as ->.
-        { by rewrite -auth_frag_op pair_op left_id right_id. }
-        iDestruct "Hsrc'" as "[$ _]".
-      + iClear "Hc'". iCombine "Hsrc Hc" as "Hsrc".
-        iCombine "Hsrc SI Hwp" as "G". iExact "G".
-    - intros σ' v Hsteps. eapply (rwp_result _ _ ([s], (heap σ_src, mapset.mapset_car (used_proph_id σ_src)), 0%nat)) in Hsteps; last apply Hsat.
-      destruct Hsteps as ([[ts [h p]] c] & m & Hsteps & Hsat').
-      eapply satisfiable_at_pure.
-      eapply satisfiable_at_mono; first apply Hsat'.
-      iIntros "(Hsrc & SI & _ & Hv)". iDestruct "Hv" as (v') "[Hsrc' %]".
-      iExists v', {| heap := h; used_proph_id := {| mapset.mapset_car := p |} |}.
-      iDestruct "Hsrc" as "[[Hsrc _] _]".
-      iDestruct (own_valid_2 with "Hsrc Hsrc'") as %[[H1%tpool_singleton_included' _]%prod_included _]%auth_both_valid.
-      destruct ts as [|e ts]; first naive_solver.
-      iExists ts.
-      iPureIntro. split; auto.
-      rewrite tpool_lookup in H1.
-      injection H1 as ->.
-      eapply lex_rtc in Hsteps.
-      eapply rtc_to_cfg in Hsteps; simpl in Hsteps.
-      destruct σ_src as [? [?]]; apply Hsteps.
-    - intros Hsn. destruct σ_src as [h_src [p_src]]; simpl in *. eapply (rwp_sn_preservation _ ([s], (h_src, p_src), 0%nat) _ _ 0).
-      { eapply sn_lex; first apply (sn_to_cfg ([s], (h_src, p_src))); eauto.
-        intros y; apply lt_wf. }
-      eapply satisfiable_at_mono; first apply Hsat.
-      iIntros "($ & $ & $)".
-    Qed.
-
-End adequacy.
diff --git a/theories/examples/safety/assert.v b/theories/examples/safety/assert.v
deleted file mode 100644
index 24d098c8fdf98b5882362f39252e391ea7e553a2..0000000000000000000000000000000000000000
--- a/theories/examples/safety/assert.v
+++ /dev/null
@@ -1,28 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation.
-Set Default Proof Using "Type".
-
-Definition assert : val :=
-  λ: "v", if: "v" #() then #() else #0 #0. (* #0 #0 is unsafe *)
-(* just below ;; *)
-Notation "'assert:' e" := (assert (λ: <>, e)%E) (at level 99) : expr_scope.
-Notation "'assert:' e" := (assert (λ: <>, e)%V) (at level 99) : val_scope.
-
-(*
-Lemma twp_assert `{!heapG Σ} E (Φ : val → iProp Σ) e :
-  WP e @ E [{ v, ⌜v = #true⌝ ∧ Φ #() }] -∗
-  WP (assert: e)%V @ E [{ Φ }].
-Proof.
-  iIntros "HΦ". wp_lam.
-  wp_apply (twp_wand with "HΦ"). iIntros (v) "[% ?]"; subst. by wp_if.
-Qed.*)
-
-Lemma wp_assert  {SI} {Σ: gFunctors SI} `{!heapG Σ} E (Φ : val → iProp Σ) e :
-  WP e @ E {{ v, ⌜v = #true⌝ ∧ ▷ Φ #() }} -∗
-  WP (assert: e)%V @ E {{ Φ }}.
-Proof.
-  iIntros "HΦ". wp_lam.
-  wp_apply (wp_wand with "HΦ"). iIntros (v) "[% ?]"; subst. by wp_if.
-Qed.
diff --git a/theories/examples/safety/barrier/barrier.v b/theories/examples/safety/barrier/barrier.v
deleted file mode 100644
index 7ae83e5da15123f3fcb6dc59f83401ee1e923ac1..0000000000000000000000000000000000000000
--- a/theories/examples/safety/barrier/barrier.v
+++ /dev/null
@@ -1,7 +0,0 @@
-From iris.heap_lang Require Export notation.
-Set Default Proof Using "Type".
-
-Definition newbarrier : val := λ: <>, ref #false.
-Definition signal : val := λ: "x", "x" <- #true.
-Definition wait : val :=
-  rec: "wait" "x" := if: !"x" then #() else "wait" "x".
diff --git a/theories/examples/safety/barrier/example_client.v b/theories/examples/safety/barrier/example_client.v
deleted file mode 100644
index 21377276318be326fb0e8312912c60052f0e38d9..0000000000000000000000000000000000000000
--- a/theories/examples/safety/barrier/example_client.v
+++ /dev/null
@@ -1,73 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang.
-From iris.heap_lang Require Import adequacy proofmode.
-From iris.examples.safety Require Import par.
-From iris.examples.safety.barrier Require Import proof.
-Set Default Proof Using "Type".
-
-Definition worker (n : Z) : val :=
-  λ: "b" "y", wait "b" ;; !"y" #n.
-Definition client : expr :=
-  let: "y" := ref #0 in
-  let: "b" := newbarrier #() in
-  ("y" <- (λ: "z", "z" + #42) ;; signal "b") |||
-    (worker 12 "b" "y" ||| worker 17 "b" "y").
-
-Section client.
-  Local Set Default Proof Using "Type*".
-  Context `{Σ : gFunctors SI} `{!heapG Σ, !barrierG Σ, !spawnG Σ}.
-
-  Definition N := nroot .@ "barrier".
-
-  Definition y_inv (q : Qp) (l : loc) : iProp Σ :=
-    (∃ f : val, l ↦{q} f ∗ □ ∀ n : Z, WP f #n {{ v, ⌜v = #(n + 42)⌝ }})%I.
-
-  Lemma y_inv_split q l : y_inv q l -∗ (y_inv (q/2) l ∗ y_inv (q/2) l).
-  Proof.
-    iDestruct 1 as (f) "[[Hl1 Hl2] #Hf]".
-    iSplitL "Hl1"; iExists f; by iSplitL; try iAlways.
-  Qed.
-
-  Lemma worker_safe q (n : Z) (b y : loc) :
-    recv N b (y_inv q y) -∗ WP worker n #b #y {{ _, True }}.
-  Proof.
-    iIntros "Hrecv". wp_lam. wp_let.
-    wp_apply (wait_spec with "Hrecv"). iDestruct 1 as (f) "[Hy #Hf]".
-    wp_seq. wp_load.
-    iApply (wp_wand with "[]"). iApply "Hf". by iIntros (v) "_".
-  Qed.
-
-  Lemma client_safe : ⊢ WP client {{ _, True }}.
-  Proof.
-    iIntros ""; rewrite /client. wp_alloc y as "Hy". wp_let.
-    wp_apply (newbarrier_spec N (y_inv 1 y) with "[//]").
-    iIntros (l) "[Hr Hs]".
-    wp_apply (wp_par (λ _, True%I) (λ _, True%I) with "[Hy Hs] [Hr]"); last auto.
-    - (* The original thread, the sender. *)
-      wp_store. iApply (signal_spec with "[-]"); last by iNext; auto.
-      iSplitR "Hy"; first by eauto.
-      iExists _; iSplitL; [done|]. iIntros "!#" (n). by wp_pures.
-    - (* The two spawned threads, the waiters. *)
-      iDestruct (recv_weaken with "[] Hr") as "Hr".
-      { iIntros "Hy". by iApply (y_inv_split with "Hy"). }
-      iPoseProof (recv_split with "Hr") as "H". instantiate (1 := ⊤). done.
-      iApply swp_wp_lstep; eauto. 
-      iApply (lstepN_lstep _ _ 1). 
-      iMod "H". do 2 iModIntro. iNext. do 2 iModIntro. iMod "H". iModIntro. swp_finish. 
-      iDestruct "H" as "[H1 H2]".
-      wp_apply (wp_par (λ _, True%I) (λ _, True%I) with "[H1] [H2]"); last auto.
-      + by iApply worker_safe.
-      + by iApply worker_safe.
-Qed.
-End client.
-
-Section ClosedProofs.
-
-Let Σ {SI} : gFunctors SI := #[ heapΣ SI ; barrierΣ ; spawnΣ SI ].
-
-Lemma client_adequate {SI : indexT} σ : adequate NotStuck client σ (λ _ _, True).
-Proof. apply (heap_adequacy Σ)=> ?. apply client_safe. Qed.
-
-End ClosedProofs.
-
-(*Print Assumptions client_adequate.*)
diff --git a/theories/examples/safety/barrier/proof.v b/theories/examples/safety/barrier/proof.v
deleted file mode 100644
index e40b3941109142f325ba941c6b60387312fb4804..0000000000000000000000000000000000000000
--- a/theories/examples/safety/barrier/proof.v
+++ /dev/null
@@ -1,187 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.base_logic Require Import invariants saved_prop.
-From iris.heap_lang Require Export lang.
-From iris.heap_lang Require Import proofmode.
-From iris.algebra Require Import auth gset.
-From iris.examples.safety.barrier Require Export barrier.
-Set Default Proof Using "Type".
-
-(** The CMRAs/functors we need. *)
-Class barrierG {SI} (Σ : gFunctors SI) := BarrierG {
-  barrier_inG :> inG Σ (authR (gset_disjUR gname));
-  barrier_savedPropG :> savedPropG Σ;
-}.
-Definition barrierΣ {SI} : gFunctors SI :=
-  #[ GFunctor (authRF (gset_disjUR gname)); savedPropΣ ].
-
-Instance subG_barrierΣ `{Σ : gFunctors SI} : subG barrierΣ Σ → barrierG Σ.
-Proof. solve_inG. Qed.
-
-(** Now we come to the Iris part of the proof. *)
-Section proof.
-Context `{Σ : gFunctors SI} `{!heapG Σ, !barrierG Σ} (N : namespace).
-
-(* P is the proposition that will be sent, R the one that will be received by the individual threads *)
-Definition barrier_inv (l : loc) (γ : gname) (P : iProp Σ) : iProp Σ :=
-  (∃ (b : bool) (γsps : gset gname) (oracle : gname -> iProp Σ),
-    l ↦ #b ∗
-    own γ (● (GSet γsps)) ∗
-    ((if b then True else P) -∗ ▷ [∗ set] γsp ∈ γsps, oracle γsp) ∗
-    ([∗ set] γsp ∈ γsps, saved_prop_own γsp (oracle γsp)))%I.
-
-(*P is the proposition that will be sent, R' the one that will be received by this particular thread, and R the one we want to have *)
-Definition recv (l : loc) (R : iProp Σ) : iProp Σ :=
-  (∃ γ P R' γsp,
-    inv N (barrier_inv l γ P) ∗
-    ▷ (R' -∗ R) ∗
-    own γ (◯ GSet {[ γsp ]}) ∗
-    saved_prop_own γsp R')%I.
-
-(* P is the prop that we need to send *)
-Definition send (l : loc) (P : iProp Σ) : iProp Σ :=
-  (∃ γ, inv N (barrier_inv l γ P))%I.
-
-(** Setoids *)
-Instance barrier_inv_ne l γ : NonExpansive (barrier_inv l γ).
-Proof. solve_proper. Qed.
-Global Instance send_ne l : NonExpansive (send l).
-Proof. solve_proper. Qed.
-Global Instance recv_ne l : NonExpansive (recv l).
-Proof. solve_proper. Qed.
-
-(** Actual proofs *)
-Lemma newbarrier_spec (P : iProp Σ) :
-  {{{ True }}} newbarrier #() {{{ l, RET #l; recv l P ∗ send l P }}}.
-Proof.
-  iIntros (Φ) "_ HΦ". iApply wp_fupd. wp_lam. wp_alloc l as "Hl".
-  iApply ("HΦ" with "[> -]").
-  iMod (saved_prop_alloc P) as (γsp) "#Hsp".
-  iMod (own_alloc (● GSet {[ γsp ]} ⋅ ◯ GSet {[ γsp ]})) as (γ) "[H● H◯]".
-  { by apply auth_both_valid. }
-  iMod (inv_alloc N _ (barrier_inv l γ P) with "[Hl H●]") as "#Hinv".
-  { iExists false, {[ γsp ]}, (fun _ => P). iIntros "{$Hl $H●} !>".
-    rewrite !big_sepS_singleton; eauto. }
-  iModIntro; iSplitL "H◯".
-  - iExists γ, P, P, γsp. iFrame; auto.
-  - by iExists γ.
-Qed.
-
-Lemma signal_spec l P :
-  {{{ send l P ∗ P }}} signal #l {{{ RET #(); True }}}.
-Proof.
-  iIntros (Φ) "[Hs HP] HΦ".
-  iDestruct "Hs" as (γ) "#Hinv". wp_lam.
-  wp_swp. iInv "Hinv" as "H".
-  swp_last_step. iNext; simpl.
-  iDestruct "H" as ([] γsps oracle) "(Hl & H● & HRs & Hsaved)".
-  { wp_store. iModIntro. iSplitR "HΦ"; last by iApply "HΦ".
-    iExists true, γsps, oracle. iFrame. }
-  wp_store. iDestruct ("HRs" with "HP") as "HRs".
-  iModIntro. iSplitR "HΦ"; last by iApply "HΦ".
-  iExists true, γsps, oracle. iFrame; eauto.
-Qed.
-
-Lemma wait_spec l P:
-  {{{ recv l P }}} wait #l {{{ RET #(); P }}}.
-Proof.
-  rename P into R.
-  iIntros (Φ) "HR HΦ".
-  iDestruct "HR" as (γ P R' γsp) "(#Hinv & HR & H◯ & #Hsp)".
-  iLöb as "IH". wp_rec. wp_bind (! _)%E.
-  iInv "Hinv" as "H". wp_swp. swp_step. iNext; simpl.
-  iDestruct "H" as ([] γsps oracle) "(Hl & H● & HRs & Hsaved)"; last first.
-  { wp_load. iModIntro. iSplitL "Hl H● HRs Hsaved".
-    { iExists false, γsps, oracle. iFrame. }
-    by wp_apply ("IH" with "[$] [$]"). }
-  iSpecialize ("HRs" with "[//]").
-  swp_last_step. iNext. wp_load.
-  iDestruct (own_valid_2 with "H● H◯")
-    as %[Hvalid%gset_disj_included%elem_of_subseteq_singleton _]%auth_both_valid.
-  iDestruct (big_sepS_delete with "HRs") as "[HR'' HRs]"; first done.
-  iDestruct (big_sepS_delete with "Hsaved") as "[HRsaved Hsaved]"; first done.
-  iDestruct (saved_prop_agree with "Hsp HRsaved") as "#Heq".
-  iMod (own_update_2 with "H● H◯") as "H●".
-  { apply (auth_update_dealloc _ _ (GSet (γsps ∖ {[ γsp ]}))).
-    apply gset_disj_dealloc_local_update. }
-  iIntros "!>". iSplitL "Hl H● HRs Hsaved".
-  { iModIntro.
-    iExists true, (γsps ∖ {[ γsp ]}), oracle. iFrame; eauto.
-  }
-  wp_if. iApply "HΦ". iApply "HR". by iRewrite "Heq".
-Qed.
-
-Lemma recv_split E l P1 P2 :
-  ↑N ⊆ E → ⊢ (recv l (P1 ∗ P2) -∗ |={E, ∅}=> ▷ |={∅, E}=> recv l P1 ∗ recv l P2)%I.
-Proof.
-  rename P1 into R1; rename P2 into R2.
-  iIntros (?). iDestruct 1 as (γ P R' γsp) "(#Hinv & HR & H◯ & #Hsp)".
-  iInv N as "H" "Hclose".
-  iMod (fupd_intro_mask' (E ∖ ↑N) ∅) as "H3". set_solver.
-  iModIntro. iNext.
-  iDestruct "H" as (b γsps oracle) "(Hl & H● & HRs & Hsaved)". (* as later does not commute with exists, this would fail without taking a step *)
-  iDestruct (own_valid_2 with "H● H◯")
-    as %[Hvalid%gset_disj_included%elem_of_subseteq_singleton _]%auth_both_valid.
-  set (γsps' := γsps ∖ {[γsp]}).
-  iMod (own_update_2 with "H● H◯") as "H●".
-  { apply (auth_update_dealloc _ _ (GSet γsps')).
-    apply gset_disj_dealloc_local_update. }
-  iMod (saved_prop_alloc_cofinite γsps' R1) as (γsp1 Hγsp1) "#Hsp1".
-  iMod (saved_prop_alloc_cofinite (γsps' ∪ {[ γsp1 ]}) R2)
-    as (γsp2 [? ?%not_elem_of_singleton]%not_elem_of_union) "#Hsp2".
-  iMod (own_update _ _ (● _ ⋅ (◯ GSet {[ γsp1 ]} ⋅ ◯ (GSet {[ γsp2 ]})))
-    with "H●") as "(H● & H◯1 & H◯2)".
-  { rewrite -auth_frag_op gset_disj_union; last set_solver.
-    apply auth_update_alloc, (gset_disj_alloc_empty_local_update _ {[ γsp1; γsp2 ]}).
-    set_solver. }
-  iMod "H3" as "_".
-  iMod ("Hclose" with "[HR Hl HRs Hsaved H●]") as "_".
-  { iModIntro. iExists b, ({[γsp1; γsp2]} ∪ γsps'),
-        (fun g => if (decide (g = γsp1)) then R1 else if (decide (g = γsp2)) then R2 else oracle g).
-    iIntros "{$Hl $H●}".
-    iDestruct (big_sepS_delete with "Hsaved") as "[HRsaved Hsaved]"; first done.
-    iSplitL "HR HRs HRsaved".
-    - iIntros "HP". iSpecialize ("HRs" with "HP").
-      iDestruct (saved_prop_agree with "Hsp HRsaved") as "#Heq".
-      iNext.
-      iDestruct (big_sepS_delete with "HRs") as "[HR'' HRs]"; first done.
-      iApply big_sepS_union; [set_solver|iSplitL "HR HR'' HRsaved"]; first last.
-      {
-        subst γsps'. iApply big_opS_forall. 2: iApply "HRs". cbn. intros γ' Hin.
-        destruct (decide (γ' = γsp1)) as [-> |_]. 1: by destruct Hγsp1.
-        destruct (decide (γ' = γsp2)) as [-> |_]. 1: by destruct H0.
-        reflexivity.
-      }
-      iApply big_sepS_union; [set_solver|].
-      iAssert (R')%I with "[HR'']" as "HR'"; [by iRewrite "Heq"|].
-      iDestruct ("HR" with "HR'") as "[HR1 HR2]".
-      iSplitL "HR1".
-      + iApply big_sepS_singleton. rewrite decide_True; done.
-      + iApply big_sepS_singleton. rewrite decide_False; [by rewrite decide_True | done].
-    - iApply big_sepS_union; [set_solver| iSplitR "Hsaved"]; first last.
-      {
-        subst γsps'. iApply big_opS_forall. 2: iApply "Hsaved". cbn. intros γ' Hin.
-        destruct (decide (γ' = γsp1)) as [-> | _]. by destruct Hγsp1.
-        destruct (decide (γ' = γsp2)) as [-> | _]. by destruct H0.
-        reflexivity.
-      }
-      iApply big_sepS_union; [set_solver|]; rewrite !big_sepS_singleton.
-      iSplitL.
-      + rewrite decide_True; done.
-      + rewrite decide_False; [by rewrite decide_True | done].
-  }
-  iModIntro; iSplitL "H◯1".
-  - iExists γ, P, R1, γsp1. iFrame; auto.
-  - iExists γ, P, R2, γsp2. iFrame; auto.
-Qed.
-
-Lemma recv_weaken l P1 P2 : (P1 -∗ P2) -∗ recv l P1 -∗ recv l P2.
-Proof.
-  iIntros "HP". iDestruct 1 as (γ P R' i) "(#Hinv & HR & H◯)".
-  iExists γ, P, R', i. iIntros "{$Hinv $H◯} !> HR'". iApply "HP". by iApply "HR".
-Qed.
-
-Lemma recv_mono l P1 P2 : (P1 ⊢ P2) → recv l P1 ⊢ recv l P2.
-Proof. iIntros (HP) "H". iApply (recv_weaken with "[] H"). iApply HP. Qed.
-End proof.
-
-Typeclasses Opaque send recv.
diff --git a/theories/examples/safety/barrier/specification.v b/theories/examples/safety/barrier/specification.v
deleted file mode 100644
index 99ff884328117d9c1b337e3c29a74810303a5648..0000000000000000000000000000000000000000
--- a/theories/examples/safety/barrier/specification.v
+++ /dev/null
@@ -1,30 +0,0 @@
-From iris.program_logic Require Export hoare.
-From iris.heap_lang Require Import proofmode.
-From iris.examples.safety.barrier Require Export barrier.
-From iris.examples.safety.barrier Require Import proof.
-Set Default Proof Using "Type".
-Import uPred.
-
-Section spec.
-Local Set Default Proof Using "Type*".
-Context `{Σ : gFunctors SI} `{!heapG Σ, !barrierG Σ}.
-
-Lemma barrier_spec (N : namespace) :
-  ∃ recv send : loc → iProp Σ -n> iProp Σ,
-    (∀ P, ⊢ {{ True }} newbarrier #()
-                     {{ v, ∃ l : loc, ⌜v = #l⌝ ∗ recv l P ∗ send l P }}) ∧
-    (∀ l P, ⊢ {{ send l P ∗ P }} signal #l {{ _, True }}) ∧
-    (∀ l P, ⊢ {{ recv l P }} wait #l {{ _, P }}) ∧
-    (∀ l P Q, recv l (P ∗ Q) -∗ |={↑N, ∅}=> ▷ |={∅, ↑N}=> recv l P ∗ recv l Q) ∧
-    (∀ l P Q, (P -∗ Q) -∗ recv l P -∗ recv l Q).
-Proof.
-  exists (λ l, OfeMor (recv N l)), (λ l, OfeMor (send N l)).
-  split_and?; simpl.
-  - iIntros (P) "!# _". iApply (newbarrier_spec _ P with "[]"); [done..|].
-    iNext. eauto.
-  - iIntros (l P) "!# [Hl HP]". iApply (signal_spec with "[$Hl $HP]"). by eauto.
-  - iIntros (l P) "!# Hl". iApply (wait_spec with "Hl"). eauto.
-  - iIntros (l P Q). by iApply recv_split.
-  - apply recv_weaken.
-Qed.
-End spec.
diff --git a/theories/examples/safety/clairvoyant_coin.v b/theories/examples/safety/clairvoyant_coin.v
deleted file mode 100644
index bdd909074fb0a1f08f95f7fbfa04fccef630298e..0000000000000000000000000000000000000000
--- a/theories/examples/safety/clairvoyant_coin.v
+++ /dev/null
@@ -1,84 +0,0 @@
-From iris.base_logic Require Export invariants.
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang proofmode notation.
-From iris.examples.safety Require Export nondet_bool.
-
-(** The clairvoyant coin predicts all the values that it will
-*non-deterministically* choose throughout the execution of the
-program. This can be seen in the spec. The predicate [coin c bs]
-expresses that [bs] is the list of all the values of the coin in the
-future. The [read_coin] operation always returns the head of [bs] and the
-[toss_coin] operation takes the [tail] of [bs]. *)
-
-Definition new_coin: val :=
-  λ: <>, (ref (nondet_bool #()), NewProph).
-
-Definition read_coin : val := λ: "cp", !(Fst "cp").
-
-Definition toss_coin : val :=
-  λ: "cp",
-  let: "c" := Fst "cp" in
-  let: "p" := Snd "cp" in
-  let: "r" := nondet_bool #() in
-  "c" <- "r";; resolve_proph: "p" to: "r";; #().
-
-Section proof.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ}.
-
-  Definition prophecy_to_list_bool (vs : list (val * val)) : list bool :=
-    (λ v, bool_decide (v = #true)) ∘ snd <$> vs.
-
-  Definition coin (cp : val) (bs : list bool) : iProp Σ :=
-    (∃ (c : loc) (p : proph_id) (vs : list (val * val)),
-        ⌜cp = (#c, #p)%V⌝ ∗
-        ⌜bs ≠ []⌝ ∗ ⌜tail bs = prophecy_to_list_bool vs⌝ ∗
-        proph p vs ∗
-        from_option (λ b : bool, c ↦ #b) (∃ b : bool, c ↦ #b) (head bs))%I.
-
-  Lemma new_coin_spec : {{{ True }}} new_coin #() {{{ c bs, RET c; coin c bs }}}.
-  Proof.
-    iIntros (Φ) "_ HΦ".
-    wp_lam.
-    wp_apply wp_new_proph; first done.
-    iIntros (vs p) "Hp".
-    wp_apply nondet_bool_spec; first done.
-    iIntros (b) "_".
-    wp_alloc c as "Hc".
-    wp_pair.
-    iApply ("HΦ" $! (#c, #p)%V (b :: prophecy_to_list_bool vs)).
-    rewrite /coin; eauto with iFrame.
-  Qed.
-
-  Lemma read_coin_spec cp bs :
-    {{{ coin cp bs }}}
-      read_coin cp
-    {{{b bs', RET #b; ⌜bs = b :: bs'⌝ ∗ coin cp bs }}}.
-  Proof.
-    iIntros (Φ) "Hc HΦ".
-    iDestruct "Hc" as (c p vs -> ? ?) "[Hp Hb]".
-    destruct bs as [|b bs]; simplify_eq/=.
-    wp_lam. wp_load.
-    iApply "HΦ"; iSplit; first done.
-    rewrite /coin; eauto 10 with iFrame.
-  Qed.
-
-  Lemma toss_coin_spec cp bs :
-    {{{ coin cp bs }}}
-      toss_coin cp
-    {{{b bs', RET #(); ⌜bs = b :: bs'⌝ ∗ coin cp bs' }}}.
-  Proof.
-    iIntros (Φ) "Hc HΦ".
-    iDestruct "Hc" as (c p vs -> ? ?) "[Hp Hb]".
-    destruct bs as [|b bs]; simplify_eq/=.
-    wp_lam. do 2 (wp_proj; wp_let).
-    wp_apply nondet_bool_spec; first done.
-    iIntros (r) "_".
-    wp_store.
-    wp_apply (wp_resolve_proph with "[Hp]"); first done.
-    iIntros (ws) "[-> Hp]".
-    wp_seq.
-    iApply "HΦ"; iSplit; first done.
-    destruct r; rewrite /coin; eauto 10 with iFrame.
-  Qed.
-
-End proof.
diff --git a/theories/examples/safety/counter.v b/theories/examples/safety/counter.v
deleted file mode 100644
index 27381bf55af1322ad4ac0fc409c2aff384ee75ce..0000000000000000000000000000000000000000
--- a/theories/examples/safety/counter.v
+++ /dev/null
@@ -1,173 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.base_logic.lib Require Export invariants.
-From iris.heap_lang Require Export lang.
-From iris.proofmode Require Import tactics.
-From iris.algebra Require Import frac_auth auth.
-From iris.heap_lang Require Import proofmode notation.
-Set Default Proof Using "Type".
-
-Definition newcounter : val := λ: <>, ref #0.
-Definition incr : val := rec: "incr" "l" :=
-    let: "n" := !"l" in
-    if: CAS "l" "n" (#1 + "n") then #() else "incr" "l".
-Definition read : val := λ: "l", !"l".
-
-(** Monotone counter *)
-Class mcounterG {SI} (Σ: gFunctors SI) := MCounterG { mcounter_inG :> inG Σ (authR (mnatUR SI)) }.
-Definition mcounterΣ {SI} : gFunctors SI := #[GFunctor (authR (mnatUR SI))].
-
-Instance subG_mcounterΣ {SI} {Σ: gFunctors SI} : subG mcounterΣ Σ → mcounterG Σ.
-Proof. solve_inG. Qed.
-
-Section mono_proof.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ, !mcounterG Σ} (N : namespace).
-
-  Definition mcounter_inv (γ : gname) (l : loc) : iProp Σ :=
-    (∃ n, own γ (● (n : mnat)) ∗ l ↦ #n)%I.
-
-  Definition mcounter (l : loc) (n : nat) : iProp Σ :=
-    (∃ γ, inv N (mcounter_inv γ l) ∧ own γ (◯ (n : mnat)))%I.
-
-  (** The main proofs. *)
-  Global Instance mcounter_persistent l n : Persistent (mcounter l n).
-  Proof. apply _. Qed.
-
-  Lemma newcounter_mono_spec :
-    {{{ True }}} newcounter #() {{{ l, RET #l; mcounter l 0 }}}.
-  Proof.
-    iIntros (Φ) "_ HΦ". rewrite -wp_fupd /newcounter /=. wp_lam. wp_alloc l as "Hl".
-    iMod (own_alloc (● (O:mnat) ⋅ ◯ (O:mnat))) as (γ) "[Hγ Hγ']";
-      first by apply auth_both_valid.
-    iMod (inv_alloc N _ (mcounter_inv γ l) with "[Hl Hγ]").
-    { iNext. iExists 0%nat. by iFrame. }
-    iModIntro. iApply "HΦ". rewrite /mcounter; eauto 10.
-  Qed.
-
-  Lemma incr_mono_spec l n :
-    {{{ mcounter l n }}} incr #l {{{ RET #(); mcounter l (S n) }}}.
-  Proof.
-    iIntros (Φ) "Hl HΦ". iLöb as "IH". wp_rec.
-    iDestruct "Hl" as (γ) "[#? Hγf]".
-    wp_bind (! _)%E.
-    wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c) "[Hγ Hl]".
-    wp_load. iModIntro. iSplitL "Hl Hγ"; [iNext; iExists c; by iFrame|].
-    wp_pures. wp_bind (CmpXchg _ _ _).
-   wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c') "[Hγ Hl]".
-    destruct (decide (c' = c)) as [->|].
-    - iDestruct (own_valid_2 with "Hγ Hγf")
-        as %[?%mnat_included _]%auth_both_valid.
-      iMod (own_update_2 with "Hγ Hγf") as "[Hγ Hγf]".
-      { apply auth_update, (mnat_local_update _ _ (S c)); auto. }
-      wp_cmpxchg_suc. iModIntro. iSplitL "Hl Hγ".
-      { iNext. iExists (S c). rewrite Nat2Z.inj_succ Z.add_1_l. by iFrame. }
-      wp_pures. iApply "HΦ"; iExists γ; repeat iSplit; eauto.
-      iApply (own_mono with "Hγf").
-      (* FIXME: FIXME(Coq #6294): needs new unification *)
-      apply: auth_frag_mono. by apply mnat_included, le_n_S.
-    - wp_cmpxchg_fail; first (by intros [= ?%Nat2Z.inj]). iModIntro.
-      iSplitL "Hl Hγ"; [iNext; iExists c'; by iFrame|].
-      wp_pures. iApply ("IH" with "[Hγf] [HΦ]"); last by auto.
-      rewrite {3}/mcounter; simpl; eauto 10.
-  Qed.
-
-  Lemma read_mono_spec l j :
-    {{{ mcounter l j }}} read #l {{{ i, RET #i; ⌜j ≤ i⌝%nat ∧ mcounter l i }}}.
-  Proof.
-    iIntros (ϕ) "Hc HΦ". iDestruct "Hc" as (γ) "[#Hinv Hγf]".
-    rewrite /read /=. wp_lam.
-    wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c) "[Hγ Hl]".
-    wp_load.
-    iDestruct (own_valid_2 with "Hγ Hγf")
-      as %[?%mnat_included _]%auth_both_valid.
-    iMod (own_update_2 with "Hγ Hγf") as "[Hγ Hγf]".
-    { apply auth_update, (mnat_local_update _ _ c); auto. }
-    iModIntro. iSplitL "Hl Hγ"; [iNext; iExists c; by iFrame|].
-    iApply ("HΦ" with "[-]"). rewrite /mcounter; simpl; eauto 10.
-  Qed.
-End mono_proof.
-
-(** Counter with contributions *)
-Class ccounterG {SI} Σ :=
-  CCounterG { ccounter_inG :> inG Σ (frac_authR (natR SI)) }.
-Definition ccounterΣ {SI} : gFunctors SI :=
-  #[GFunctor (frac_authR (natR SI))].
-
-Instance subG_ccounterΣ {SI} {Σ: gFunctors SI} : subG ccounterΣ Σ → ccounterG Σ.
-Proof. solve_inG. Qed.
-
-Section contrib_spec.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ, !ccounterG Σ} (N : namespace).
-
-  Definition ccounter_inv (γ : gname) (l : loc) : iProp Σ :=
-    (∃ n, own γ (●F n) ∗ l ↦ #n)%I.
-
-  Definition ccounter_ctx (γ : gname) (l : loc) : iProp Σ :=
-    inv N (ccounter_inv γ l).
-
-  Definition ccounter (γ : gname) (q : frac) (n : nat) : iProp Σ :=
-    own γ (◯F{q} n).
-
-  (** The main proofs. *)
-  Lemma ccounter_op γ q1 q2 n1 n2 :
-    ccounter γ (q1 + q2) (n1 + n2) ⊣⊢ ccounter γ q1 n1 ∗ ccounter γ q2 n2.
-  Proof. by rewrite /ccounter frac_auth_frag_op -own_op. Qed.
-
-  Lemma newcounter_contrib_spec (R : iProp Σ) :
-    {{{ True }}} newcounter #()
-    {{{ γ l, RET #l; ccounter_ctx γ l ∗ ccounter γ 1 0 }}}.
-  Proof.
-    iIntros (Φ) "_ HΦ". rewrite -wp_fupd /newcounter /=. wp_lam. wp_alloc l as "Hl".
-    iMod (own_alloc (●F O%nat ⋅ ◯F 0%nat)) as (γ) "[Hγ Hγ']";
-      first by apply auth_both_valid.
-    iMod (inv_alloc N _ (ccounter_inv γ l) with "[Hl Hγ]").
-    { iNext. iExists 0%nat. by iFrame. }
-    iModIntro. iApply "HΦ". rewrite /ccounter_ctx /ccounter; eauto 10.
-  Qed.
-
-  Lemma incr_contrib_spec γ l q n :
-    {{{ ccounter_ctx γ l ∗ ccounter γ q n }}} incr #l
-    {{{ RET #(); ccounter γ q (S n) }}}.
-  Proof.
-    iIntros (Φ) "[#? Hγf] HΦ". iLöb as "IH". wp_rec.
-    wp_bind (! _)%E.
-    wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c) "[Hγ Hl]".
-    wp_load. iModIntro. iSplitL "Hl Hγ"; [iNext; iExists c; by iFrame|].
-    wp_pures. wp_bind (CmpXchg _ _ _).
-    wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c') "[Hγ Hl]".
-    destruct (decide (c' = c)) as [->|].
-    - iMod (own_update_2 with "Hγ Hγf") as "[Hγ Hγf]".
-      { apply frac_auth_update, (nat_local_update _ _ (S c) (S n)); lia. }
-      wp_cmpxchg_suc. iModIntro. iSplitL "Hl Hγ".
-      { iNext. iExists (S c). rewrite Nat2Z.inj_succ Z.add_1_l. by iFrame. }
-      wp_pures. by iApply "HΦ".
-    - wp_cmpxchg_fail; first (by intros [= ?%Nat2Z.inj]).
-      iModIntro. iSplitL "Hl Hγ"; [iNext; iExists c'; by iFrame|].
-      wp_pures. by iApply ("IH" with "[Hγf] [HΦ]"); auto.
-  Qed.
-
-  Lemma read_contrib_spec γ l q n :
-    {{{ ccounter_ctx γ l ∗ ccounter γ q n }}} read #l
-    {{{ c, RET #c; ⌜n ≤ c⌝%nat ∧ ccounter γ q n }}}.
-  Proof.
-    iIntros (Φ) "[#? Hγf] HΦ".
-    rewrite /read /=. wp_lam.
-    wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c) "[Hγ Hl]".
-    wp_load.
-    iDestruct (own_valid_2 with "Hγ Hγf") as % ?%frac_auth_included_total%nat_included.
-    iModIntro. iSplitL "Hl Hγ"; [iNext; iExists c; by iFrame|].
-    iApply ("HΦ" with "[-]"); rewrite /ccounter; simpl; eauto 10.
-  Qed.
-
-  Lemma read_contrib_spec_1 γ l n :
-    {{{ ccounter_ctx γ l ∗ ccounter γ 1 n }}} read #l
-    {{{ n, RET #n; ccounter γ 1 n }}}.
-  Proof.
-    iIntros (Φ) "[#? Hγf] HΦ".
-    rewrite /read /=. wp_lam.
-    wp_swp 1%nat. iInv N as "H". swp_step. iNext. iDestruct "H" as (c) "[Hγ Hl]".
-    wp_load.
-    iDestruct (own_valid_2 with "Hγ Hγf") as % <-%frac_auth_agreeL.
-    iModIntro. iSplitL "Hl Hγ"; [iNext; iExists c; by iFrame|].
-    by iApply "HΦ".
-  Qed.
-End contrib_spec.
diff --git a/theories/examples/safety/lazy_coin.v b/theories/examples/safety/lazy_coin.v
deleted file mode 100644
index adb4ee3da2f569bdc4d9041c4bf4ab08e583a7de..0000000000000000000000000000000000000000
--- a/theories/examples/safety/lazy_coin.v
+++ /dev/null
@@ -1,68 +0,0 @@
-From iris.base_logic Require Export invariants.
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang proofmode notation.
-From iris.examples.safety Require Export nondet_bool.
-
-Definition new_coin: val := λ: <>, (ref NONE, NewProph).
-
-Definition read_coin : val :=
-  λ: "cp",
-  let: "c" := Fst "cp" in
-  let: "p" := Snd "cp" in
-  match: !"c" with
-    NONE => let: "r" := nondet_bool #() in
-           "c" <- SOME "r";; resolve_proph: "p" to: "r";; "r"
-  | SOME "b" => "b"
-  end.
-
-Section proof.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ}.
-
-  Definition val_to_bool (v : val) : bool := bool_decide (v = #true).
-
-  Definition prophecy_to_bool (vs : list (val * val)) : bool :=
-    default false (val_to_bool ∘ snd <$> head vs).
-
-  Lemma prophecy_to_bool_of_bool (b : bool) v vs :
-    prophecy_to_bool ((v, #b) :: vs) = b.
-  Proof. by destruct b. Qed.
-
-  Definition coin (cp : val) (b : bool) : iProp Σ :=
-    (∃ (c : loc) (p : proph_id) (vs : list (val * val)),
-        ⌜cp = (#c, #p)%V⌝ ∗ proph p vs ∗
-        (c ↦ SOMEV #b ∨ (c ↦ NONEV ∗ ⌜b = prophecy_to_bool vs⌝)))%I.
-
-  Lemma new_coin_spec : {{{ True }}} new_coin #() {{{ c b, RET c; coin c b }}}.
-  Proof.
-    iIntros (Φ) "_ HΦ".
-    wp_lam.
-    wp_apply wp_new_proph; first done.
-    iIntros (vs p) "Hp".
-    wp_alloc c as "Hc".
-    wp_pair.
-    iApply ("HΦ" $! (#c, #p)%V ).
-    rewrite /coin; eauto 10 with iFrame.
-  Qed.
-
-  Lemma read_coin_spec cp b :
-    {{{ coin cp b }}} read_coin cp {{{ RET #b; coin cp b }}}.
-  Proof.
-    iIntros (Φ) "Hc HΦ".
-    iDestruct "Hc" as (c p vs ->) "[Hp [Hc | [Hc ->]]]".
-    - wp_lam. wp_load. wp_match.
-      iApply "HΦ".
-      rewrite /coin; eauto 10 with iFrame.
-    - wp_lam. wp_load. wp_match.
-      wp_apply nondet_bool_spec; first done.
-      iIntros (r) "_".
-      wp_let.
-      wp_store.
-      wp_apply (wp_resolve_proph with "[Hp]"); first done.
-      iIntros (ws) "[-> Hws]".
-      rewrite !prophecy_to_bool_of_bool.
-      wp_seq.
-      iApply "HΦ".
-      rewrite /coin; eauto with iFrame.
-  Qed.
-
-End proof.
diff --git a/theories/examples/safety/lock.v b/theories/examples/safety/lock.v
deleted file mode 100644
index df71e47bfb2ead4c680224483056406553680142..0000000000000000000000000000000000000000
--- a/theories/examples/safety/lock.v
+++ /dev/null
@@ -1,39 +0,0 @@
-From iris.heap_lang Require Export lifting notation.
-From iris.base_logic.lib Require Export invariants.
-Set Default Proof Using "Type".
-
-Structure lock {SI} (Σ: gFunctors SI) `{!heapG Σ} := Lock {
-  (* -- operations -- *)
-  newlock : val;
-  acquire : val;
-  release : val;
-  (* -- predicates -- *)
-  (* name is used to associate locked with is_lock *)
-  name : Type;
-  is_lock (N: namespace) (γ: name) (lock: val) (R: iProp Σ) : iProp Σ;
-  locked (γ: name) : iProp Σ;
-  (* -- general properties -- *)
-  is_lock_ne N γ lk : NonExpansive (is_lock N γ lk);
-  is_lock_persistent N γ lk R : Persistent (is_lock N γ lk R);
-  locked_timeless γ : Timeless (locked γ);
-  locked_exclusive γ : locked γ -∗ locked γ -∗ False;
-  (* -- operation specs -- *)
-  newlock_spec N (R : iProp Σ) :
-    {{{ R }}} newlock #() {{{ lk γ, RET lk; is_lock N γ lk R }}};
-  acquire_spec N γ lk R :
-    {{{ is_lock N γ lk R }}} acquire lk {{{ RET #(); locked γ ∗ R }}};
-  release_spec N γ lk R :
-    {{{ is_lock N γ lk R ∗ locked γ ∗ R }}} release lk {{{ RET #(); True }}}
-}.
-
-Arguments newlock {_ _ _} _.
-Arguments acquire {_ _ _} _.
-Arguments release {_ _ _} _.
-Arguments is_lock {_ _ _} _ _ _ _ _.
-Arguments locked {_ _ _} _ _.
-
-Existing Instances is_lock_ne is_lock_persistent locked_timeless.
-
-Instance is_lock_proper {SI} (Σ: gFunctors SI) `{!heapG Σ} (L: lock Σ) N γ lk:
-  Proper ((≡) ==> (≡)) (is_lock L N γ lk) := ne_proper _.
-
diff --git a/theories/examples/safety/nondet_bool.v b/theories/examples/safety/nondet_bool.v
deleted file mode 100644
index f07854e399b90414dc48604345dcc841d785c21a..0000000000000000000000000000000000000000
--- a/theories/examples/safety/nondet_bool.v
+++ /dev/null
@@ -1,25 +0,0 @@
-From iris.base_logic Require Export invariants.
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang proofmode notation.
-
-Definition nondet_bool : val :=
-  λ: <>, let: "l" := ref #true in Fork ("l" <- #false);; !"l".
-
-Section proof.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ}.
-
-  Lemma nondet_bool_spec : {{{ True }}} nondet_bool #() {{{ (b : bool), RET #b; True }}}.
-  Proof.
-    iIntros (Φ) "_ HΦ".
-    wp_lam. wp_alloc l as "Hl". wp_let.
-    pose proof (nroot .@ "rnd") as rndN.
-    iMod (inv_alloc rndN _ (∃ (b : bool), l ↦ #b)%I with "[Hl]") as "#Hinv";
-      first by eauto.
-    wp_apply wp_fork.
-    - wp_swp 1%nat. iInv rndN as "H". swp_step. iNext. iDestruct "H" as (?) "?". wp_store; eauto.
-    - wp_seq. wp_swp 1%nat. iInv rndN as "H". swp_step. iNext. iDestruct "H" as (?) "?". wp_load.
-      iSplitR "HΦ"; first by eauto.
-      by iApply "HΦ".
-  Qed.
-
-End proof.
diff --git a/theories/examples/safety/par.v b/theories/examples/safety/par.v
deleted file mode 100644
index 57c6ea6a9ec18ffc70690cc1b20505e9eba44cc1..0000000000000000000000000000000000000000
--- a/theories/examples/safety/par.v
+++ /dev/null
@@ -1,46 +0,0 @@
-From iris.examples.safety Require Export spawn.
-From iris.heap_lang Require Import proofmode notation.
-Set Default Proof Using "Type".
-Import uPred.
-
-Definition parN : namespace := nroot .@ "par".
-
-Definition par : val :=
-  λ: "e1" "e2",
-    let: "handle" := spawn "e1" in
-    let: "v2" := "e2" #() in
-    let: "v1" := join "handle" in
-    ("v1", "v2").
-Notation "e1 ||| e2" := (par (λ: <>, e1)%E (λ: <>, e2)%E) : expr_scope.
-Notation "e1 ||| e2" := (par (λ: <>, e1)%V (λ: <>, e2)%V) : val_scope.
-
-Section proof.
-Local Set Default Proof Using "Type*".
-Context {SI} {Σ: gFunctors SI} `{!heapG Σ, !spawnG Σ}.
-
-(* Notice that this allows us to strip a later *after* the two Ψ have been
-   brought together.  That is strictly stronger than first stripping a later
-   and then merging them, as demonstrated by [tests/joining_existentials.v].
-   This is why these are not Texan triples. *)
-Lemma par_spec (Ψ1 Ψ2 : val → iProp Σ) (f1 f2 : val) (Φ : val → iProp Σ) :
-  WP f1 #() {{ Ψ1 }} -∗ WP f2 #() {{ Ψ2 }} -∗
-  (▷ ∀ v1 v2, Ψ1 v1 ∗ Ψ2 v2 -∗ ▷ Φ (v1,v2)%V) -∗
-  WP par f1 f2 {{ Φ }}.
-Proof.
-  iIntros "Hf1 Hf2 HΦ". wp_lam. wp_let.
-  wp_apply (spawn_spec parN with "Hf1").
-  iIntros (l) "Hl". wp_let. wp_bind (f2 _).
-  wp_apply (wp_wand with "Hf2"); iIntros (v) "H2". wp_let.
-  wp_apply (join_spec with "[$Hl]"). iIntros (w) "H1".
-  iSpecialize ("HΦ" with "[$H1 $H2]"). by wp_pures.
-Qed.
-
-Lemma wp_par (Ψ1 Ψ2 : val → iProp Σ) (e1 e2 : expr) (Φ : val → iProp Σ) :
-  WP e1 {{ Ψ1 }} -∗ WP e2 {{ Ψ2 }} -∗
-  (∀ v1 v2, Ψ1 v1 ∗ Ψ2 v2 -∗ ▷ Φ (v1,v2)%V) -∗
-  WP (e1 ||| e2)%V {{ Φ }}.
-Proof.
-  iIntros "H1 H2 H".
-  wp_apply (par_spec Ψ1 Ψ2 with "[H1] [H2] [H]"); [by wp_lam..|auto].
-Qed.
-End proof.
diff --git a/theories/examples/safety/spawn.v b/theories/examples/safety/spawn.v
deleted file mode 100644
index 415dcd82ffa8330427499c0ee3dc3b9af04bf678..0000000000000000000000000000000000000000
--- a/theories/examples/safety/spawn.v
+++ /dev/null
@@ -1,78 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.base_logic.lib Require Export invariants.
-From iris.heap_lang Require Export lang.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation.
-From iris.algebra Require Import excl.
-Set Default Proof Using "Type".
-
-Definition spawn : val :=
-  λ: "f",
-    let: "c" := ref NONE in
-    Fork ("c" <- SOME ("f" #())) ;; "c".
-Definition join : val :=
-  rec: "join" "c" :=
-    match: !"c" with
-      SOME "x" => "x"
-    | NONE => "join" "c"
-    end.
-
-(** The CMRA & functor we need. *)
-(* Not bundling heapG, as it may be shared with other users. *)
-Class spawnG {SI} (Σ: gFunctors SI) := SpawnG { spawn_tokG :> inG Σ (exclR (unitO SI)) }.
-Definition spawnΣ SI : gFunctors SI := #[GFunctor (exclR (unitO SI))].
-
-Instance subG_spawnΣ {SI} {Σ: gFunctors SI} : subG (spawnΣ SI) Σ → spawnG Σ.
-Proof. solve_inG. Qed.
-
-(** Now we come to the Iris part of the proof. *)
-Section proof.
-Context {SI} {Σ: gFunctors SI} `{!heapG Σ, !spawnG Σ} (N : namespace).
-
-Definition spawn_inv (γ : gname) (l : loc) (Ψ : val → iProp Σ) : iProp Σ :=
-  (∃ lv, l ↦ lv ∗ (⌜lv = NONEV⌝ ∨
-                   ∃ w, ⌜lv = SOMEV w⌝ ∗ (Ψ w ∨ own γ (Excl ()))))%I.
-
-Definition join_handle (l : loc) (Ψ : val → iProp Σ) : iProp Σ :=
-  (∃ γ, own γ (Excl ()) ∗ inv N (spawn_inv γ l Ψ))%I.
-
-Global Instance spawn_inv_ne n γ l :
-  Proper (pointwise_relation val (dist n) ==> dist n) (spawn_inv γ l).
-Proof. solve_proper. Qed.
-Global Instance join_handle_ne n l :
-  Proper (pointwise_relation val (dist n) ==> dist n) (join_handle l).
-Proof. solve_proper. Qed.
-
-(** The main proofs. *)
-Lemma spawn_spec (Ψ : val → iProp Σ) (f : val) :
-  {{{ WP f #() {{ Ψ }} }}} spawn f {{{ l, RET #l; join_handle l Ψ }}}.
-Proof.
-  iIntros (Φ) "Hf HΦ". rewrite /spawn /=. wp_lam.
-  wp_alloc l as "Hl".
-  iMod (own_alloc (Excl ())) as (γ) "Hγ"; first done.
-  iMod (inv_alloc N _ (spawn_inv γ l Ψ) with "[Hl]") as "#?".
-  { iNext. iExists NONEV. iFrame; eauto. }
-  wp_apply (wp_fork with "[Hf]").
-  - iNext. wp_bind (f _). iApply (wp_wand with "Hf"); iIntros (v) "Hv".
-    wp_inj. iInv N as "H". wp_swp 1%nat. swp_step. iNext. iDestruct "H" as (v') "[Hl _]".
-    wp_store. iSplitL; last done. iIntros "!> !>". iExists (SOMEV v). iFrame. eauto.
-  - wp_pures. iApply "HΦ". rewrite /join_handle. eauto.
-Qed.
-
-Lemma join_spec (Ψ : val → iProp Σ) l :
-  {{{ join_handle l Ψ }}} join #l {{{ v, RET v; Ψ v }}}.
-Proof.
-  iIntros (Φ) "H HΦ". iDestruct "H" as (γ) "[Hγ #?]".
-  iLöb as "IH". wp_rec. wp_bind (! _)%E.
-  iInv N as "H". wp_swp 1%nat. swp_step. iNext. iDestruct "H" as (v) "[Hl Hinv]".
-  wp_load. iDestruct "Hinv" as "[%|Hinv]"; subst.
-  - iModIntro. iSplitL "Hl"; [iNext; iExists _; iFrame; eauto|].
-    wp_apply ("IH" with "Hγ [HΦ]"). auto.
-  - iDestruct "Hinv" as (v' ->) "[HΨ|Hγ']".
-    + iModIntro. iSplitL "Hl Hγ"; [iNext; iExists _; iFrame; eauto|].
-      wp_pures. by iApply "HΦ".
-    + iDestruct (own_valid_2 with "Hγ Hγ'") as %[].
-Qed.
-End proof.
-
-Typeclasses Opaque join_handle.
diff --git a/theories/examples/safety/spin_lock.v b/theories/examples/safety/spin_lock.v
deleted file mode 100644
index e73573296bf24454a80e82da79ad777480c1880d..0000000000000000000000000000000000000000
--- a/theories/examples/safety/spin_lock.v
+++ /dev/null
@@ -1,100 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation.
-From iris.algebra Require Import excl.
-From iris.examples.safety Require Import lock.
-Set Default Proof Using "Type".
-
-Definition newlock : val := λ: <>, ref #false.
-Definition try_acquire : val := λ: "l", CAS "l" #false #true.
-Definition acquire : val :=
-  rec: "acquire" "l" := if: try_acquire "l" then #() else "acquire" "l".
-Definition release : val := λ: "l", "l" <- #false.
-
-(** The CMRA we need. *)
-(* Not bundling heapG, as it may be shared with other users. *)
-Class lockG {SI} (Σ: gFunctors SI) := LockG { lock_tokG :> inG Σ (exclR (unitO SI)) }.
-Definition lockΣ SI : gFunctors SI := #[GFunctor (exclR (unitO SI))].
-
-Instance subG_lockΣ {SI} {Σ: gFunctors SI} : subG (lockΣ SI) Σ → lockG Σ.
-Proof. solve_inG. Qed.
-
-Section proof.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ, !lockG Σ} (N : namespace).
-
-  Definition lock_inv (γ : gname) (l : loc) (R : iProp Σ) : iProp Σ :=
-    (∃ b : bool, l ↦ #b ∗ if b then True else own γ (Excl ()) ∗ R)%I.
-
-  Definition is_lock (γ : gname) (lk : val) (R : iProp Σ) : iProp Σ :=
-    (∃ l: loc, ⌜lk = #l⌝ ∧ inv N (lock_inv γ l R))%I.
-
-  Definition locked (γ : gname) : iProp Σ := own γ (Excl ()).
-
-  Lemma locked_exclusive (γ : gname) : locked γ -∗ locked γ -∗ False.
-  Proof. iIntros "H1 H2". by iDestruct (own_valid_2 with "H1 H2") as %?. Qed.
-
-  Global Instance lock_inv_ne γ l : NonExpansive (lock_inv γ l).
-  Proof. solve_proper. Qed.
-  Global Instance is_lock_ne γ l : NonExpansive (is_lock γ l).
-  Proof. solve_proper. Qed.
-
-  (** The main proofs. *)
-  Global Instance is_lock_persistent γ l R : Persistent (is_lock γ l R).
-  Proof. apply _. Qed.
-  Global Instance locked_timeless γ : Timeless (locked γ).
-  Proof. apply _. Qed.
-
-  Lemma newlock_spec (R : iProp Σ):
-    {{{ R }}} newlock #() {{{ lk γ, RET lk; is_lock γ lk R }}}.
-  Proof.
-    iIntros (Φ) "HR HΦ". rewrite -wp_fupd /newlock /=.
-    wp_lam. wp_alloc l as "Hl".
-    iMod (own_alloc (Excl ())) as (γ) "Hγ"; first done.
-    iMod (inv_alloc N _ (lock_inv γ l R) with "[-HΦ]") as "#?".
-    { iIntros "!>". iExists false. by iFrame. }
-    iModIntro. iApply "HΦ". iExists l. eauto.
-  Qed.
-
-  Lemma try_acquire_spec γ lk R :
-    {{{ is_lock γ lk R }}} try_acquire lk
-    {{{ b, RET #b; if b is true then locked γ ∗ R else True }}}.
-  Proof.
-    iIntros (Φ) "#Hl HΦ". iDestruct "Hl" as (l ->) "#Hinv".
-    wp_rec. wp_bind (CmpXchg _ _ _). wp_swp. iInv N as "H". swp_step. iNext.
-    iDestruct "H" as ([]) "[Hl HR]".
-    - wp_cmpxchg_fail. iModIntro. iSplitL "Hl"; first (iNext; iExists true; eauto).
-      wp_pures. iApply ("HΦ" $! false). done.
-    - wp_cmpxchg_suc. iDestruct "HR" as "[Hγ HR]".
-      iModIntro. iSplitL "Hl"; first (iNext; iExists true; eauto).
-      rewrite /locked. wp_pures. by iApply ("HΦ" $! true with "[$Hγ $HR]").
-      Unshelve. exact 0%nat.
-  Qed.
-
-  Lemma acquire_spec γ lk R :
-    {{{ is_lock γ lk R }}} acquire lk {{{ RET #(); locked γ ∗ R }}}.
-  Proof.
-    iIntros (Φ) "#Hl HΦ". iLöb as "IH". wp_rec.
-    wp_apply (try_acquire_spec with "Hl"). iIntros ([]).
-    - iIntros "[Hlked HR]". wp_if. iApply "HΦ"; iFrame.
-    - iIntros "_". wp_if. iApply ("IH" with "[HΦ]"). auto.
-  Qed.
-
-  Lemma release_spec γ lk R :
-    {{{ is_lock γ lk R ∗ locked γ ∗ R }}} release lk {{{ RET #(); True }}}.
-  Proof.
-    iIntros (Φ) "(Hlock & Hlocked & HR) HΦ".
-    iDestruct "Hlock" as (l ->) "#Hinv".
-    rewrite /release /=. wp_lam. wp_swp. iInv N as "H". swp_step. iNext.
-    iDestruct "H" as (b) "[Hl _]".
-    wp_store. iSplitR "HΦ"; last by iApply "HΦ".
-    iModIntro. iNext. iExists false. by iFrame.
-    Unshelve. exact 0%nat.
-  Qed.
-End proof.
-
-Typeclasses Opaque is_lock locked.
-
-Canonical Structure spin_lock {SI} {Σ: gFunctors SI} `{!heapG Σ, !lockG Σ} : lock Σ :=
-  {| lock.locked_exclusive := locked_exclusive; lock.newlock_spec := newlock_spec;
-     lock.acquire_spec := acquire_spec; lock.release_spec := release_spec |}.
diff --git a/theories/examples/safety/ticket_lock.v b/theories/examples/safety/ticket_lock.v
deleted file mode 100644
index 104824ac19b9f11f4665501309e1232f62349f31..0000000000000000000000000000000000000000
--- a/theories/examples/safety/ticket_lock.v
+++ /dev/null
@@ -1,167 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation.
-From iris.algebra Require Import excl auth gset.
-From iris.examples.safety Require Export lock.
-Set Default Proof Using "Type".
-Import uPred.
-
-Definition wait_loop: val :=
-  rec: "wait_loop" "x" "lk" :=
-    let: "o" := !(Fst "lk") in
-    if: "x" = "o"
-      then #() (* my turn *)
-      else "wait_loop" "x" "lk".
-
-Definition newlock : val :=
-  λ: <>, ((* owner *) ref #0, (* next *) ref #0).
-
-Definition acquire : val :=
-  rec: "acquire" "lk" :=
-    let: "n" := !(Snd "lk") in
-    if: CAS (Snd "lk") "n" ("n" + #1)
-      then wait_loop "n" "lk"
-      else "acquire" "lk".
-
-Definition release : val :=
-  λ: "lk", (Fst "lk") <- !(Fst "lk") + #1.
-
-(** The CMRAs we need. *)
-Class tlockG {SI} (Σ: gFunctors SI) :=
-  tlock_G :> inG Σ (authR (prodUR (optionUR (exclR (natO SI))) (gset_disjUR nat))).
-Definition tlockΣ {SI} : gFunctors SI :=
-  #[ GFunctor (authR (prodUR (optionUR (exclR (natO SI))) (gset_disjUR nat))) ].
-
-Instance subG_tlockΣ {SI} {Σ: gFunctors SI} : subG tlockΣ Σ → tlockG Σ.
-Proof. solve_inG. Qed.
-
-Section proof.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ, !tlockG Σ} (N : namespace).
-
-  Definition lock_inv (γ : gname) (lo ln : loc) (R : iProp Σ) : iProp Σ :=
-    (∃ o n : nat,
-      lo ↦ #o ∗ ln ↦ #n ∗
-      own γ (● (Excl' o, GSet (set_seq 0 n))) ∗
-      ((own γ (◯ (Excl' o, GSet ∅)) ∗ R) ∨ own γ (◯ (ε, GSet {[ o ]}))))%I.
-
-  Definition is_lock (γ : gname) (lk : val) (R : iProp Σ) : iProp Σ :=
-    (∃ lo ln : loc,
-       ⌜lk = (#lo, #ln)%V⌝ ∗ inv N (lock_inv γ lo ln R))%I.
-
-  Definition issued (γ : gname) (x : nat) : iProp Σ :=
-    own γ (◯ (ε, GSet {[ x ]}))%I.
-
-  Definition locked (γ : gname) : iProp Σ := (∃ o, own γ (◯ (Excl' o, GSet ∅)))%I.
-
-  Global Instance lock_inv_ne γ lo ln :
-    NonExpansive (lock_inv γ lo ln).
-  Proof. solve_proper. Qed.
-  Global Instance is_lock_ne γ lk : NonExpansive (is_lock γ lk).
-  Proof. solve_proper. Qed.
-  Global Instance is_lock_persistent γ lk R : Persistent (is_lock γ lk R).
-  Proof. apply _. Qed.
-  Global Instance locked_timeless γ : Timeless (locked γ).
-  Proof. apply _. Qed.
-
-  Lemma locked_exclusive (γ : gname) : locked γ -∗ locked γ -∗ False.
-  Proof.
-    iDestruct 1 as (o1) "H1". iDestruct 1 as (o2) "H2".
-    iDestruct (own_valid_2 with "H1 H2") as %[[] _].
-  Qed.
-
-  Lemma newlock_spec (R : iProp Σ) :
-    {{{ R }}} newlock #() {{{ lk γ, RET lk; is_lock γ lk R }}}.
-  Proof.
-    iIntros (Φ) "HR HΦ". rewrite -wp_fupd. wp_lam.
-    wp_alloc ln as "Hln". wp_alloc lo as "Hlo".
-    iMod (own_alloc (● (Excl' 0%nat, GSet ∅) ⋅ ◯ (Excl' 0%nat, GSet ∅))) as (γ) "[Hγ Hγ']".
-    { by apply auth_both_valid. }
-    iMod (inv_alloc _ _ (lock_inv γ lo ln R) with "[-HΦ]").
-    { iNext. rewrite /lock_inv.
-      iExists 0%nat, 0%nat. iFrame. iLeft. by iFrame. }
-    wp_pures. iModIntro. iApply ("HΦ" $! (#lo, #ln)%V γ). iExists lo, ln. eauto.
-  Qed.
-
-  Lemma wait_loop_spec γ lk x R :
-    {{{ is_lock γ lk R ∗ issued γ x }}} wait_loop #x lk {{{ RET #(); locked γ ∗ R }}}.
-  Proof.
-    iIntros (Φ) "[Hl Ht] HΦ". iDestruct "Hl" as (lo ln ->) "#Hinv".
-    iLöb as "IH". wp_rec. subst. wp_pures. wp_bind (! _)%E.
-    wp_swp 1%nat. iInv N as "Hlock". swp_step. iNext. iDestruct "Hlock" as (o n) "(Hlo & Hln & Ha)".
-    wp_load. destruct (decide (x = o)) as [->|Hneq].
-    - iDestruct "Ha" as "[Hainv [[Ho HR] | Haown]]".
-      + iModIntro. iSplitL "Hlo Hln Hainv Ht".
-        { iNext. iExists o, n. iFrame. }
-        wp_pures. case_bool_decide; [|done]. wp_if.
-        iApply ("HΦ" with "[-]"). rewrite /locked. iFrame. simpl. eauto.
-      + iDestruct (own_valid_2 with "Ht Haown") as % [_ ?%gset_disj_valid_op].
-        set_solver.
-    - iModIntro. iSplitL "Hlo Hln Ha".
-      { iNext. iExists o, n. by iFrame. }
-      wp_pures. case_bool_decide; [simplify_eq |].
-      wp_if. iApply ("IH" with "Ht"). iNext. by iExact "HΦ".
-  Qed.
-
-  Lemma acquire_spec γ lk R :
-    {{{ is_lock γ lk R }}} acquire lk {{{ RET #(); locked γ ∗ R }}}.
-  Proof.
-    iIntros (ϕ) "Hl HΦ". iDestruct "Hl" as (lo ln ->) "#Hinv".
-    iLöb as "IH". wp_rec. wp_bind (! _)%E. simplify_eq/=. wp_proj.
-    wp_swp 1%nat. iInv N as "Hlock". swp_step. iNext. iDestruct "Hlock" as (o n) "(Hlo & Hln & Ha)".
-    wp_load. iModIntro. iSplitL "Hlo Hln Ha".
-    { iNext. iExists o, n. by iFrame. }
-    wp_pures. wp_bind (CmpXchg _ _ _).
-    wp_swp 1%nat. iInv N as "Hlock". swp_step. iNext. iDestruct "Hlock" as (o' n') "(Hlo' & Hln' & Hauth & Haown)".
-    destruct (decide (#n' = #n))%V as [[= ->%Nat2Z.inj] | Hneq].
-    - iMod (own_update with "Hauth") as "[Hauth Hofull]".
-      { eapply auth_update_alloc, prod_local_update_2.
-        eapply (gset_disj_alloc_empty_local_update _ {[ n ]}).
-        apply (set_seq_S_end_disjoint 0). }
-      rewrite -(set_seq_S_end_union_L 0).
-      wp_cmpxchg_suc. iModIntro. iSplitL "Hlo' Hln' Haown Hauth".
-      { iNext. iExists o', (S n).
-        rewrite Nat2Z.inj_succ -Z.add_1_r. by iFrame. }
-      wp_pures.
-      iApply (wait_loop_spec γ (#lo, #ln) with "[-HΦ]").
-      + iFrame. rewrite /is_lock; eauto 10.
-      + by iNext.
-    - wp_cmpxchg_fail. iModIntro.
-      iSplitL "Hlo' Hln' Hauth Haown".
-      { iNext. iExists o', n'. by iFrame. }
-      wp_pures. by iApply "IH"; auto.
-  Qed.
-
-  Lemma release_spec γ lk R :
-    {{{ is_lock γ lk R ∗ locked γ ∗ R }}} release lk {{{ RET #(); True }}}.
-  Proof.
-    iIntros (Φ) "(Hl & Hγ & HR) HΦ". iDestruct "Hl" as (lo ln ->) "#Hinv".
-    iDestruct "Hγ" as (o) "Hγo".
-    wp_lam. wp_proj. wp_bind (! _)%E.
-    wp_swp 1%nat. iInv N as "Hlock". swp_step. iNext. iDestruct "Hlock" as (o' n) "(Hlo & Hln & Hauth & Haown)".
-    wp_load.
-    iDestruct (own_valid_2 with "Hauth Hγo") as
-      %[[<-%Excl_included%leibniz_equiv _]%prod_included _]%auth_both_valid.
-    iModIntro. iSplitL "Hlo Hln Hauth Haown".
-    { iNext. iExists o, n. by iFrame. }
-    wp_pures.
-    wp_swp 1%nat. iInv N as "Hlock". swp_step. iNext. iDestruct "Hlock" as (o' n') "(Hlo & Hln & Hauth & Haown)".
-    iApply swp_fupd. wp_store.
-    iDestruct (own_valid_2 with "Hauth Hγo") as
-      %[[<-%Excl_included%leibniz_equiv _]%prod_included _]%auth_both_valid.
-    iDestruct "Haown" as "[[Hγo' _]|Haown]".
-    { iDestruct (own_valid_2 with "Hγo Hγo'") as %[[] ?]. }
-    iMod (own_update_2 with "Hauth Hγo") as "[Hauth Hγo]".
-    { apply auth_update, prod_local_update_1.
-      by apply option_local_update, (exclusive_local_update _ (Excl (S o))). }
-    iModIntro. iSplitR "HΦ"; last by iApply "HΦ".
-    iIntros "!> !>". iExists (S o), n'.
-    rewrite Nat2Z.inj_succ -Z.add_1_r. iFrame. iLeft. by iFrame.
-  Qed.
-End proof.
-
-Typeclasses Opaque is_lock issued locked.
-
-Canonical Structure ticket_lock {SI} {Σ: gFunctors SI} `{!heapG Σ, !tlockG Σ} : lock Σ :=
-  {| lock.locked_exclusive := locked_exclusive; lock.newlock_spec := newlock_spec;
-     lock.acquire_spec := acquire_spec; lock.release_spec := release_spec |}.
diff --git a/theories/examples/termination/adequacy.v b/theories/examples/termination/adequacy.v
deleted file mode 100644
index d46c9b883d8022bd490f914dd685e645184c8aea..0000000000000000000000000000000000000000
--- a/theories/examples/termination/adequacy.v
+++ /dev/null
@@ -1,67 +0,0 @@
-From iris.program_logic.refinement Require Export ref_weakestpre ref_source seq_weakestpre.
-From iris.base_logic.lib Require Export invariants na_invariants.
-From iris.heap_lang Require Export lang lifting.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation metatheory.
-From iris.algebra Require Import auth gmap excl frac agree.
-From iris.program_logic Require Import ref_adequacy.
-From iris.examples Require Import refinement.
-Set Default Proof Using "Type".
-
-
-(* Adequacy Theorem *)
-Section adequacy.
-  Context {SI} `{C: Classical}  {Σ: gFunctors SI} {Hlarge: LargeIndex SI}. 
-  Context `{Hpre: !heapPreG Σ} `{Hna: !na_invG Σ} `{Htc: !inG Σ (authR (ordA SI))}.
-
-  Theorem heap_lang_ref_adequacy (e: expr) σ:
-    (∀ `{heapG SI Σ} `{!seqG Σ} `{!auth_sourceG Σ (ordA SI)},
-      True ⊢ (∃ α, $α -∗ SEQ e ⟨⟨ v, True ⟩⟩)%I
-    ) →
-    sn erased_step ([e], σ).
-  Proof using C Hlarge Σ Hpre Hna Htc.
-    intros Hobj.
-    (* allocate the heap *)
-    edestruct (satisfiable_at_gen_heap nil σ) as [Hheap Hsat].
-    (* allocate sequential invariants *)
-    eapply satisfiable_update_alloc in Hsat as [seqG_name Hsat]; last apply na_alloc.
-    pose (seq := {| seqG_na_invG := _; seqG_name := seqG_name |}).
-    (* allocte stuttering credits *)
-    eapply (satisfiable_at_alloc (● zero ⋅ ◯ zero)) in Hsat as [authG_name Hsat]; last first.
-    { apply auth_both_valid; by split. }
-    pose (stutter := {| sourceG_inG := _; sourceG_name := authG_name |}).
-    specialize (Hobj Hheap seq stutter).
-    eapply satisfiable_at_mono with (Q := (∃ α: Ord, _)%I) in Hsat; last first.
-    { iIntros "H". iPoseProof (Hobj with "[//]") as (α) "Hwp".
-      iExists α. iCombine "H Hwp" as "H". iExact "H". }
-    eapply satisfiable_at_exists in Hsat as [α Hsat]; last apply _.
-    eapply satisfiable_at_mono with (Q := (|={⊤}=> _)%I) in Hsat; last first.
-    - iIntros "[[[[SI _] Hna] [Hc Hc']] Hwp]".
-      iMod (own_update_2 _ _  _ (● α ⋅ ◯ α) with "Hc Hc'") as "[Hc Hc']".
-      { rewrite -[α]natural_addition_zero_left_id natural_addition_comm -ord_op_plus.
-        eapply auth_update, op_local_update_discrete; done. }
-      iSpecialize ("Hwp" with "Hc' Hna").
-      iCombine "Hc SI Hwp" as "G". iExact "G".
-    - eapply satisfiable_at_fupd in Hsat as Hsat.
-      eapply (rwp_sn_preservation _ (α) _ _ 0); first apply index_lt_wf.
-      eapply satisfiable_at_mono; first apply Hsat.
-      iIntros "($ & $ & $)".
-    Qed.
-
-End adequacy.
-
-Section adequacy_ord. 
-  (* result for the ordinal step-index type *)
-  Context `{C: Classical}  {Σ: gFunctors ordI}.
-  Context `{Hpre: !heapPreG Σ} `{Hna: !na_invG Σ} `{Htc: !inG Σ (authR (ordA ordI))}.
-  Theorem heap_lang_ref_adequacy_ord (e: expr) σ:
-    (∀ `{heapG ordI Σ} `{!seqG Σ} `{!auth_sourceG Σ (ordA ordI)},
-      True ⊢ (∃ α, $α -∗ SEQ e ⟨⟨ v, True ⟩⟩)%I
-    ) →
-    sn erased_step ([e], σ).
-  Proof using C Σ Hpre Hna Htc.
-    apply heap_lang_ref_adequacy.
-  Qed.
-  Print Assumptions heap_lang_ref_adequacy_ord. 
-
-End adequacy_ord.
diff --git a/theories/examples/termination/eventloop.v b/theories/examples/termination/eventloop.v
deleted file mode 100644
index de992cf02a315d01d7ef9853d33d0689441c0a18..0000000000000000000000000000000000000000
--- a/theories/examples/termination/eventloop.v
+++ /dev/null
@@ -1,211 +0,0 @@
-From iris.program_logic.refinement Require Export seq_weakestpre.
-From iris.base_logic.lib Require Export invariants na_invariants.
-From iris.heap_lang Require Export lang lifting.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation metatheory.
-From iris.algebra Require Import auth.
-From iris.algebra.ordinals Require Import arithmetic.
-Set Default Proof Using "Type".
-
-Section eventloop_code.
-  Definition new_stack : val := λ: <>, ref NONEV.
-
-  Definition push : val := λ: "s", λ: "x",
-                           let: "hd" := !"s" in
-                           let: "p" := ("x", "hd") in
-                           "s" <- SOME (ref "p").
-
-  Definition pop : val := (λ: "s",
-                           let: "hd" := !"s" in
-                           match: "hd" with
-                             NONE => NONE
-                           | SOME "l" =>
-                             let: "p" := !"l" in
-                             let: "x" := Fst "p" in
-                             "s" <- Snd "p" ;; SOME "x"
-                           end).
-
-  Definition enqueue : val := push.
-
-  Definition run : val :=
-      λ: "q", rec: "run" <> :=
-      match: pop "q" with
-        NONE => #()
-      | SOME "f" => "f" #() ;; "run" #()
-      end.
-
-  Definition mkqueue : val :=
-    λ: <>, new_stack #().
-
-End eventloop_code.
-Section eventloop_spec.
-
-  Context {SI} {Σ: gFunctors SI} `{Hheap: !heapG Σ} `{Htc: !tcG Σ} `{Hseq: !seqG Σ} (N : namespace).
-
-  Implicit Types (l: loc).
-
-  Fixpoint stack_contents (hd: val) (xs: list val) (φ: val → iProp Σ) :=
-    match xs with
-    | [] => ⌜hd = NONEV⌝
-    | x :: xs => ∃ l hd', ⌜hd = SOMEV #l⌝ ∗ l ↦ (x, hd') ∗ φ x ∗ stack_contents hd' xs φ
-  end%I.
-  Definition stack (l: loc) (xs: list val) (φ: val → iProp Σ): iProp Σ := (∃ hd, l ↦ hd ∗ stack_contents hd xs φ)%I.
-  Definition queue (q: val) : iProp Σ := (∃ l, ⌜q = #l⌝ ∗ na_inv seqG_name (N .@ l) (∃ xs, stack l xs (λ f, $ one ∗ SEQ f #() [{_, True}])))%I.
-
-
-  Lemma new_stack_spec φ:
-    sbi_emp_valid (WP (new_stack #()) [{ v, ∃ l, ⌜v = #l⌝ ∗ stack l nil φ }])%I.
-  Proof.
-    rewrite /new_stack. wp_pures.
-    wp_alloc l as "Hl". iFrame.
-    rewrite /stack. iExists l; iSplit; auto.
-  Qed.
-
-  Lemma push_spec  l xs φ (x : val):
-    (stack l xs φ ∗ φ x ⊢ RSWP (push #l x) at 0 ⟨⟨ v, ⌜v = #()⌝ ∗ stack l (x :: xs) φ ⟩⟩)%I.
-  Proof.
-    iIntros "(Hstack & Hφ)".
-    rewrite /push /stack. wp_pures.
-    iDestruct "Hstack" as (hd) "[Hl cont]".
-    wp_load. wp_pures. wp_alloc r as "Hr". rewrite -tcwp_rwp.
-    wp_store. iSplit; auto. iExists (SOMEV #r). iFrame "Hl".
-    simpl. iExists r, hd. by iFrame.
-  Qed.
-
-  Lemma pop_element_spec  l xs φ (x : val):
-    (stack l (x :: xs) φ ⊢ RSWP (pop #l) at 0 ⟨⟨ v, ⌜v = SOMEV x⌝ ∗ φ x ∗ stack l xs φ ⟩⟩)%I.
-  Proof.
-    iIntros "Hstack".
-    rewrite /pop /stack. wp_pures.
-    iDestruct "Hstack" as (hd) "[Hl Hcont]".
-    iDestruct "Hcont" as (r hd') "(-> & Hr & Hφ & Hcont)".
-    wp_load. wp_pures. wp_load. wp_pures. wp_store. wp_pures; iFrame.
-    iSplit; eauto. iExists hd'. iFrame.
-  Qed.
-
-  Lemma pop_empty_spec  l φ:
-    (stack l nil φ ⊢ RSWP (pop #l) at 0 ⟨⟨ v, ⌜v = NONEV⌝ ∗ stack l nil φ ⟩⟩)%I.
-  Proof.
-    iIntros "Hstack".
-    rewrite /pop /stack. wp_pures.
-    iDestruct "Hstack" as (hd) "[Hl ->]".
-    wp_load. wp_pures; iSplit; eauto.
-  Qed.
-
-  Lemma run_spec `{FiniteBoundedExistential SI} q :
-    queue q ∗ $ one ⊢ SEQ (run q #()) [{v, ⌜v = #()⌝ }].
-  Proof.
-    iIntros "[#Q Hc] Hna". rewrite /run. do 2 wp_pure _.
-    iLöb as "IH". wp_pures.
-    wp_bind (pop _). iDestruct "Q" as (l) "[-> I]".
-    iMod (na_inv_acc_open _ _ _ with "I Hna") as "Hinv"; auto.
-    iApply (tcwp_burn_credit with "Hc"); first done.
-    iNext. iDestruct "Hinv" as "(Hinv & Hna & Hclose)".
-    iDestruct "Hinv" as (xs) "Hstack".
-    destruct xs as [|f xs].
-    - iPoseProof (pop_empty_spec with "Hstack") as "Hwp".
-      iApply (rswp_wand with "Hwp"). iIntros (v) "[-> Hstack]".
-      iMod ("Hclose" with "[Hstack $Hna]") as "Hna"; eauto.
-      wp_pures. by iFrame.
-    - iPoseProof (pop_element_spec with "Hstack") as "Hwp".
-      iApply (rswp_wand with "Hwp"). iIntros (v) "[-> [[Hone Hwp] Hstack]]".
-      iMod ("Hclose" with "[Hstack $Hna]") as "Hna"; eauto.
-      wp_pures. iSpecialize ("Hwp" with "Hna").
-      wp_bind (f _).
-      iApply (rwp_wand with "Hwp"). iIntros (v) "[Hna _]".
-      do 2 wp_pure _. rewrite -tcwp_rwp.
-      iApply ("IH" with "Hone Hna").
-  Qed.
-
-  Lemma enqueue_spec `{FiniteBoundedExistential SI} q (f: val) :
-    queue q ∗ $ one ∗ $ one ∗ SEQ (f #()) [{ _, True }] ⊢ SEQ (enqueue q f) [{v, ⌜v = #()⌝ }].
-  Proof.
-    iIntros "[#Q [Hc Hf]] Hna". rewrite /enqueue.
-    iDestruct "Q" as (l) "[-> I]".
-    iMod (na_inv_acc_open _ _ _ with "I Hna") as "Hinv"; auto.
-    iApply (tcwp_burn_credit with "Hc"); first done.
-    iNext. iDestruct "Hinv" as "(Hinv & Hna & Hclose)".
-    iDestruct "Hinv" as (xs) "Hstack".
-    iPoseProof (push_spec with "[$Hstack $Hf]") as "Hpush".
-    iApply (rswp_strong_mono with "Hpush"); auto.
-    iIntros (v) "(-> & Hstack)". iMod ("Hclose" with "[Hstack $Hna]"); eauto.
-  Qed.
-
-  Lemma mkqueue_spec :
-    sbi_emp_valid (SEQ (mkqueue #()) [{ q, queue q}])%I.
-  Proof.
-    iIntros "Hna". rewrite /mkqueue. wp_pures.
-    iMod (new_stack_spec) as "_".
-    iIntros (v) "H". iDestruct "H" as (l) "[-> Hstack]".
-    iMod (na_inv_alloc with "[Hstack]"); last first.
-    { iModIntro. iFrame. iExists l. iSplit; eauto. }
-    iNext. by iExists nil.
-  Qed.
-
-End eventloop_spec.
-
-
-
-
-
-Section open_example.
-
-  Variable external_code: val.
-  Variable print: val.
-  Variable q: val.
-  Context {SI} {Σ: gFunctors SI} `{Hheap: !heapG Σ} `{Htc: !tcG Σ} `{Hseq: !seqG Σ} (N : namespace).
-
-
-  Definition for_loop: val :=
-    (rec: "loop" "f"  "n" :=
-      if: "n" ≤ #0 then #() else let: "m" := "n" - #1 in "f" #() ;; "loop" "f" "m")%V.
-
-  Notation "'for:' n 'do' e" := (for_loop (λ: <>, e)%V n%V) (at level 200, n at level 200, e at level 200) : val_scope.
-  Notation "'for:' n 'do' e" := (for_loop (λ: <>, e)%E n%E) (at level 200, n at level 200, e at level 200) : expr_scope.
-
-  Definition example : expr :=
-    let: "n" := external_code #() in
-    for: "n" do
-      enqueue q (λ: <>, print "Hello World!").
-
-  Lemma for_zero e:
-    sbi_emp_valid (WP (for: #0 do e)%V [{ v, ⌜v = #()⌝ }])%I.
-  Proof.
-    rewrite /for_loop; by wp_pures.
-  Qed.
-
-  Lemma for_val (n: nat) e φ:
-    WP (for: #n do e)%V [{v, φ v}] ⊢ WP (for: #n do e) [{ v, φ v }].
-  Proof.
-    rewrite /for_loop; iIntros "H". by wp_pure _.
-  Qed.
-
-
-  Lemma for_succ (n: nat) e φ:
-    WP e;; (for: #n do e)%V [{v, φ v}] ⊢ WP (for: #(S n) do e)%V [{ v, φ v }].
-  Proof.
-    rewrite /for_loop; iIntros "H". wp_pures.
-    by replace (S n - 1) with (n: Z) by lia.
-  Qed.
-
-  Lemma example_spec `{FiniteBoundedExistential SI}:
-    queue N q ∗ $ (omul one) ∗ SEQ external_code #() [{ v, ∃ n: nat, ⌜v = #n⌝ }] ∗ (□ ∀ s: string, SEQ print s [{ _, True }]) ⊢
-    SEQ example [{ _, True }].
-  Proof.
-    iIntros "(#Q & Hc & Hwp & #Hprint) Hna". rewrite /example.
-    wp_bind (external_code _). iMod ("Hwp" with "Hna") as "_".
-    iIntros (v) "[Hna Hn] !>". iDestruct "Hn" as (n) "->".
-    do 2 wp_pure _. iApply (tc_weaken (omul one) (natmul (n * 2)%nat one)); auto; first apply (ord_stepindex.limit_upper_bound (λ n, natmul n one)).
-    iFrame "Hc". iIntros "Hc". iApply for_val.
-    iInduction n as [|n] "IH".
-    - iMod (for_zero) as "_"; iFrame; auto.
-    - simpl. rewrite !tc_split. iDestruct "Hc" as "(Ho & Ho' & Hc)".
-      iApply for_succ. wp_pures.
-      wp_bind (enqueue _ _).
-      iMod (enqueue_spec with "[$Q $Ho $Ho'] Hna") as "_".
-      + iIntros "Hna". wp_pures. iMod ("Hprint" with "Hna") as "_"; auto.
-      + iIntros (v) "[Hna _] !>". wp_pures. iApply ("IH" with "Hna Hc").
-  Qed.
-
-End open_example.
-
diff --git a/theories/examples/termination/logrel.v b/theories/examples/termination/logrel.v
deleted file mode 100644
index 2452064b95ba3ad92547554646946ee78a83d784..0000000000000000000000000000000000000000
--- a/theories/examples/termination/logrel.v
+++ /dev/null
@@ -1,931 +0,0 @@
-
-From iris.program_logic.refinement Require Export seq_weakestpre.
-From iris.base_logic.lib Require Export invariants na_invariants.
-From iris.heap_lang Require Export lang lifting.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation metatheory.
-From iris.algebra Require Import auth.
-From iris.algebra.ordinals Require Import arithmetic.
-Set Default Proof Using "Type".
-
-
-
-Section token_ra.
-  Context {SI: indexT} {Σ: gFunctors SI} `{!inG Σ (authR (unitUR SI))}.
-
-  Definition tok γ := own γ (● ()).
-
-  Lemma tok_alloc: ⊢ (|==> ∃ γ, tok γ)%I.
-  Proof.
-    iStartProof. iMod (own_alloc (● ())); auto.
-    by apply auth_auth_valid.
-  Qed.
-
-  Lemma tok_unique γ: tok γ ∗ tok γ ⊢ False.
-  Proof.
-    rewrite /tok -own_op own_valid -auth_auth_frac_op uPred.discrete_valid.
-    iIntros (Htok). apply ->(@auth_auth_frac_valid SI) in Htok.
-    destruct Htok as [Htok _]. apply ->(@frac_valid' SI) in Htok.
-    exfalso. by eapply Qp_not_plus_q_ge_1.
-  Qed.
-
-End token_ra.
-
-
-
-
-(* the heap values for empty, value, and computation *)
-Definition div : expr := (rec: "f" "x" := "f" "x") #().
-Definition E : expr := InjL #().
-Definition V (e: expr): expr := InjR (InjL e).
-Definition C (e: expr): expr := InjR (InjR e).
-Definition EV : val := InjLV #().
-Definition VV (v: val): val := InjRV (InjLV v).
-Definition CV (v: val): val := InjRV (InjRV v).
-Definition caseof : val :=
-  λ: "e" "e_empty" "e_val" "e_cont",
-  match: "e" with
-    InjL <> => "e_empty" #()
-  | InjR "x" =>
-    match: "x" with
-    InjL "v" => "e_val" "v"
-    | InjR "f" => "e_cont" "f"
-    end
-  end.
-Notation "'case' e 'of' 'E' => e1 | 'V' v => e2 | 'C' c => e3 'end'" := (caseof e (λ: <>, e1)%E (λ: v, e2)%E (λ: c, e3)%E).
-
-Definition letpair : val :=
-  λ: "p" "f", "f" (Fst "p") (Snd "p").
-
-Notation "'let:' ( x , y ) := p 'in' e" := (letpair p (λ: x y, e)%E) (at level 200, x at level 1, y at level 1, p, e at level 200, format "'[' 'let:'  ( x , y )  :=  '[' p ']'  'in'  '/' e ']'") : expr_scope.
-
-Definition iter : val :=
-  rec: "iter" "s" := λ: "n" "f", if: "n" = #0 then "s" else "iter" ("f" "s") ("n" - #1) "f".
-
-Definition chan : val :=
-  λ: <>, let: "c" := ref E in ("c", "c").
-
-Definition put : val :=
-  λ: "p",
-  let: "c" := Fst "p" in
-  let: "v" := Snd "p" in
-  case ! "c" of
-    E => "c" <- V "v"
-  | V <> => div
-  | C "f" => "c" <- E;; "f" "v"
-  end.
-
-Definition get : val :=
-  λ: "p",
-  let: "c" := Fst "p" in
-  let: "f" := Snd "p" in
-  case ! "c" of
-    E => "c" <- C "f"
-  | V "v" => "c" <- E;; "f" "v"
-  | C <> => div
-  end.
-
-Section semantic_model.
-  Context {SI} {Σ: gFunctors SI} `{Heap: !heapG Σ} `{TimeCredits: !tcG Σ} `{Sequential: !seqG Σ} `{FBI: FiniteBoundedExistential SI} `{Tok: !inG Σ (authR (unitUR SI))}.
-
-  Implicit Types (l r: loc).
-  Implicit Types (n: nat).
-  Implicit Types (b: bool).
-  Implicit Types (e : expr).
-  Implicit Types (v f: val).
-  Implicit Types (P Q: iProp Σ).
-  Implicit Types (Φ Ψ: val → iProp Σ).
-  Implicit Types (x y: string).
-
-
-  Section execution_lemmas.
-    Lemma rwp_put_empty l v:
-      l ↦ EV ⊢ WP (put (#l, v)%V)%E [{ w, ⌜w = #()⌝ ∗ l ↦ VV v}].
-    Proof.
-      iIntros "Hl". rewrite /put /caseof. wp_pures. wp_load. wp_pures.
-      wp_store. by iFrame.
-    Qed.
-
-    Lemma rwp_put_cont l f v Φ:
-      l ↦ CV f ∗ WP f v [{ w, Φ w }] ⊢ WP (put (#l, v)%V)%E [{ w, Φ w ∗ l ↦ EV}].
-    Proof.
-      iIntros "[Hl Hwp]". rewrite /put /caseof. wp_pures. wp_load. wp_pures.
-      wp_store. by iFrame "Hl".
-    Qed.
-
-    Lemma rwp_get_empty l f:
-      l ↦ EV ⊢ WP (get (#l, f)%V)%E [{ w, ⌜w = #()⌝ ∗ l ↦ CV f}].
-    Proof.
-      iIntros "Hl". rewrite /get /caseof. wp_pures. wp_load. wp_pures.
-      wp_store. by iFrame.
-    Qed.
-
-    Lemma rwp_get_val l f v Φ:
-      l ↦ VV v ∗ WP f v [{ w, Φ w }] ⊢ WP (get (#l, f)%V)%E [{ w, Φ w ∗ l ↦ EV}].
-    Proof.
-      iIntros "[Hl Hwp]". rewrite /get /caseof. wp_pures. wp_load. wp_pures.
-      wp_store. by iFrame "Hl".
-    Qed.
-
-    Lemma rwp_chan :
-      ⊢ (WP (chan #())%E [{ v, ∃ l, ⌜v = (#l, #l)%V⌝ ∗ l ↦ EV}])%I.
-    Proof.
-      iStartProof. rewrite /chan. wp_pures. wp_alloc l as "Hl".
-      wp_pures. eauto.
-    Qed.
-  End execution_lemmas.
-
-
-  Section closed_lemmas.
-  (* the channel invariant *)
-  Definition ch_inv  γget γput l A :=
-    (l ↦ EV ∨ (∃ v, l ↦ VV v ∗ tok γput  ∗ A v) ∨ (∃ f, l ↦ CV f ∗ tok γget ∗ ∀ v, A v -∗ SEQ f v [{ v, ⌜v = #()⌝ }]))%I.
-
-  (* we have a linear type system *)
-  Definition lN := nroot .@ "type".
-  Definition ltype := val -d> iProp Σ.
-
-  Implicit Types (A B C: ltype).
-
-  (* type interpretations *)
-  Definition lunit : ltype := λ v, (⌜v = #()⌝)%I.
-  Definition lbool : ltype := λ v, (∃ b, ⌜v = #b⌝)%I.
-  Definition lnat : ltype := λ v, (∃ n, ⌜v = #n⌝)%I.
-  Definition lget A : ltype := λ v, (∃ l γget γput, ⌜v = #l⌝ ∗ tok γget ∗ se_inv (lN .@ l) (ch_inv γget γput l A) ∗ $ one)%I.
-  Definition lput A : ltype := λ v, (∃ l γget γput, ⌜v = #l⌝ ∗ tok γput ∗ se_inv (lN .@ l) (ch_inv γget γput l A) ∗ $ one)%I.
-  Definition ltensor A B : ltype := λ v, (∃ v1 v2, ⌜v = (v1, v2)%V⌝ ∗ A v1 ∗ B v2)%I.
-  Definition larr A B : ltype := λ f, (∀ v, A v -∗ SEQ f v [{ v, B v }])%I.
-
-  Lemma closed_unit_intro: (SEQ #() [{ v, lunit v }])%I.
-  Proof.
-    iApply seq_value. by rewrite /lunit.
-  Qed.
-
-  Lemma closed_unit_elim e1 e2 Φ: (SEQ e1 [{ v, lunit v}] ∗ SEQ e2 [{ v, Φ v }] ⊢ SEQ e1;;e2 [{ v, Φ v }])%I.
-  Proof.
-    iIntros "[He He2] Hna". wp_bind e1.
-    iMod ("He" with "Hna") as "_". iIntros (v) "[Hna ->] !>".
-    wp_pures. by iApply "He2".
-  Qed.
-
-  Lemma closed_bool_intro (b: bool): (SEQ #b [{ v, lbool v }])%I.
-  Proof.
-    iApply seq_value. rewrite /lbool; eauto.
-  Qed.
-
-  Lemma closed_bool_elim e e_1 e_2 A P: (SEQ e [{ v, lbool v}] ∗ (P -∗ SEQ e_1 [{ v, A v}]) ∗ (P -∗ SEQ e_2 [{ v, A v}]) ∗ P) ⊢ (SEQ (if: e then e_1 else e_2) [{ v, A v}])%I.
-  Proof.
-    iIntros "(He & H1 & H2 & P) Hna". wp_bind e.
-    iMod ("He" with "Hna") as "_"; iIntros (v) "[Hna Hb] !>"; iDestruct "Hb" as ([]) "->".
-    - wp_pures. iApply ("H1" with "P Hna").
-    - wp_pures. iApply ("H2" with "P Hna").
-  Qed.
-
-  Lemma closed_nat_intro n: (SEQ #n [{ v, lnat v }])%I.
-  Proof.
-    iApply seq_value. rewrite /lnat; eauto.
-  Qed.
-
-  Lemma closed_nat_add e1 e2: (SEQ e1 [{ v, lnat v }] ∗ SEQ e2 [{ v, lnat v }] ⊢ SEQ (e1 + e2) [{ v, lnat v}])%I.
-  Proof.
-    iIntros "(H1 & H2) Hna".
-    wp_bind e2. iMod ("H2" with "Hna") as "_"; iIntros (v2) "[Hna Hv2] !>"; iDestruct "Hv2" as (n2) "->".
-    wp_bind e1. iMod ("H1" with "Hna") as "_"; iIntros (v1) "[Hna Hv1] !>"; iDestruct "Hv1" as (n1) "->".
-    wp_pures. iFrame. rewrite /lnat; iExists (n1 + n2)%nat. iPureIntro. do 2 f_equal.
-    lia.
-  Qed.
-
-  Lemma closed_nat_iter_n n s f α A: (SEQ s [{ v, A v }] ∗ (□ $ α -∗ ∀ v, A v -∗ SEQ f v [{ w, A w }]) ∗ $ (natmul n α) ⊢ SEQ (iter s #n f) [{ v, A v}])%I.
-  Proof.
-    iIntros "(H1 & #H2 & Hc) Hna". iInduction n as [|n] "IH" forall (s); simpl.
-    all: wp_bind s; iMod ("H1" with "Hna") as "_"; iIntros (v) "[Hna Hv] !>".
-    - rewrite /iter. wp_pures. replace (#0%nat) with (#0) by ((do 2 f_equal); lia).
-      wp_pure _; first naive_solver. wp_pures. by iFrame.
-    - rewrite tc_split. iDestruct "Hc" as "[Hα Hc]".
-      rewrite /iter. wp_pures. wp_pure _; first naive_solver.
-      wp_pures. replace (S n - 1) with (n: Z) by lia.
-      iApply ("IH" with "[Hα Hv] Hc Hna"). iApply ("H2" with "Hα Hv").
-  Qed.
-
-
-  Lemma closed_nat_iter e1 e2 f α A: (SEQ e1 [{ v, lnat v }] ∗ SEQ e2 [{ v, A v }] ∗ (□ $ α -∗ ∀ v, A v -∗ SEQ f v [{ w, A w }]) ∗ $ (omul α) ⊢ SEQ (iter e2 e1 f) [{ v, A v}])%I.
-  Proof.
-    iIntros "(H1 & H2 & H3 & Hc) Hna".
-    wp_bind e1. iMod ("H1" with "Hna") as "_"; iIntros (v) "[Hna Hv] !>"; iDestruct "Hv" as (n) "->".
-    iApply (tc_weaken (omul α) (natmul n α) with "[H2 H3 Hna $Hc]"); auto.
-    { eapply (ord_stepindex.limit_upper_bound (λ n, natmul n α)). }
-    iIntros "Hα". iApply (closed_nat_iter_n with "[$H2 $H3 $Hα] Hna").
-  Qed.
-
-  Lemma closed_fun_intro x e A B: (∀ v, A v -∗ SEQ (subst x v e) [{ w, B w}] ) ⊢ (SEQ (λ: x, e) [{ v, larr A B v}])%I.
-  Proof.
-    iIntros "H Hna". wp_pures. iFrame. iIntros (v) "Hv Hna". wp_pures.
-    by iApply ("H" with "Hv Hna").
-  Qed.
-
-  Lemma closed_fun_elim e_1 e_2 A B: (SEQ e_1 [{ v, larr A B v}] ∗ SEQ e_2 [{ v, A v }]) ⊢ (SEQ (e_1 e_2) [{ v, B v}])%I.
-  Proof.
-    iIntros "(H1 & H2) Hna".
-    wp_bind e_2. iMod ("H2" with "Hna") as "_"; iIntros (v) "[Hna HA] !>".
-    wp_bind e_1. iMod ("H1" with "Hna") as "_"; iIntros (f) "[Hna HAB] !>".
-    iApply ("HAB" with "HA Hna").
-  Qed.
-
-  Lemma closed_tensor_intro e_1 e_2 A B: (SEQ e_1 [{ v, A v}] ∗ SEQ e_2 [{ v, B v }]) ⊢ (SEQ (e_1, e_2) [{ v, ltensor A B v}])%I.
-  Proof.
-    iIntros "(H1 & H2) Hna".
-    wp_bind e_2. iMod ("H2" with "Hna") as "_"; iIntros (v2) "[Hna HB] !>".
-    wp_bind e_1. iMod ("H1" with "Hna") as "_"; iIntros (v1) "[Hna HA] !>".
-    wp_pures. iFrame. iExists v1, v2; by iFrame.
-  Qed.
-
-  Lemma closed_tensor_elim x y e1 e2 A B C: x ≠ y → (SEQ e1 [{ v, ltensor A B v }]) ∗ (∀ v1 v2, A v1 -∗ B v2 -∗ SEQ (subst y v2 (subst x v1 e2)) [{ w, C w}]) ⊢ (SEQ (let: (x, y) := e1 in e2) [{ v, C v}])%I.
-  Proof.
-    iIntros (Hneq) "[H1 H2] Hna". wp_pures. wp_bind e1.
-    iMod ("H1" with "Hna") as "_". iIntros (p) "[Hna Hp] !>".
-    iDestruct "Hp" as (v1 v2) "(-> & Hv1 & Hv2)".
-    rewrite /letpair. wp_pures.
-    destruct decide as [H|H].
-    - iApply ("H2" with "Hv1 Hv2 Hna").
-    - exfalso. apply H; split; auto. by injection 1.
-  Qed.
-
-
-  Lemma closed_get e1 e2 A: SEQ e1 [{ v, lget A v}] ∗ SEQ e2 [{ f, larr A lunit f}] ⊢ SEQ (get (e1, e2)) [{ v, lunit v}].
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    iIntros "[H1 H2] Hna".
-    wp_bind e2. iMod ("H2" with "Hna") as "_"; iIntros (f) "[Hna Hf] !>".
-    wp_bind e1. iMod ("H1" with "Hna") as "_"; iIntros (?) "[Hna Hloc] !>"; iDestruct "Hloc" as (l γget γput) "(-> & Hget & #I & Hone)".
-    iMod (na_inv_acc_open with "I Hna") as "P"; auto.
-    iApply (tcwp_burn_credit with "Hone"); first done. iNext. wp_pures. (* we use the step from expressions to values here conventiently *)
-    rewrite -tcwp_rwp.
-    iDestruct "P" as "([HI|[HI|HI]] & Hna & Hclose)".
-    - iMod (rwp_get_empty with "HI") as "_". iIntros (?) "(-> & Hl)".
-      iMod ("Hclose" with "[Hf Hl Hget $Hna]") as "Hna".
-      { iNext. iRight. iRight. iExists f. iFrame. }
-      iModIntro. iFrame. eauto.
-    - iDestruct "HI" as (v) "[Hl [Hput Hv]]".
-      iSpecialize ("Hf" with "Hv").
-      (* we need to close the invariant after the value has been updated before we execute f, since f assumes all invariants *)
-      rewrite /get. wp_pures. wp_load. rewrite /caseof. wp_pures.
-      wp_store. iApply fupd_rwp.
-      iMod ("Hclose" with "[Hl $Hna]") as "Hna".
-      { iNext. by iLeft. }
-      iApply ("Hf" with "Hna").
-    - iDestruct "HI" as (f') "[_ [Hget' _]]".
-      iExFalso. iApply (tok_unique with "[$Hget $Hget']").
-  Qed.
-
-  Lemma closed_put e1 e2 A: SEQ e1 [{ v, lput A v}] ∗ SEQ e2 [{ v, A v}] ⊢ SEQ (put (e1, e2)) [{ v, lunit v}].
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    iIntros "[H1 H2] Hna".
-    wp_bind e2. iMod ("H2" with "Hna") as "_"; iIntros (v) "[Hna Hv] !>".
-    wp_bind e1. iMod ("H1" with "Hna") as "_"; iIntros (?) "[Hna Hloc] !>"; iDestruct "Hloc" as (l γget γput) "(-> & Hput & #I & Hone)".
-    iMod (na_inv_acc_open with "I Hna") as "P"; auto.
-    iApply (tcwp_burn_credit with "Hone"); first done. iNext. wp_pures. (* we use the step from expressions to values here conventiently *)
-    rewrite -tcwp_rwp.
-    iDestruct "P" as "([HI|[HI|HI]] & Hna & Hclose)".
-    - iMod (rwp_put_empty with "HI") as "_". iIntros (?) "(-> & Hl)".
-      iMod ("Hclose" with "[Hv Hl Hput $Hna]") as "Hna".
-      { iNext. iRight. iLeft. iExists v. iFrame. }
-      iModIntro. by iFrame.
-    - iDestruct "HI" as (v') "[Hl [Hput' _]]".
-      iExFalso. iApply (tok_unique with "[$Hput $Hput']").
-    - iDestruct "HI" as (f) "[Hl [Hget Hf]]".
-      iSpecialize ("Hf" with "Hv").
-      (* we need to close the invariant after the value has been updated before we execute f, since f assumes all invariants *)
-      rewrite /put. wp_pures. wp_load. rewrite /caseof. wp_pures.
-      wp_store. iApply fupd_rwp.
-      iMod ("Hclose" with "[Hl $Hna]") as "Hna".
-      { iNext. by iLeft. }
-      iApply ("Hf" with "Hna").
-  Qed.
-
-  Lemma closed_chan A: $ one ∗ $ one ⊢ SEQ (chan #()) [{ v, ltensor (lget A) (lput A) v}].
-  Proof.
-    iIntros "[Hone Hone'] Hna".
-    iMod (rwp_chan) as "_". iIntros (v) "Hv". iDestruct "Hv" as (l) "[-> Hl]".
-    iMod (tok_alloc) as (γget) "Hget".
-    iMod (tok_alloc) as (γput) "Hput".
-    iMod (na_inv_alloc seqG_name _  (lN .@ l) (ch_inv γget γput l A)  with "[Hl]") as "#I".
-    { iNext. by iLeft. }
-    iModIntro; rewrite /ltensor /lget /lput; iFrame.
-    iExists #l, #l; iSplit; auto.
-    iSplitL "Hget"; iExists l, γget, γput; iFrame; eauto.
-  Qed.
-
-  End closed_lemmas.
-
-  Section simple_logical_relation.
-  (* The semantic typing judgment *)
-  Implicit Types (Γ Δ: gmap string ltype).
-  Implicit Types (θ τ: gmap string val).
-
-  Definition env_ltyped Γ θ: iProp Σ := ([∗ map] x ↦ A ∈ Γ, ∃ v, ⌜θ !! x = Some v⌝ ∗ A v)%I.
-  Definition ltyped Γ e A := ⊢ (∃ α, $ α -∗ ∀ θ, env_ltyped Γ θ -∗ SEQ subst_map θ e [{ v, A v }])%I.
-  Notation "Γ ⊨ e : A" := (ltyped Γ e A) (at level 100, e at next level, A at level 200) : bi_scope.
-
-  Lemma env_ltyped_split Γ Δ θ: Γ ##ₘ Δ → env_ltyped (Γ ∪ Δ) θ ⊢ env_ltyped Γ θ ∗ env_ltyped Δ θ.
-  Proof.
-    intros H. rewrite /env_ltyped. by rewrite big_sepM_union.
-  Qed.
-
-  Lemma env_ltyped_empty θ: ⊢ (env_ltyped ∅ θ).
-  Proof.
-    iStartProof. by rewrite /env_ltyped big_sepM_empty.
-  Qed.
-
-  Lemma env_ltyped_insert Γ θ A v x: env_ltyped Γ θ ∗ A v ⊢ env_ltyped (<[x:=A]> Γ) (<[x:=v]> θ).
-  Proof.
-    iIntros "[HΓ HA]". destruct (Γ !! x) eqn: Hx.
-    - rewrite -[<[x:=A]> Γ]insert_delete. iApply (big_sepM_insert_2 with "[HA] [HΓ]"); simpl.
-      + iExists v. iFrame. iPureIntro. apply lookup_insert.
-      + rewrite /env_ltyped.
-        rewrite big_sepM_delete; last apply Hx.
-        iDestruct "HΓ" as "[_ HΓ]". iApply (big_sepM_mono with "HΓ").
-        iIntros (y B Hy) "Hv"; simpl. iDestruct "Hv" as (w) "[% B]".
-        iExists w. iFrame. iPureIntro.
-        rewrite lookup_insert_ne; auto.
-        intros ->. rewrite lookup_delete in Hy. discriminate.
-    - iApply (big_sepM_insert_2 with "[HA] [HΓ]"); simpl.
-      + iExists v. iFrame. iPureIntro. apply lookup_insert.
-      + rewrite /env_ltyped. iApply (big_sepM_mono with "HΓ").
-        iIntros (y B Hy) "Hv"; simpl. iDestruct "Hv" as (w) "[% B]".
-        iExists w. iFrame. iPureIntro.
-        rewrite lookup_insert_ne; auto.
-        intros ->. rewrite Hy in Hx. discriminate.
-  Qed.
-
-  Lemma env_ltyped_weaken x A Γ θ: Γ !! x = None → env_ltyped (<[x:=A]> Γ) θ ⊢ env_ltyped Γ θ.
-  Proof.
-    intros Hx. rewrite insert_union_singleton_l. iIntros "H".
-    iPoseProof (env_ltyped_split with "H") as "[_ $]".
-    apply map_disjoint_insert_l_2, map_disjoint_empty_l; auto.
-  Qed.
-
-  (* the typing rules *)
-  Lemma variable x A: ({[ x := A ]} ⊨ x : A)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (θ) "HΓ". rewrite /env_ltyped.
-    iPoseProof (big_sepM_lookup _ _ x A with "HΓ") as "Hx"; first eapply lookup_insert.
-    simpl; iDestruct "Hx" as (v) "(-> & HA)".
-    by iApply seq_value.
-  Qed.
-
-  Lemma weaken x Γ e A B: Γ !! x = None → (Γ ⊨ e : B)%I → (<[ x := A ]> Γ ⊨ e : B)%I.
-  Proof.
-    intros Hx He. iDestruct He as (α) "He".
-    iExists α. iIntros "Hα". iIntros (θ) "Hθ".
-    iApply ("He" with "Hα"). by iApply (env_ltyped_weaken with "Hθ").
-  Qed.
-
-  Lemma unit_intro: (∅ ⊨ #() : lunit)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (θ) "HΓ"; simpl. iApply closed_unit_intro.
-  Qed.
-
-  Lemma unit_elim Γ Δ e e' A: Γ ##ₘ Δ → (Γ ⊨ e : lunit)%I → (Δ ⊨ e' : A)%I → (Γ ∪ Δ ⊨ (e ;; e'): A)%I.
-  Proof.
-    intros Hdis He He'. iDestruct He as (α_e) "He". iDestruct He' as (α_e') "He'".
-    iExists (α_e ⊕ α_e'). rewrite tc_split. iIntros "[α_e α_e']".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("He" with "α_e HΓ"). iSpecialize ("He'" with "α_e' HΔ").
-    simpl; iApply (closed_unit_elim with "[$He $He']").
-  Qed.
-
-  Lemma bool_intro b: (∅ ⊨ #b : lbool)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (θ) "HΓ"; simpl. iApply closed_bool_intro.
-  Qed.
-
-  Lemma bool_elim Γ Δ e e_1 e_2 A: Γ ##ₘ Δ → (Γ ⊨ e : lbool)%I → (Δ ⊨ e_1 : A)%I  → (Δ ⊨ e_2 : A)%I → (Γ ∪ Δ ⊨ (if: e then e_1 else e_2): A)%I.
-  Proof.
-    intros Hdis He H1 H2. iDestruct He as (α_e) "He". iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_e ⊕ α_1 ⊕ α_2). rewrite !tc_split. iIntros "[[α_e α_1] α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("He" with "α_e HΓ"). simpl.
-    iApply (closed_bool_elim _ _ _ _ (env_ltyped Δ θ)); iFrame.
-    iSplitL "H1 α_1".
-    - iApply ("H1" with "α_1").
-    - iApply ("H2" with "α_2").
-  Qed.
-
-  Lemma nat_intro n: (∅ ⊨ #n : lnat)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (θ) "HΓ"; simpl. iApply closed_nat_intro.
-  Qed.
-
-  Lemma nat_plus e1 e2 Γ Δ: Γ ##ₘ Δ → (Γ ⊨ e1 : lnat)%I → (Δ ⊨ e2 : lnat)%I → (Γ ∪ Δ ⊨ e1 + e2 : lnat)%I.
-  Proof.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 HΓ"). iSpecialize ("H2" with "α_2 HΔ").
-    simpl; iApply (closed_nat_add with "[$H1 $H2]").
-  Qed.
-
-  Lemma nat_elim e e_0 e_S x A Γ Δ: Γ ##ₘ Δ → (Γ ⊨ e : lnat)%I → (Δ ⊨ e_0 : A)%I → ({[ x := A ]} ⊨ e_S : A)%I → (Γ ∪ Δ ⊨ iter e_0 e (λ: x, e_S)%V : A)%I.
-  Proof.
-    intros Hdis He H0 HS.
-    iDestruct He as (α_e) "He". iDestruct H0 as (α_0) "H0". iDestruct HS as (α_S) "HS".
-    iExists (α_e ⊕ α_0 ⊕ omul α_S). rewrite !tc_split. iIntros "[[α_e α_0] α_S]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]". simpl.
-    iSpecialize ("He" with "α_e HΓ"). iSpecialize ("H0" with "α_0 HΔ").
-    simpl; iApply (closed_nat_iter _ _ _ α_S with "[$He $H0 $α_S]").
-    iModIntro. iIntros "α_S". iIntros (v) "Hv".
-    iIntros "Hna". wp_pures.
-    replace e_S with (subst_map (delete x ∅) e_S) at 1; last by rewrite delete_empty subst_map_empty.
-    rewrite -subst_map_insert. iApply ("HS" with "α_S [Hv] Hna").
-    iApply env_ltyped_insert; iFrame.
-    iApply env_ltyped_empty.
-  Qed.
-
-  Lemma fun_intro Γ x e A B: ((<[x:=A]> Γ) ⊨ e : B)%I → (Γ ⊨ (λ: x, e) : larr A B)%I.
-  Proof.
-    intros He. iDestruct He as (α_e) "He". iExists α_e.
-    iIntros "α_e". iSpecialize ("He" with "α_e").
-    iIntros (θ) "HΓ". simpl.  iApply (closed_fun_intro).
-    iIntros (v) "Hv". rewrite -subst_map_insert. iApply ("He" with "[HΓ Hv]").
-    iApply (env_ltyped_insert with "[$HΓ Hv]"); first done.
-  Qed.
-
-  Lemma fun_elim Γ Δ e1 e2 A B: Γ ##ₘ Δ → (Γ ⊨ e1 : larr A B)%I → (Δ ⊨ e2 : A)%I → (Γ ∪ Δ ⊨ (e1 e2): B)%I.
-  Proof.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 HΓ"). iSpecialize ("H2" with "α_2 HΔ").
-    simpl; iApply (closed_fun_elim with "[$H1 $H2]").
-  Qed.
-
-  Lemma tensor_intro Γ Δ e1 e2 A B: Γ ##ₘ Δ → (Γ ⊨ e1 : A)%I → (Δ ⊨ e2 : B)%I → (Γ ∪ Δ ⊨ (e1, e2): ltensor A B)%I.
-  Proof.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 HΓ"). iSpecialize ("H2" with "α_2 HΔ").
-    iApply (closed_tensor_intro with "[$H1 $H2]").
-  Qed.
-
-  Lemma tensor_elim Γ Δ x y e1 e2 A B C: x ≠ y → Γ ##ₘ Δ → (Γ ⊨ e1 : ltensor A B)%I → ((<[x := A]> (<[y := B]> Δ)) ⊨ e2 : C)%I → (Γ ∪ Δ ⊨ (let: (x, y) := e1 in e2) : C)%I.
-  Proof.
-    intros Hne Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 HΓ"). simpl. iApply (closed_tensor_elim with "[$H1 HΔ α_2]"); auto.
-    iIntros (v1 v2) "Hv1 Hv2".
-    rewrite delete_commute -subst_map_insert -delete_insert_ne; auto.
-    rewrite -subst_map_insert. iApply ("H2" with "α_2").
-    rewrite insert_commute; auto.
-    do 2 (iApply env_ltyped_insert; iFrame).
-  Qed.
-
-  Lemma chan_alloc A: (∅ ⊨ chan #() : ltensor (lget A) (lput A))%I.
-  Proof.
-    iExists (one ⊕ one). rewrite tc_split. iIntros "Hcred".
-    iIntros (θ) "_"; simpl. iApply (closed_chan A with "Hcred").
-  Qed.
-
-  Lemma chan_get Γ Δ e1 e2 A: Γ ##ₘ Δ → (Γ ⊨ e1 : lget A)%I → (Δ ⊨ e2 : larr A lunit)%I → (Γ ∪ Δ ⊨ get (e1, e2)%E: lunit)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 HΓ"). iSpecialize ("H2" with "α_2 HΔ").
-    simpl; iApply (closed_get with "[$H1 $H2]").
-  Qed.
-
-  Lemma chan_put Γ Δ e1 e2 A: Γ ##ₘ Δ → (Γ ⊨ e1 : lput A)%I → (Δ ⊨ e2 : A)%I → (Γ ∪ Δ ⊨ put (e1, e2)%E: lunit)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (θ). rewrite env_ltyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 HΓ"). iSpecialize ("H2" with "α_2 HΔ").
-    simpl; iApply (closed_put with "[$H1 $H2]").
-  Qed.
-
-  End simple_logical_relation.
-
-  Section polymorphic_logical_relation.
-  (* The semantic typing judgment *)
-  Implicit Types (Ω: gset string) (* the type variables *).
-  Implicit Types (δ: gmap string ltype) (* the instantiation of the type variables *).
-  Definition lptype := gmap string ltype -d> ltype.
-
-  Implicit Types (Π Ξ: gmap string lptype). (* the variables, given an instantiation of the type variables *)
-  Implicit Types (T U: lptype). (* the types *)
-  Implicit Types (θ τ: gmap string val).
-
-  Definition subst_cons δ X A := <[X := A]> δ.
-  Definition subst_ty (T: lptype) (X: string) U : lptype := λ δ, T (subst_cons δ X (U δ)).
-  Definition well_formed Ω δ : iProp Σ := (⌜Ω ≡ dom (gset string) δ⌝)%I.
-  Definition well_formed_type Ω T : Prop := (∀ δ δ', (∀ X, X ∈ Ω → δ !! X = δ' !! X) → T δ = T δ').
-  Definition well_formed_ctx Ω Π : Prop := (∀ x T, Π !! x = Some T → well_formed_type Ω T).
-  Definition env_lptyped Π δ θ : iProp Σ := (env_ltyped (fmap (λ T, T δ) Π) θ)%I.
-  Definition lptyped Ω Π e T := ⊢ (∃ α, $ α -∗ ∀ δ, well_formed Ω δ -∗ ∀ θ, env_lptyped Π δ θ -∗ SEQ subst_map θ e [{ v, (T δ) v }])%I.
-  Notation "Ω ; Π ⊨ e : T" := (lptyped Ω Π e T) (at level 100, Π at next level, e at next level, T at level 200) : bi_scope.
-
-  (* Notation for well-formedness *)
-  Class is_wf (A B: Type) := Is_wf: A → B → Prop.
-  Notation "A ⊨ B" := (Is_wf A B) (at level 100, B at level 200).
-  Instance: is_wf (gset string) (lptype) := well_formed_type.
-  Instance: is_wf (gset string) (gmap string lptype) := well_formed_ctx.
-
-  Definition lpunit : lptype := λ _, lunit.
-  Definition lpbool : lptype := λ _, lbool.
-  Definition lpnat : lptype := λ _, lnat.
-  Definition lpget T : lptype := λ δ, lget (T δ).
-  Definition lpput T : lptype := λ δ, lput (T δ).
-  Definition lptensor T U : lptype := λ δ, ltensor (T δ) (U δ).
-  Definition lparr T U : lptype := λ δ, larr (T δ) (U δ).
-  Definition lpforall X (T: lptype) : lptype := λ δ f, (∀ U, SEQ (f #()) [{ u, (subst_ty T X U) δ u }])%I.
-  Definition lpexists X (T: lptype) : lptype := λ δ v, (∃ U, (subst_ty T X U) δ v)%I.
-
-  Definition tlam e : expr := λ: <>, e.
-  Definition tapp e : expr := e #().
-  Definition pack e : expr := e.
-  Definition unpack e x e' : expr := (λ: x, e') e.
-
-  Lemma well_formed_empty:
-    True ⊢ well_formed ∅ ∅.
-  Proof using SI Σ.
-    iIntros (Heq). iPureIntro.
-    by rewrite dom_empty.
-  Qed.
-
-
-  Lemma well_formed_insert Ω δ X A:
-    well_formed Ω δ ⊢ well_formed ({[X]} ∪ Ω) (subst_cons δ X A).
-  Proof using SI Σ.
-    iIntros (Heq). iPureIntro.
-    by rewrite dom_insert Heq.
-  Qed.
-
-  Lemma env_lptyped_split Π Ξ δ θ: Π ##ₘ Ξ → env_lptyped (Π ∪ Ξ) δ θ ⊢ env_lptyped Π δ θ ∗ env_lptyped Ξ δ θ.
-  Proof.
-    intros H. rewrite /env_lptyped /env_ltyped !big_sepM_fmap big_sepM_union; auto.
-  Qed.
-
-  Lemma env_lptyped_empty δ θ: sbi_emp_valid (env_lptyped ∅ δ θ).
-  Proof.
-    iStartProof. by rewrite /env_lptyped /env_ltyped !big_sepM_fmap big_sepM_empty.
-  Qed.
-
-  Lemma env_lptyped_insert Π δ θ T v x: env_lptyped Π δ θ ∗ T δ v ⊢ env_lptyped (<[x:=T]> Π) δ (<[x:=v]> θ).
-  Proof.
-    rewrite /env_lptyped fmap_insert. eapply env_ltyped_insert.
-  Qed.
-
-  Lemma env_lptyped_weaken x T Π θ δ: Π !! x = None → env_lptyped (<[x:=T]> Π) δ θ ⊢ env_lptyped Π δ θ.
-  Proof.
-    intros Hx. rewrite /env_lptyped fmap_insert env_ltyped_weaken //= lookup_fmap Hx //=.
-  Qed.
-
-  Lemma env_lptyped_update_type_map Ω Π T δ X θ:
-    (Ω ⊨ Π) → (X ∉ Ω) → env_lptyped Π δ θ ⊢ env_lptyped Π (subst_cons δ X (T δ)) θ.
-  Proof using SI Σ.
-    clear FBI. intros Hwf HX. rewrite /env_lptyped /env_ltyped !big_opM_fmap.
-    iIntros "Hθ". iApply (big_sepM_mono with "Hθ").
-    iIntros (Y B HYB) "H". iDestruct "H" as (v) "[% B]".
-    iExists v; iSplit; auto.
-    feed pose proof (Hwf _ _ HYB δ (<[X:=T δ]> δ)) as HB.
-    { intros Z Hx'. assert (X ≠ Z) by  set_solver. by rewrite lookup_insert_ne. }
-    by erewrite HB.
-  Qed.
-
-
-  (* the typing rules *)
-  Lemma poly_variable Ω x T: (Ω; {[ x := T ]} ⊨ x : T)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (δ) "%". iIntros (θ) "HΓ". rewrite /env_lptyped /env_ltyped big_opM_fmap.
-    iPoseProof (big_sepM_lookup _ _ x T with "HΓ") as "Hx"; first eapply lookup_insert.
-    simpl; iDestruct "Hx" as (v) "(-> & HA)".
-    by iApply seq_value.
-  Qed.
-
-  Lemma poly_weaken x Ω Π e T U: Π !! x = None → (Ω; Π ⊨ e : U)%I → (Ω; (<[ x := T ]> Π) ⊨ e : U)%I.
-  Proof.
-    intros Hx He. iDestruct He as (α) "He".
-    iExists α. iIntros "Hα". iIntros (δ) "Hδ". iIntros (θ) "Hθ".
-    iApply ("He" with "Hα Hδ"). by iApply (env_lptyped_weaken with "Hθ").
-  Qed.
-
-  Lemma poly_unit_intro Ω: (Ω; ∅ ⊨ #() : lpunit)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (δ) "Hδ". iIntros (θ) "HΓ"; simpl. iApply closed_unit_intro.
-  Qed.
-
-  Lemma poly_unit_elim Ω Π Ξ e e' T: Π ##ₘ Ξ → (Ω; Π ⊨ e : lpunit)%I → (Ω; Ξ ⊨ e' : T)%I → (Ω; Π ∪ Ξ ⊨ (e ;; e'): T)%I.
-  Proof.
-    intros Hdis He He'. iDestruct He as (α_e) "He". iDestruct He' as (α_e') "He'".
-    iExists (α_e ⊕ α_e'). rewrite tc_split. iIntros "[α_e α_e']".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("He" with "α_e Hδ HΓ"). iSpecialize ("He'" with "α_e' Hδ HΔ").
-    simpl; iApply (closed_unit_elim with "[$He $He']").
-  Qed.
-
-  Lemma poly_bool_intro Ω b: (Ω; ∅ ⊨ #b : lpbool)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (δ) "#Hδ". iIntros (θ) "HΓ"; simpl. iApply closed_bool_intro.
-  Qed.
-
-  Lemma poly_bool_elim Ω Π Ξ e e_1 e_2 T:
-    Π ##ₘ Ξ
-    → (Ω; Π ⊨ e : lpbool)%I
-    → (Ω; Ξ ⊨ e_1 : T)%I
-    → (Ω; Ξ ⊨ e_2 : T)%I
-    → (Ω; (Π ∪ Ξ) ⊨ (if: e then e_1 else e_2): T)%I.
-  Proof.
-    intros Hdis He H1 H2. iDestruct He as (α_e) "He". iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_e ⊕ α_1 ⊕ α_2). rewrite !tc_split. iIntros "[[α_e α_1] α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("He" with "α_e Hδ HΓ"). simpl.
-    iApply (closed_bool_elim _ _ _ _ (env_lptyped Ξ δ θ)); iFrame.
-    iSplitL "H1 α_1".
-    - iApply ("H1" with "α_1 Hδ").
-    - iApply ("H2" with "α_2 Hδ").
-  Qed.
-
-  Lemma poly_nat_intro Ω n: (Ω; ∅ ⊨ #n : lpnat)%I.
-  Proof.
-    iExists ord_stepindex.zero. iIntros "_".
-    iIntros (δ) "#Hδ". iIntros (θ) "HΓ"; simpl. iApply closed_nat_intro.
-  Qed.
-
-  Lemma poly_nat_plus Ω e1 e2 Π Ξ: Π ##ₘ Ξ → (Ω; Π ⊨ e1 : lpnat)%I → (Ω; Ξ ⊨ e2 : lpnat)%I → (Ω; Π ∪ Ξ ⊨ e1 + e2 : lpnat)%I.
-  Proof.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 Hδ HΓ"). iSpecialize ("H2" with "α_2 Hδ HΔ").
-    simpl; iApply (closed_nat_add with "[$H1 $H2]").
-  Qed.
-
-  Lemma poly_nat_elim Ω e e_0 e_S x T Π Ξ:
-    Π ##ₘ Ξ
-    → (Ω; Π ⊨ e : lpnat)%I
-    → (Ω; Ξ ⊨ e_0 : T)%I
-    → (Ω; {[ x := T ]} ⊨ e_S : T)%I
-    → (Ω; Π ∪ Ξ ⊨ iter e_0 e (λ: x, e_S)%V : T)%I.
-  Proof.
-    intros Hdis He H0 HS.
-    iDestruct He as (α_e) "He". iDestruct H0 as (α_0) "H0". iDestruct HS as (α_S) "HS".
-    iExists (α_e ⊕ α_0 ⊕ omul α_S). rewrite !tc_split. iIntros "[[α_e α_0] α_S]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]". simpl.
-    iSpecialize ("He" with "α_e Hδ HΓ"). iSpecialize ("H0" with "α_0 Hδ HΔ").
-    simpl; iApply (closed_nat_iter _ _ _ α_S with "[$He $H0 $α_S]").
-    iModIntro. iIntros "α_S". iIntros (v) "Hv".
-    iIntros "Hna". wp_pures.
-    replace e_S with (subst_map (delete x ∅) e_S) at 1; last by rewrite delete_empty subst_map_empty.
-    rewrite -subst_map_insert. iApply ("HS" with "α_S Hδ [Hv] Hna").
-    iApply env_lptyped_insert; iFrame.
-    iApply env_lptyped_empty.
-  Qed.
-
-  Lemma poly_fun_intro Ω Π x e T U:
-    (Ω; (<[x:=T]> Π) ⊨ e : U)%I
-    → (Ω; Π ⊨ (λ: x, e) : lparr T U)%I.
-  Proof.
-    intros He. iDestruct He as (α_e) "He". iExists α_e.
-    iIntros "α_e". iSpecialize ("He" with "α_e").
-    iIntros (δ) "#Hδ". iIntros (θ) "HΓ". simpl.  iApply (closed_fun_intro).
-    iIntros (v) "Hv". rewrite -subst_map_insert. iApply ("He" with "Hδ [HΓ Hv]").
-    iApply (env_lptyped_insert with "[$HΓ Hv]"); first done.
-  Qed.
-
-  Lemma poly_fun_elim Ω Π Ξ e1 e2 T U:
-    Π ##ₘ Ξ
-    → (Ω; Π ⊨ e1 : lparr T U)%I
-    → (Ω; Ξ ⊨ e2 : T)%I
-    → (Ω; Π ∪ Ξ ⊨ (e1 e2): U)%I.
-  Proof.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 Hδ HΓ"). iSpecialize ("H2" with "α_2 Hδ HΔ").
-    simpl; iApply (closed_fun_elim with "[$H1 $H2]").
-  Qed.
-
-  Lemma poly_tensor_intro Ω Π Ξ e1 e2 T U:
-    Π ##ₘ Ξ
-    → (Ω; Π ⊨ e1 : T)%I
-    → (Ω; Ξ ⊨ e2 : U)%I
-    → (Ω; Π ∪ Ξ ⊨ (e1, e2): lptensor T U)%I.
-  Proof.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 Hδ HΓ"). iSpecialize ("H2" with "α_2 Hδ HΔ").
-    iApply (closed_tensor_intro with "[$H1 $H2]").
-  Qed.
-
-  Lemma poly_tensor_elim Ω Π Ξ x y e1 e2 T1 T2 U:
-    x ≠ y
-    → Π ##ₘ Ξ
-    → (Ω; Π ⊨ e1 : lptensor T1 T2)%I
-    → (Ω; (<[x := T1]> (<[y := T2]> Ξ)) ⊨ e2 : U)%I
-    → (Ω; Π ∪ Ξ ⊨ (let: (x, y) := e1 in e2) : U)%I.
-  Proof.
-    intros Hne Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 Hδ HΓ"). simpl. iApply (closed_tensor_elim with "[$H1 HΔ α_2]"); auto.
-    iIntros (v1 v2) "Hv1 Hv2".
-    rewrite delete_commute -subst_map_insert -delete_insert_ne; auto.
-    rewrite -subst_map_insert. iApply ("H2" with "α_2 Hδ").
-    rewrite insert_commute; auto.
-    do 2 (iApply env_lptyped_insert; iFrame).
-  Qed.
-
-  Lemma poly_chan_alloc Ω T: (Ω; ∅ ⊨ chan #() : lptensor (lpget T) (lpput T))%I.
-  Proof.
-    iExists (one ⊕ one). rewrite tc_split. iIntros "Hcred".
-    iIntros (δ) "#Hδ". iIntros (θ) "_"; simpl. iApply (closed_chan (T δ) with "Hcred").
-  Qed.
-
-  Lemma poly_chan_get Ω Π Ξ e1 e2 T:
-    Π ##ₘ Ξ
-    → (Ω; Π ⊨ e1 : lpget T)%I
-    → (Ω; Ξ ⊨ e2 : lparr T lpunit)%I
-    → (Ω; Π ∪ Ξ ⊨ get (e1, e2)%E: lpunit)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 Hδ HΓ"). iSpecialize ("H2" with "α_2 Hδ HΔ").
-    simpl; iApply (closed_get with "[$H1 $H2]").
-  Qed.
-
-  Lemma poly_chan_put Ω Π Ξ e1 e2 T:
-    Π ##ₘ Ξ
-    → (Ω; Π ⊨ e1 : lpput T)%I
-    → (Ω; Ξ ⊨ e2 : T)%I
-    → (Ω; Π ∪ Ξ ⊨ put (e1, e2)%E: lpunit)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros Hdis H1 H2. iDestruct H1 as (α_1) "H1". iDestruct H2 as (α_2) "H2".
-    iExists (α_1 ⊕ α_2). rewrite tc_split. iIntros "[α_1 α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split; auto. iIntros "[HΓ HΔ]".
-    iSpecialize ("H1" with "α_1 Hδ HΓ"). iSpecialize ("H2" with "α_2 Hδ HΔ").
-    simpl; iApply (closed_put with "[$H1 $H2]").
-  Qed.
-
-
-  Lemma poly_forall_intro Ω X Π e T:
-    (Ω ⊨ Π) → X ∉ Ω → (({[X]} ∪ Ω); Π ⊨ e : T)%I → (Ω; Π ⊨ tlam e : lpforall X T)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros Hwf Hx He.
-    iDestruct He as (α_e) "He". iExists α_e.
-    iIntros "Ha". iSpecialize ("He" with "Ha").
-    iIntros (δ) "Hδ". iIntros (θ) "Hθ". simpl.
-    iIntros "Hna". wp_pures. iFrame.
-    unfold lpforall. iIntros (U) "Hna".
-    wp_pures. unfold subst_ty. iApply ("He" with "[Hδ] [Hθ] Hna").
-    - by iApply well_formed_insert.
-    - iApply (env_lptyped_update_type_map with "Hθ"); eauto.
-  Qed.
-
-  (* For the compatibility lemma, we do not need well-formedness of U. It's only needed for type preservation. *)
-  Lemma poly_forall_elim Ω X Π e T U:
-    (* Ω ⊨ U → *) (Ω; Π ⊨ e : lpforall X T)%I → (Ω; Π ⊨ tapp e : subst_ty T X U)%I.
-  Proof.
-    intros He.
-    iDestruct He as (α_e) "He". iExists α_e.
-    iIntros "Ha". iSpecialize ("He" with "Ha").
-    iIntros (δ) "Hδ". iIntros (θ) "Hθ". simpl.
-    iIntros "Hna". wp_bind (subst_map _ e).
-    iMod ("He" with "Hδ Hθ Hna") as "_".
-    iIntros (v) "[Hna Hf] !>". rewrite /lpforall.
-    by iApply "Hf".
-  Qed.
-
-  (* Well-formedness assumptions needed for type preservation but not for the compatibility lemma.*)
-  Lemma poly_exists_intro Ω X Π e T U:
-    (Ω; Π ⊨ e : subst_ty T X U)%I → (Ω; Π ⊨ pack e : lpexists X T)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros He.
-    iDestruct He as (α_e) "He". iExists α_e.
-    iIntros "Ha". iSpecialize ("He" with "Ha").
-    iIntros (δ) "Hδ". iIntros (θ) "Hθ".
-    iIntros "Hna". iMod ("He" with "Hδ Hθ Hna") as "_".
-    iIntros (v) "[$ HT] !>". by iExists U.
-  Qed.
-
-  Lemma poly_exists_elim Ω X Π Ξ x e e2 T U:
-    X ∉ Ω
-    → (Ω ⊨ Ξ)
-    → (Ω ⊨ U)
-    → Π ##ₘ Ξ
-    → (Ω; Π ⊨ e : lpexists X T)%I
-    → ({[X]} ∪ Ω; <[x := T ]> Ξ ⊨ e2 : U)%I
-    → (Ω; Π ∪ Ξ ⊨ unpack e x e2 : U)%I.
-  Proof using FBI Heap SI Sequential TimeCredits Σ.
-    intros Hx Hwf HwfU Hdis He He2.
-    iDestruct He as (α_e) "He". iDestruct He2 as (α_2) "H2".
-    iExists (α_e ⊕ α_2). rewrite tc_split. iIntros "[α_e α_2]".
-    iIntros (δ) "#Hδ". iIntros (θ). rewrite env_lptyped_split //=.
-    iIntros "[HΓ HΞ] Hna".
-    wp_bind (subst_map _ e). iMod ("He" with "α_e Hδ HΓ Hna") as "_".
-    iIntros (v) "[Hna Hv] !>". iDestruct "Hv" as (T') "Hv".
-    wp_pures. rewrite -subst_map_insert.
-    iMod ("H2" with "α_2 [Hδ] [HΞ Hv] Hna") as "_".
-    - by iApply well_formed_insert.
-    - iApply env_lptyped_insert; iFrame.
-      iApply (env_lptyped_update_type_map with "HΞ"); eauto.
-    - feed pose proof (HwfU δ (<[X := (T' δ)]> δ)).
-      { intros Z Hx'. assert (X ≠ Z) by set_solver. by rewrite lookup_insert_ne. }
-      iIntros (w) "[$ HU] !>". by rewrite -H.
-  Qed.
-
-End polymorphic_logical_relation.
-
-End semantic_model.
-
-From iris.examples.termination Require Import adequacy.
-Section adequacy.
-
-  Context {SI} `{C: Classical}  {Σ: gFunctors SI} {Hlarge: LargeIndex SI}.
-  Context `{Hpre: !heapPreG Σ} `{Hna: !na_invG Σ} `{Htc: !inG Σ (authR (ordA SI))}.
-
-  Theorem simple_logrel_adequacy (e: expr) σ A:
-    (∀ `{heapG SI Σ} `{!seqG Σ} `{!auth_sourceG Σ (ordA SI)},
-      ltyped ∅ e A
-    ) →
-    sn erased_step ([e], σ).
-  Proof using Hlarge C Σ Hpre Hna Htc.
-    intros Htyped.
-    eapply heap_lang_ref_adequacy.
-    intros ???. iIntros "_".
-    iPoseProof (Htyped) as (α) "H".
-    iExists α. iIntros "Hα". iSpecialize ("H" with "Hα").
-    iPoseProof (env_ltyped_empty ∅) as "Henv". iSpecialize ("H" with "Henv").
-    rewrite subst_map_empty. iIntros "Hna". iMod ("H" with "Hna"); eauto.
-    by iIntros (v) "[$ _]".
-  Qed.
-
-  Theorem logrel_adequacy (e: expr) σ A:
-    (∀ `{heapG SI Σ} `{!seqG Σ} `{!auth_sourceG Σ (ordA SI)},
-      lptyped ∅ ∅ e A
-    ) →
-    sn erased_step ([e], σ).
-  Proof using Hlarge C Σ Hpre Hna Htc.
-    intros Htyped.
-    eapply heap_lang_ref_adequacy.
-    intros ???. iIntros "_".
-    iPoseProof (Htyped) as (α) "H".
-    iExists α. iIntros "Hα". iSpecialize ("H" with "Hα").
-    iPoseProof (well_formed_empty with "[//]") as "Hctx".
-    iPoseProof (env_lptyped_empty ∅ ∅) as "Henv".
-    iSpecialize ("H" with "Hctx Henv").
-    rewrite subst_map_empty. iIntros "Hna". iMod ("H" with "Hna"); eauto.
-    by iIntros (v) "[$ _]".
-  Qed.
-
-End adequacy.
-
-Section ordinals. 
-  Context `{C: Classical}  {Σ: gFunctors ordI}.
-  Context `{Hpre: !heapPreG Σ} `{Hna: !na_invG Σ} `{Htc: !inG Σ (authR (ordA ordI))}.
-
-  Theorem simple_logrel_adequacy_ord (e: expr) σ A:
-    (∀ `{heapG ordI Σ} `{!seqG Σ} `{!auth_sourceG Σ (ordA ordI)},
-      ltyped ∅ e A
-    ) →
-    sn erased_step ([e], σ).
-  Proof using C Σ Hpre Hna Htc.
-    intros Htyped.
-    eapply heap_lang_ref_adequacy.
-    intros ???. iIntros "_".
-    iPoseProof (Htyped) as (α) "H".
-    iExists α. iIntros "Hα". iSpecialize ("H" with "Hα").
-    iPoseProof (env_ltyped_empty ∅) as "Henv". iSpecialize ("H" with "Henv").
-    rewrite subst_map_empty. iIntros "Hna". iMod ("H" with "Hna"); eauto.
-    by iIntros (v) "[$ _]".
-  Qed.
-
-  Theorem logrel_adequacy_ord (e: expr) σ A:
-    (∀ `{heapG ordI Σ} `{!seqG Σ} `{!auth_sourceG Σ (ordA ordI)},
-      lptyped ∅ ∅ e A
-    ) →
-    sn erased_step ([e], σ).
-  Proof using C Σ Hpre Hna Htc.
-    intros Htyped.
-    eapply heap_lang_ref_adequacy.
-    intros ???. iIntros "_".
-    iPoseProof (Htyped) as (α) "H".
-    iExists α. iIntros "Hα". iSpecialize ("H" with "Hα").
-    iPoseProof (well_formed_empty with "[//]") as "Hctx".
-    iPoseProof (env_lptyped_empty ∅ ∅) as "Henv".
-    iSpecialize ("H" with "Hctx Henv").
-    rewrite subst_map_empty. iIntros "Hna". iMod ("H" with "Hna"); eauto.
-    by iIntros (v) "[$ _]".
-  Qed.
-
-End ordinals.
-
diff --git a/theories/examples/termination/thunk.v b/theories/examples/termination/thunk.v
deleted file mode 100644
index 615ea79a76fbdbc4e9be2f6260e44f02c46b9c1c..0000000000000000000000000000000000000000
--- a/theories/examples/termination/thunk.v
+++ /dev/null
@@ -1,139 +0,0 @@
-From iris.program_logic.refinement Require Export seq_weakestpre.
-From iris.base_logic.lib Require Export invariants na_invariants.
-From iris.heap_lang Require Export lang lifting.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation metatheory.
-From iris.algebra Require Import auth.
-From iris.algebra.ordinals Require Import arithmetic.
-Set Default Proof Using "Type".
-
-
-
-Definition thunk : val :=
-  λ: "f", let: "r" := ref NONE in
-  λ: <>, match: !"r" with
-    SOME "v" => "v"
-    | NONE => (let: "y" := "f" #() in "r" <- SOME "y";; "y")
-  end.
-
-Section thunk_proof.
-  Context {SI} {Σ: gFunctors SI} `{Hheap: !heapG Σ} `{Htc: !tcG Σ} (N : namespace) `{Htok: !inG Σ (authR (unitUR SI))}.
-
-  Implicit Types (α β: ord_stepindex.Ord).
-
-  (* simplest spec - one to one correspondence *)
-  Lemma thunk_partial_spec (f: val) Φ:
-    WP f #() {{ Φ }} -∗ WP (thunk f) {{ g, WP g #() {{ Φ }} }}.
-  Proof.
-    iIntros "Hf". unfold thunk. wp_pures. wp_bind (ref _)%E.
-    wp_alloc r as "Hr"; wp_pures.
-    wp_pures. wp_load. wp_pures.
-    wp_apply (wp_wand with "Hf [Hr]").
-    iIntros (v) "Hv"; wp_pures.
-    by wp_store.
-  Qed.
-
-  Lemma thunk_spec (f: val) Φ:
-    WP f #() [{ Φ }] -∗ WP (thunk f) [{ g, WP g #() [{ Φ }] }].
-  Proof.
-    iIntros "Hf". unfold thunk. wp_pures. wp_bind (ref _)%E.
-    wp_alloc r as "Hr"; wp_pures.
-    wp_pures. wp_load. wp_pures.
-    wp_apply (rwp_wand with "Hf [Hr]").
-    iIntros (v) "Hv"; wp_pures.
-    by wp_store.
-  Qed.
-
-
-  Definition thunk_inv `{!seqG Σ} r (f: val) Φ : iProp Σ :=
-    (r ↦ NONEV ∗ SEQ  (f #()) @ (⊤ ∖ ↑N) ⟨⟨ v, Φ v ⟩⟩ ∨ (∃ v, r ↦ SOMEV v ∗ Φ v))%I.
-
-  Lemma thunk_sequential_spec `{!seqG Σ} `{FiniteBoundedExistential SI} (f: val) Φ:
-    (∀ x, Persistent (Φ x)) →
-    SEQ (f #()) @ (⊤ ∖ ↑N) ⟨⟨ v, Φ v ⟩⟩ -∗
-    SEQ (thunk f) ⟨⟨ g, □ $one -∗ SEQ (g #()) ⟨⟨ v, Φ v⟩⟩⟩⟩.
-  Proof.
-    iIntros (HΦ) "Hf". rewrite /thunk. iIntros "Hna".
-    wp_pures. wp_bind (ref _)%E.
-    wp_alloc r as "Hr".
-    iMod (na_inv_alloc seqG_name _ N (thunk_inv r f Φ) with "[Hr Hf]") as "#I".
-    { iNext. iLeft. by iFrame. }
-    wp_pures. iFrame. iModIntro.
-    iIntros "Hc Hna". wp_pures.
-    wp_bind (! _)%E.
-    iMod (na_inv_acc_open with "I Hna") as "P"; eauto.
-    iApply (tcwp_burn_credit with "Hc"); auto. iNext.
-    iDestruct "P" as "([H|H] & Hna & Hclose)".
-    - iDestruct "H" as "(Hr & Hwp)".
-      wp_load. wp_pures. iSpecialize ("Hwp" with "Hna").
-      wp_bind (f #()). iApply (rwp_wand with "Hwp [Hr Hclose]").
-      iIntros (v) "[Hna #HΦ]". wp_pures.
-      wp_bind (#r <- _)%E. wp_store.
-      iMod ("Hclose" with "[Hr $Hna]") as "Hna".
-      { iNext. iRight. iExists v. by iFrame. }
-      wp_pures. by iFrame.
-    - iDestruct "H" as (v) "[Hr #HΦ]".
-      wp_load. iMod ("Hclose" with "[Hr $Hna]") as "Hna".
-      { iNext. iRight. iExists v. by iFrame. }
-      wp_pures. by iFrame.
-  Qed.
-
-
-  (* the timeless portion *)
-  Definition prepaid_inv_tl `{!seqG Σ} γ r Φ : iProp Σ :=
-    ((r ↦ NONEV ∗ $ one ∗ own γ (● ())) ∨ (∃ v, r ↦ SOMEV v ∗ Φ v))%I.
-
-  Global Instance prepaid_inv_tl_timeless `{!seqG Σ} α γ Φ r: (∀ v, Timeless (Φ v)) → Timeless (prepaid_inv_tl γ r Φ).
-  Proof.
-    intros. rewrite /prepaid_inv_tl. apply _.
-  Qed.
-
-  Definition prepaid_inv_re `{!seqG Σ} γ (f: val) Φ : iProp Σ :=
-    (SEQ  (f #())  @ (⊤ ∖ ↑N.@"tl" ∖ ↑N.@"re") ⟨⟨ v, Φ v ⟩⟩ ∨ own γ (● ()))%I.
-
-
-  Lemma thunk_sequential_prepaid_spec `{!seqG Σ} `{FiniteBoundedExistential SI} (f: val) Φ:
-    (∀ x, Persistent (Φ x)) → (∀ x, Timeless (Φ x)) →
-    SEQ (f #()) @  (⊤ ∖ ↑N.@"tl" ∖ ↑N.@"re") ⟨⟨v, Φ v⟩⟩ -∗ $one -∗ SEQ (thunk f) ⟨⟨ g, □ SEQ (g #()) ⟨⟨ v, Φ v⟩⟩⟩⟩.
-  Proof using Hheap Htc Htok N SI Σ.
-    iIntros (??) "Hf Hone". rewrite /thunk. iIntros "Hna".
-    wp_pures.
-    iMod (own_alloc (● ())) as (γ) "H●"; first by apply auth_auth_valid.
-    wp_bind (ref _)%E.
-    wp_alloc r as "Hr".
-    iMod (na_inv_alloc seqG_name _ (N .@ "tl") (prepaid_inv_tl γ r Φ) with "[Hr Hone H●]") as "#Itl".
-    { iNext. iLeft. by iFrame. }
-    iMod (na_inv_alloc seqG_name _ (N .@ "re") (prepaid_inv_re γ f Φ) with "[$Hf]") as "#Ire".
-    wp_pures. iFrame. iModIntro.
-    iIntros "Hna". wp_pures.
-    wp_bind (! _)%E.
-    iMod (na_inv_acc_open_timeless with "Itl Hna") as "([H|H] & Hna & Hclose)"; eauto.
-    - iDestruct "H" as "(Hr & Hone & H●)".
-      iMod (na_inv_acc_open with "Ire Hna") as "P"; eauto; first solve_ndisj.
-      iApply (tcwp_burn_credit with "Hone"); auto.
-      iNext. iDestruct "P" as "(Hre & Hna & Hclose')".
-      wp_load. wp_pures.
-      wp_bind (f #()). rewrite /prepaid_inv_re.
-      iDestruct "Hre" as "[Hwp|H●']".
-      + iSpecialize ("Hwp" with "Hna").
-        iApply (rwp_wand with "Hwp [Hr Hclose Hclose' H●]").
-        iIntros (v) "[Hna #HΦ]". wp_pures.
-        wp_bind (#r <- _)%E. wp_store.
-        iMod ("Hclose'" with "[$Hna $H●]") as "Hna".
-        iMod ("Hclose" with "[Hr $Hna]") as "Hna".
-        { iNext. iRight. iExists v. by iFrame. }
-        wp_pures. by iFrame.
-      + iCombine "H● H●'" as "H".
-        iPoseProof (own_valid with "H") as "H".
-        rewrite uPred.discrete_valid.
-        iDestruct "H" as "%".
-        apply ->(@auth_auth_frac_valid SI) in H2.
-        destruct H2 as [H2 _]. rewrite frac_op' in H2.
-        apply ->(@frac_valid' SI) in H2.
-        exfalso. by eapply Qp_not_plus_q_ge_1.
-    - iDestruct "H" as (v) "[Hr #HΦ]".
-      wp_load. iMod ("Hclose" with "[Hr $Hna]") as "Hna".
-      { iNext. iRight. iExists v. by iFrame. }
-      wp_pures. by iFrame.
-  Qed.
-End thunk_proof.
diff --git a/theories/examples/transfinite.v b/theories/examples/transfinite.v
deleted file mode 100644
index c2554f18d771c3bb739947ca6a3dc0dafcec1b78..0000000000000000000000000000000000000000
--- a/theories/examples/transfinite.v
+++ /dev/null
@@ -1,150 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.heap_lang Require Export lang.
-From iris.proofmode Require Import tactics.
-From iris.heap_lang Require Import proofmode notation.
-From iris.algebra Require Import auth.
-From iris.examples.safety Require Import lock.
-Set Default Proof Using "Type".
-
-
-Section how_to_handle_invariants.
-  Context {SI} {Σ: gFunctors SI} `{!heapG Σ} (N : namespace).
-
-
-
-  (* We compare how opening invariants worked previously and
-     how it can be done in the transfinite setting. *)
-  Lemma invariants_previously `{FiniteIndex SI} l Φ:
-    {{{ inv N (∃ v, l ↦ v ∗ Φ v) }}} ! #l {{{ v, RET v; True }}}.
-  Proof.
-    iIntros (ϕ) "#I Post".
-    iInv "I" as "H" "Hclose".
-    iDestruct "H" as (v) "[Hl P]".
-    wp_load. iMod ("Hclose" with "[Hl P]") as "_".
-    { iNext. iExists v. iFrame. }
-    iModIntro. by iApply "Post".
-  Qed.
-
-
-  Lemma invariants_transfinite l Φ:
-    {{{ inv N (∃ v, l ↦ v ∗ Φ v) }}} ! #l {{{ v, RET v; True }}}.
-  Proof.
-    iIntros (ϕ) "#I Post".
-    (* We move from the weakest pre to the stronger version which allows us to strip off laters.
-       The argument is the number of laters we want to strip off. *)
-    wp_swp 1%nat.
-    (* SWP supports opening up invariants *)
-    iInv "I" as "H" "Hclose".
-    (* In general, we cannot commutate later with existential quantification *)
-    Fail iDestruct "H" as (v) "[Hl P]".
-    (* To access the contents of "H", we need to get rid of the later modality.
-       We use the step property of SWP to add an additional later to our goal. *)
-    swp_step. iNext; simpl.
-    (* Afterwards the proof continues exactly the same as before. *)
-    iDestruct "H" as (v) "[Hl P]".
-    wp_load. iMod ("Hclose" with "[Hl P]") as "_".
-    { iNext. iExists v. iFrame. }
-    iModIntro. by iApply "Post".
-  Qed.
-
-
-  (* Using Coq EVars we leave the step counting to Coq: *)
-  Lemma invariants_transfinite_evars l Φ:
-    {{{ inv N (∃ v, l ↦ v ∗ Φ v) }}} ! #l {{{ v, RET v; True }}}.
-  Proof.
-    iIntros (ϕ) "#I Post".
-    (* If no argument is provided to wp_swp, then the number of
-       laters is instantiated with an evar (k in the following). *)
-    wp_swp. iInv "I" as "H" "Hclose".
-    (* In calling swp_step Coq creates a new evar, say k', and picks k := S k'.
-       The user will usually only see k' from there on. *)
-    swp_step.
-    iNext; simpl.
-    iDestruct "H" as (v) "[Hl P]".
-    wp_load. iMod ("Hclose" with "[Hl P]") as "_".
-    { iNext. iExists v. iFrame. }
-    iModIntro. by iApply "Post".
-    (* At the end we need to pick a value for the evar k'. Here 0 is always sufficient. *)
-    Unshelve. exact 0%nat.
-    (* Note that from k' := 0 automatically k := 1 follows *)
-  Qed.
-
-  (* Make the instantiation step explicit *)
-  Lemma swp_finish E e s Φ : SWP e at 0%nat @ s; E {{ Φ }} ⊢ SWP e at 0%nat @ s; E {{ Φ }}.
-  Proof. eauto. Qed.
-  Ltac swp_finish := iApply swp_finish.
-  Ltac swp_last_step := swp_step; swp_finish.
-
-
-  (* Using Coq EVars we leave the step counting to Coq: *)
-  Lemma invariants_transfinite_evars_inst l Φ:
-    {{{ inv N (∃ v, l ↦ v ∗ Φ v) }}} ! #l {{{ v, RET v; True }}}.
-  Proof.
-    iIntros (ϕ) "#I Post".
-    (* If no argument is provided to wp_swp, then the number of
-       laters is instantiated with an evar (k in the following). *)
-    wp_swp. iInv "I" as "H" "Hclose".
-    (* do 5 swp_step. swp_finish. *)
-    swp_last_step.
-    iNext; simpl.
-    iDestruct "H" as (v) "[Hl P]".
-    wp_load. iMod ("Hclose" with "[Hl P]") as "_".
-    { iNext. iExists v. iFrame. }
-    iModIntro. by iApply "Post".
-  Qed.
-
-  (* Nested invariants *)
-  (* We can nest invariants and open nested invariants in a single step of computation *)
-  Section nested_invariants.
-    Context `{inG SI Σ (authR (mnatUR SI))}.
-
-    (* invariant asserting that the value stored at l is only increasing and already positive *)
-    Definition Pos N l γ : iProp Σ := inv N (∃ n: mnat, l ↦ #n ∗ ⌜n > 0⌝ ∗ own γ (◯ n))%I.
-
-
-    Definition L l1 γ : iProp Σ := inv (N .@ "L") (∃ m: mnat, l1 ↦ #m ∗ own γ (● m))%I.
-    Definition R l2 γ : iProp Σ := inv (N .@ "R") (∃ l2': loc, l2 ↦ #l2' ∗ Pos (N .@ "I") l2' γ)%I.
-
-    Lemma mnat_own (m n: mnat) γ:
-      own γ (● m) -∗ own γ (◯ n) -∗ ⌜n ≤ m⌝%nat.
-    Proof.
-      iIntros "Hγ● Hγ◯". iDestruct (own_valid_2 with "Hγ● Hγ◯") as "H"; iRevert "H".
-      iIntros (Hv). iPureIntro. eapply (mnat_included SI).
-      apply auth_both_valid in Hv as [Hv _]; done.
-    Qed.
-
-    Lemma invariants_transfinite_nested  γ l1 l2:
-      {{{ L l1 γ ∗ R l2 γ }}} !#l1 {{{ (m: nat), RET #m; ⌜m > 0⌝ }}}.
-    Proof.
-      iIntros (ϕ) "[#L #R] H".
-      (* we need to open all invariants to ensure that the value stored at l1 is positive *)
-      wp_swp 2%nat.
-      iInv "L" as "HL" "CloseL".
-      iInv "R" as "HR" "CloseR".
-      swp_step. iNext; simpl.
-      iDestruct "HL" as (m) "[Hl1 Hγ●]". iDestruct "HR" as (l2') "[Hl2 #I]".
-      iInv "I" as "HI" "CloseI".
-      swp_step. iNext; simpl.
-      iDestruct "HI" as (n) "(Hl2' & % & #Hγ◯)".
-      iPoseProof (mnat_own with "Hγ● Hγ◯") as "%".
-      wp_load.
-      iMod ("CloseI" with "[Hl2']") as "_".
-      { iExists n; iNext; iFrame; by iSplit. }
-      iModIntro. iMod ("CloseR" with "[Hl2]") as "_".
-      { iExists l2'; iNext; by iFrame. } iModIntro.
-      iMod ("CloseL" with "[Hl1 Hγ●]") as "_"; first (iNext; iExists m; iFrame).
-      iModIntro. iApply "H". iPureIntro. lia.
-    Qed.
-  End nested_invariants.
-
-
-  Lemma invariants_swp k e φ P `{!Atomic StronglyAtomic e}:
-    (P ⊢ SWP e at k @ ⊤∖↑N  {{v, φ v ∗ P}}) → inv N P ⊢ SWP e at (S k) {{ v, φ v}}.
-  Proof.
-    iIntros (H) "I". iInv "I" as "P". swp_step. iNext.
-    iPoseProof (H with "P") as "Q". iApply swp_wand_r.
-    iFrame. iIntros (v) "($ & $)". by iModIntro.
-  Qed.
-
-
-End how_to_handle_invariants.
diff --git a/theories/heap_lang/adequacy.v b/theories/heap_lang/adequacy.v
deleted file mode 100644
index eb1a8e0df2e3ba3e19cbf26fcbc6d806e5a905d7..0000000000000000000000000000000000000000
--- a/theories/heap_lang/adequacy.v
+++ /dev/null
@@ -1,38 +0,0 @@
-From iris.program_logic Require Export weakestpre adequacy.
-From iris.program_logic.refinement Require Export ref_weakestpre ref_adequacy tc_weakestpre.
-From iris.algebra Require Import auth.
-From iris.heap_lang Require Import proofmode notation.
-From iris.base_logic.lib Require Import proph_map.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-Definition heapΣ SI : gFunctors SI := #[invΣ SI; gen_heapΣ loc val; proph_mapΣ proph_id (val * val)].
-Instance subG_heapPreG {SI} {Σ: gFunctors SI} : subG (heapΣ SI) Σ → heapPreG Σ.
-Proof. solve_inG. Qed.
-
-Definition heap_adequacy {SI} `{TransfiniteIndex SI} (Σ: gFunctors SI) `{!heapPreG Σ} s e σ φ :
-  (∀ `{!heapG Σ}, sbi_emp_valid (WP e @ s; ⊤ {{ v, ⌜φ v⌝ }}%I)) →
-  adequate s e σ (λ v _, φ v).
-Proof.
-  intros Hwp; eapply (wp_adequacy _ _). iIntros (??) "".
-  iMod (gen_heap_init σ.(heap)) as (?) "Hh".
-  iMod (proph_map_init κs σ.(used_proph_id)) as (?) "Hp".
-  iModIntro. iExists
-    (λ σ κs, (gen_heap_ctx σ.(heap) ∗ proph_map_ctx κs σ.(used_proph_id))%I),
-    (λ _, True%I).
-  iFrame. iApply (Hwp (HeapG _ _ _ _ _)).
-Qed.
-
-
-Arguments satisfiable_at {_ _ _} _ _%I.
-Lemma satisfiable_at_add {SI} (Σ: gFunctors SI) `{!invG Σ} E P Q: satisfiable_at E P → sbi_emp_valid Q → satisfiable_at E (P ∗ Q).
-Proof.
-  intros Hsat Hval. eapply satisfiable_at_mono; first eauto.
-  iIntros "$". iApply Hval.
-Qed.
-
-Lemma satisfiable_at_add' {SI} (Σ: gFunctors SI) `{!invG Σ} E Q: satisfiable_at E True → sbi_emp_valid Q → satisfiable_at E Q.
-Proof.
-  intros Hsat Hval. eapply satisfiable_at_mono; first eauto.
-  iIntros "_". iApply Hval.
-Qed.
diff --git a/theories/heap_lang/lang.v b/theories/heap_lang/lang.v
deleted file mode 100644
index 723b6cbc1d0ad407b63638a9426ea98e6987fb88..0000000000000000000000000000000000000000
--- a/theories/heap_lang/lang.v
+++ /dev/null
@@ -1,769 +0,0 @@
-From iris.program_logic Require Export language ectx_language ectxi_language.
-From iris.heap_lang Require Export locations.
-From iris.algebra Require Export ofe.
-From stdpp Require Export binders strings.
-From stdpp Require Import gmap.
-Set Default Proof Using "Type".
-
-(** heap_lang.  A fairly simple language used for common Iris examples.
-
-- This is a right-to-left evaluated language, like CakeML and OCaml.  The reason
-  for this is that it makes curried functions usable: Given a WP for [f a b], we
-  know that any effects [f] might have to not matter until after *both* [a] and
-  [b] are evaluated.  With left-to-right evaluation, that triple is basically
-  useless unless the user let-expands [b].
-
-- For prophecy variables, we annotate the reduction steps with an "observation"
-  and tweak adequacy such that WP knows all future observations. There is
-  another possible choice: Use non-deterministic choice when creating a prophecy
-  variable ([NewProph]), and when resolving it ([Resolve]) make the
-  program diverge unless the variable matches. That, however, requires an
-  erasure proof that this endless loop does not make specifications useless.
-
-The expression [Resolve e p v] attaches a prophecy resolution (for prophecy
-variable [p] to value [v]) to the top-level head-reduction step of [e]. The
-prophecy resolution happens simultaneously with the head-step being taken.
-Furthermore, it is required that the head-step produces a value (otherwise
-the [Resolve] is stuck), and this value is also attached to the resolution.
-A prophecy variable is thus resolved to a pair containing (1) the result
-value of the wrapped expression (called [e] above), and (2) the value that
-was attached by the [Resolve] (called [v] above). This allows, for example,
-to distinguish a resolution originating from a successful [CmpXchg] from one
-originating from a failing [CmpXchg]. For example:
- - [Resolve (CmpXchg #l #n #(n+1)) #p v] will behave as [CmpXchg #l #n #(n+1)],
-   which means step to a value-boole pair [(n', b)] while updating the heap, but
-   in the meantime the prophecy variable [p] will be resolved to [(n', b), v)].
- - [Resolve (! #l) #p v] will behave as [! #l], that is return the value
-   [w] pointed to by [l] on the heap (assuming it was allocated properly),
-   but it will additionally resolve [p] to the pair [(w,v)].
-
-Note that the sub-expressions of [Resolve e p v] (i.e., [e], [p] and [v])
-are reduced as usual, from right to left. However, the evaluation of [e]
-is restricted so that the head-step to which the resolution is attached
-cannot be taken by the context. For example:
- - [Resolve (CmpXchg #l #n (#n + #1)) #p v] will first be reduced (with by a
-   context-step) to [Resolve (CmpXchg #l #n #(n+1) #p v], and then behave as
-   described above.
- - However, [Resolve ((λ: "n", CmpXchg #l "n" ("n" + #1)) #n) #p v] is stuck.
-   Indeed, it can only be evaluated using a head-step (it is a β-redex),
-   but the process does not yield a value.
-
-The mechanism described above supports nesting [Resolve] expressions to
-attach several prophecy resolutions to a head-redex. *)
-
-Delimit Scope expr_scope with E.
-Delimit Scope val_scope with V.
-
-Module heap_lang.
-Open Scope Z_scope.
-
-(** Expressions and vals. *)
-Definition proph_id := positive.
-
-Inductive base_lit : Set :=
-  | LitInt (n : Z) | LitBool (b : bool) | LitUnit | LitErased
-  | LitLoc (l : loc) | LitProphecy (p: proph_id).
-Inductive un_op : Set :=
-  | NegOp | MinusUnOp.
-Inductive bin_op : Set :=
-  | PlusOp | MinusOp | MultOp | QuotOp | RemOp (* Arithmetic *)
-  | AndOp | OrOp | XorOp (* Bitwise *)
-  | ShiftLOp | ShiftROp (* Shifts *)
-  | LeOp | LtOp | EqOp (* Relations *)
-  | OffsetOp. (* Pointer offset *)
-
-Inductive expr :=
-  (* Values *)
-  | Val (v : val)
-  (* Base lambda calculus *)
-  | Var (x : string)
-  | Rec (f x : binder) (e : expr)
-  | App (e1 e2 : expr)
-  (* Base types and their operations *)
-  | UnOp (op : un_op) (e : expr)
-  | BinOp (op : bin_op) (e1 e2 : expr)
-  | If (e0 e1 e2 : expr)
-  (* Products *)
-  | Pair (e1 e2 : expr)
-  | Fst (e : expr)
-  | Snd (e : expr)
-  (* Sums *)
-  | InjL (e : expr)
-  | InjR (e : expr)
-  | Case (e0 : expr) (e1 : expr) (e2 : expr)
-  (* Concurrency *)
-  | Fork (e : expr)
-  (* Heap *)
-  | AllocN (e1 e2 : expr) (* array length (positive number), initial value *)
-  | Load (e : expr)
-  | Store (e1 : expr) (e2 : expr)
-  | CmpXchg (e0 : expr) (e1 : expr) (e2 : expr) (* Compare-exchange *)
-  | FAA (e1 : expr) (e2 : expr) (* Fetch-and-add *)
-  (* Prophecy *)
-  | NewProph
-  | Resolve (e0 : expr) (e1 : expr) (e2 : expr) (* wrapped expr, proph, val *)
-with val :=
-  | LitV (l : base_lit)
-  | RecV (f x : binder) (e : expr)
-  | PairV (v1 v2 : val)
-  | InjLV (v : val)
-  | InjRV (v : val).
-
-Bind Scope expr_scope with expr.
-Bind Scope val_scope with val.
-
-(** An observation associates a prophecy variable (identifier) to a pair of
-values. The first value is the one that was returned by the (atomic) operation
-during which the prophecy resolution happened (typically, a boolean when the
-wrapped operation is a CmpXchg). The second value is the one that the prophecy
-variable was actually resolved to. *)
-Definition observation : Set := proph_id * (val * val).
-
-Notation of_val := Val (only parsing).
-
-Definition to_val (e : expr) : option val :=
-  match e with
-  | Val v => Some v
-  | _ => None
-  end.
-
-(** We assume the following encoding of values to 64-bit words: The least 3
-significant bits of every word are a "tag", and we have 61 bits of payload,
-which is enough if all pointers are 8-byte-aligned (common on 64bit
-architectures). The tags have the following meaning:
-
-0: Payload is the data for a LitV (LitInt _).
-1: Payload is the data for a InjLV (LitV (LitInt _)).
-2: Payload is the data for a InjRV (LitV (LitInt _)).
-3: Payload is the data for a LitV (LitLoc _).
-4: Payload is the data for a InjLV (LitV (LitLoc _)).
-4: Payload is the data for a InjRV (LitV (LitLoc _)).
-6: Payload is one of the following finitely many values, which 61 bits are more
-   than enough to encode:
-   LitV LitUnit, InjLV (LitV LitUnit), InjRV (LitV LitUnit),
-   LitV (LitBool _), InjLV (LitV (LitBool _)), InjRV (LitV (LitBool _)).
-7: Value is boxed, i.e., payload is a pointer to some read-only memory area on
-   the heap which stores whether this is a RecV, PairV, InjLV or InjRV and the
-   relevant data for those cases. However, the boxed representation is never
-   used if any of the above representations could be used.
-
-Ignoring (as usual) the fact that we have to fit the infinite Z/loc into 61
-bits, this means every value is machine-word-sized and can hence be atomically
-read and written.  Also notice that the sets of boxed and unboxed values are
-disjoint. *)
-Definition lit_is_unboxed (l: base_lit) : Prop :=
-  match l with
-  (** Disallow comparing (erased) prophecies with (erased) prophecies, by
-  considering them boxed. *)
-  | LitProphecy _ | LitErased => False
-  | _ => True
-  end.
-Definition val_is_unboxed (v : val) : Prop :=
-  match v with
-  | LitV l => lit_is_unboxed l
-  | InjLV (LitV l) => lit_is_unboxed l
-  | InjRV (LitV l) => lit_is_unboxed l
-  | _ => False
-  end.
-
-Instance lit_is_unboxed_dec l : Decision (lit_is_unboxed l).
-Proof. destruct l; simpl; exact (decide _). Defined.
-Instance val_is_unboxed_dec v : Decision (val_is_unboxed v).
-Proof. destruct v as [ | | | [] | [] ]; simpl; exact (decide _). Defined.
-
-(** We just compare the word-sized representation of two values, without looking
-into boxed data.  This works out fine if at least one of the to-be-compared
-values is unboxed (exploiting the fact that an unboxed and a boxed value can
-never be equal because these are disjoint sets). *)
-Definition vals_compare_safe (vl v1 : val) : Prop :=
-  val_is_unboxed vl ∨ val_is_unboxed v1.
-Arguments vals_compare_safe !_ !_ /.
-
-(** The state: heaps of vals. *)
-Record state : Type := {
-  heap: gmap loc val;
-  used_proph_id: gset proph_id;
-}.
-
-(** Equality and other typeclass stuff *)
-Lemma to_of_val v : to_val (of_val v) = Some v.
-Proof. by destruct v. Qed.
-
-Lemma of_to_val e v : to_val e = Some v → of_val v = e.
-Proof. destruct e=>//=. by intros [= <-]. Qed.
-
-Instance of_val_inj : Inj (=) (=) of_val.
-Proof. intros ??. congruence. Qed.
-
-Instance base_lit_eq_dec : EqDecision base_lit.
-Proof. solve_decision. Defined.
-Instance un_op_eq_dec : EqDecision un_op.
-Proof. solve_decision. Defined.
-Instance bin_op_eq_dec : EqDecision bin_op.
-Proof. solve_decision. Defined.
-Instance expr_eq_dec : EqDecision expr.
-Proof.
-  refine (
-   fix go (e1 e2 : expr) {struct e1} : Decision (e1 = e2) :=
-     match e1, e2 with
-     | Val v, Val v' => cast_if (decide (v = v'))
-     | Var x, Var x' => cast_if (decide (x = x'))
-     | Rec f x e, Rec f' x' e' =>
-        cast_if_and3 (decide (f = f')) (decide (x = x')) (decide (e = e'))
-     | App e1 e2, App e1' e2' => cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
-     | UnOp o e, UnOp o' e' => cast_if_and (decide (o = o')) (decide (e = e'))
-     | BinOp o e1 e2, BinOp o' e1' e2' =>
-        cast_if_and3 (decide (o = o')) (decide (e1 = e1')) (decide (e2 = e2'))
-     | If e0 e1 e2, If e0' e1' e2' =>
-        cast_if_and3 (decide (e0 = e0')) (decide (e1 = e1')) (decide (e2 = e2'))
-     | Pair e1 e2, Pair e1' e2' =>
-        cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
-     | Fst e, Fst e' => cast_if (decide (e = e'))
-     | Snd e, Snd e' => cast_if (decide (e = e'))
-     | InjL e, InjL e' => cast_if (decide (e = e'))
-     | InjR e, InjR e' => cast_if (decide (e = e'))
-     | Case e0 e1 e2, Case e0' e1' e2' =>
-        cast_if_and3 (decide (e0 = e0')) (decide (e1 = e1')) (decide (e2 = e2'))
-     | Fork e, Fork e' => cast_if (decide (e = e'))
-     | AllocN e1 e2, AllocN e1' e2' =>
-        cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
-     | Load e, Load e' => cast_if (decide (e = e'))
-     | Store e1 e2, Store e1' e2' =>
-        cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
-     | CmpXchg e0 e1 e2, CmpXchg e0' e1' e2' =>
-        cast_if_and3 (decide (e0 = e0')) (decide (e1 = e1')) (decide (e2 = e2'))
-     | FAA e1 e2, FAA e1' e2' =>
-        cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
-     | NewProph, NewProph => left _
-     | Resolve e0 e1 e2, Resolve e0' e1' e2' =>
-        cast_if_and3 (decide (e0 = e0')) (decide (e1 = e1')) (decide (e2 = e2'))
-     | _, _ => right _
-     end
-   with gov (v1 v2 : val) {struct v1} : Decision (v1 = v2) :=
-     match v1, v2 with
-     | LitV l, LitV l' => cast_if (decide (l = l'))
-     | RecV f x e, RecV f' x' e' =>
-        cast_if_and3 (decide (f = f')) (decide (x = x')) (decide (e = e'))
-     | PairV e1 e2, PairV e1' e2' =>
-        cast_if_and (decide (e1 = e1')) (decide (e2 = e2'))
-     | InjLV e, InjLV e' => cast_if (decide (e = e'))
-     | InjRV e, InjRV e' => cast_if (decide (e = e'))
-     | _, _ => right _
-     end
-   for go); try (clear go gov; abstract intuition congruence).
-Defined.
-Instance val_eq_dec : EqDecision val.
-Proof. solve_decision. Defined.
-Instance state_eq_dec : EqDecision state.
-Proof. solve_decision. Defined.
-
-Instance base_lit_countable : Countable base_lit.
-Proof.
- refine (inj_countable' (λ l, match l with
-  | LitInt n => (inl (inl n), None)
-  | LitBool b => (inl (inr b), None)
-  | LitUnit => (inr (inl false), None)
-  | LitErased => (inr (inl true), None)
-  | LitLoc l => (inr (inr l), None)
-  | LitProphecy p => (inr (inl false), Some p)
-  end) (λ l, match l with
-  | (inl (inl n), None) => LitInt n
-  | (inl (inr b), None) => LitBool b
-  | (inr (inl false), None) => LitUnit
-  | (inr (inl true), None) => LitErased
-  | (inr (inr l), None) => LitLoc l
-  | (_, Some p) => LitProphecy p
-  end) _); by intros [].
-Qed.
-Instance un_op_finite : Countable un_op.
-Proof.
- refine (inj_countable' (λ op, match op with NegOp => 0 | MinusUnOp => 1 end)
-  (λ n, match n with 0 => NegOp | _ => MinusUnOp end) _); by intros [].
-Qed.
-Instance bin_op_countable : Countable bin_op.
-Proof.
- refine (inj_countable' (λ op, match op with
-  | PlusOp => 0 | MinusOp => 1 | MultOp => 2 | QuotOp => 3 | RemOp => 4
-  | AndOp => 5 | OrOp => 6 | XorOp => 7 | ShiftLOp => 8 | ShiftROp => 9
-  | LeOp => 10 | LtOp => 11 | EqOp => 12 | OffsetOp => 13
-  end) (λ n, match n with
-  | 0 => PlusOp | 1 => MinusOp | 2 => MultOp | 3 => QuotOp | 4 => RemOp
-  | 5 => AndOp | 6 => OrOp | 7 => XorOp | 8 => ShiftLOp | 9 => ShiftROp
-  | 10 => LeOp | 11 => LtOp | 12 => EqOp | _ => OffsetOp
-  end) _); by intros [].
-Qed.
-Instance expr_countable : Countable expr.
-Proof.
- set (enc :=
-   fix go e :=
-     match e with
-     | Val v => GenNode 0 [gov v]
-     | Var x => GenLeaf (inl (inl x))
-     | Rec f x e => GenNode 1 [GenLeaf (inl (inr f)); GenLeaf (inl (inr x)); go e]
-     | App e1 e2 => GenNode 2 [go e1; go e2]
-     | UnOp op e => GenNode 3 [GenLeaf (inr (inr (inl op))); go e]
-     | BinOp op e1 e2 => GenNode 4 [GenLeaf (inr (inr (inr op))); go e1; go e2]
-     | If e0 e1 e2 => GenNode 5 [go e0; go e1; go e2]
-     | Pair e1 e2 => GenNode 6 [go e1; go e2]
-     | Fst e => GenNode 7 [go e]
-     | Snd e => GenNode 8 [go e]
-     | InjL e => GenNode 9 [go e]
-     | InjR e => GenNode 10 [go e]
-     | Case e0 e1 e2 => GenNode 11 [go e0; go e1; go e2]
-     | Fork e => GenNode 12 [go e]
-     | AllocN e1 e2 => GenNode 13 [go e1; go e2]
-     | Load e => GenNode 14 [go e]
-     | Store e1 e2 => GenNode 15 [go e1; go e2]
-     | CmpXchg e0 e1 e2 => GenNode 16 [go e0; go e1; go e2]
-     | FAA e1 e2 => GenNode 17 [go e1; go e2]
-     | NewProph => GenNode 18 []
-     | Resolve e0 e1 e2 => GenNode 19 [go e0; go e1; go e2]
-     end
-   with gov v :=
-     match v with
-     | LitV l => GenLeaf (inr (inl l))
-     | RecV f x e =>
-        GenNode 0 [GenLeaf (inl (inr f)); GenLeaf (inl (inr x)); go e]
-     | PairV v1 v2 => GenNode 1 [gov v1; gov v2]
-     | InjLV v => GenNode 2 [gov v]
-     | InjRV v => GenNode 3 [gov v]
-     end
-   for go).
- set (dec :=
-   fix go e :=
-     match e with
-     | GenNode 0 [v] => Val (gov v)
-     | GenLeaf (inl (inl x)) => Var x
-     | GenNode 1 [GenLeaf (inl (inr f)); GenLeaf (inl (inr x)); e] => Rec f x (go e)
-     | GenNode 2 [e1; e2] => App (go e1) (go e2)
-     | GenNode 3 [GenLeaf (inr (inr (inl op))); e] => UnOp op (go e)
-     | GenNode 4 [GenLeaf (inr (inr (inr op))); e1; e2] => BinOp op (go e1) (go e2)
-     | GenNode 5 [e0; e1; e2] => If (go e0) (go e1) (go e2)
-     | GenNode 6 [e1; e2] => Pair (go e1) (go e2)
-     | GenNode 7 [e] => Fst (go e)
-     | GenNode 8 [e] => Snd (go e)
-     | GenNode 9 [e] => InjL (go e)
-     | GenNode 10 [e] => InjR (go e)
-     | GenNode 11 [e0; e1; e2] => Case (go e0) (go e1) (go e2)
-     | GenNode 12 [e] => Fork (go e)
-     | GenNode 13 [e1; e2] => AllocN (go e1) (go e2)
-     | GenNode 14 [e] => Load (go e)
-     | GenNode 15 [e1; e2] => Store (go e1) (go e2)
-     | GenNode 16 [e0; e1; e2] => CmpXchg (go e0) (go e1) (go e2)
-     | GenNode 17 [e1; e2] => FAA (go e1) (go e2)
-     | GenNode 18 [] => NewProph
-     | GenNode 19 [e0; e1; e2] => Resolve (go e0) (go e1) (go e2)
-     | _ => Val $ LitV LitUnit (* dummy *)
-     end
-   with gov v :=
-     match v with
-     | GenLeaf (inr (inl l)) => LitV l
-     | GenNode 0 [GenLeaf (inl (inr f)); GenLeaf (inl (inr x)); e] => RecV f x (go e)
-     | GenNode 1 [v1; v2] => PairV (gov v1) (gov v2)
-     | GenNode 2 [v] => InjLV (gov v)
-     | GenNode 3 [v] => InjRV (gov v)
-     | _ => LitV LitUnit (* dummy *)
-     end
-   for go).
- refine (inj_countable' enc dec _).
- refine (fix go (e : expr) {struct e} := _ with gov (v : val) {struct v} := _ for go).
- - destruct e as [v| | | | | | | | | | | | | | | | | | | |]; simpl; f_equal;
-     [exact (gov v)|done..].
- - destruct v; by f_equal.
-Qed.
-Instance val_countable : Countable val.
-Proof. refine (inj_countable of_val to_val _); auto using to_of_val. Qed.
-
-Instance state_inhabited : Inhabited state :=
-  populate {| heap := inhabitant; used_proph_id := inhabitant |}.
-Instance val_inhabited : Inhabited val := populate (LitV LitUnit).
-Instance expr_inhabited : Inhabited expr := populate (Val inhabitant).
-
-Canonical Structure stateO SI := leibnizO SI state.
-Canonical Structure locO SI := leibnizO SI loc.
-Canonical Structure valO SI := leibnizO SI val.
-Canonical Structure exprO SI := leibnizO SI expr.
-
-(** Evaluation contexts *)
-Inductive ectx_item :=
-  | AppLCtx (v2 : val)
-  | AppRCtx (e1 : expr)
-  | UnOpCtx (op : un_op)
-  | BinOpLCtx (op : bin_op) (v2 : val)
-  | BinOpRCtx (op : bin_op) (e1 : expr)
-  | IfCtx (e1 e2 : expr)
-  | PairLCtx (v2 : val)
-  | PairRCtx (e1 : expr)
-  | FstCtx
-  | SndCtx
-  | InjLCtx
-  | InjRCtx
-  | CaseCtx (e1 : expr) (e2 : expr)
-  | AllocNLCtx (v2 : val)
-  | AllocNRCtx (e1 : expr)
-  | LoadCtx
-  | StoreLCtx (v2 : val)
-  | StoreRCtx (e1 : expr)
-  | CmpXchgLCtx (v1 : val) (v2 : val)
-  | CmpXchgMCtx (e0 : expr) (v2 : val)
-  | CmpXchgRCtx (e0 : expr) (e1 : expr)
-  | FaaLCtx (v2 : val)
-  | FaaRCtx (e1 : expr)
-  | ResolveLCtx (ctx : ectx_item) (v1 : val) (v2 : val)
-  | ResolveMCtx (e0 : expr) (v2 : val)
-  | ResolveRCtx (e0 : expr) (e1 : expr).
-
-(** Contextual closure will only reduce [e] in [Resolve e (Val _) (Val _)] if
-the local context of [e] is non-empty. As a consequence, the first argument of
-[Resolve] is not completely evaluated (down to a value) by contextual closure:
-no head steps (i.e., surface reductions) are taken. This means that contextual
-closure will reduce [Resolve (CmpXchg #l #n (#n + #1)) #p #v] into [Resolve
-(CmpXchg #l #n #(n+1)) #p #v], but it cannot context-step any further. *)
-
-Fixpoint fill_item (Ki : ectx_item) (e : expr) : expr :=
-  match Ki with
-  | AppLCtx v2 => App e (of_val v2)
-  | AppRCtx e1 => App e1 e
-  | UnOpCtx op => UnOp op e
-  | BinOpLCtx op v2 => BinOp op e (Val v2)
-  | BinOpRCtx op e1 => BinOp op e1 e
-  | IfCtx e1 e2 => If e e1 e2
-  | PairLCtx v2 => Pair e (Val v2)
-  | PairRCtx e1 => Pair e1 e
-  | FstCtx => Fst e
-  | SndCtx => Snd e
-  | InjLCtx => InjL e
-  | InjRCtx => InjR e
-  | CaseCtx e1 e2 => Case e e1 e2
-  | AllocNLCtx v2 => AllocN e (Val v2)
-  | AllocNRCtx e1 => AllocN e1 e
-  | LoadCtx => Load e
-  | StoreLCtx v2 => Store e (Val v2)
-  | StoreRCtx e1 => Store e1 e
-  | CmpXchgLCtx v1 v2 => CmpXchg e (Val v1) (Val v2)
-  | CmpXchgMCtx e0 v2 => CmpXchg e0 e (Val v2)
-  | CmpXchgRCtx e0 e1 => CmpXchg e0 e1 e
-  | FaaLCtx v2 => FAA e (Val v2)
-  | FaaRCtx e1 => FAA e1 e
-  | ResolveLCtx K v1 v2 => Resolve (fill_item K e) (Val v1) (Val v2)
-  | ResolveMCtx ex v2 => Resolve ex e (Val v2)
-  | ResolveRCtx ex e1 => Resolve ex e1 e
-  end.
-
-(** Substitution *)
-Fixpoint subst (x : string) (v : val) (e : expr)  : expr :=
-  match e with
-  | Val _ => e
-  | Var y => if decide (x = y) then Val v else Var y
-  | Rec f y e =>
-     Rec f y $ if decide (BNamed x ≠ f ∧ BNamed x ≠ y) then subst x v e else e
-  | App e1 e2 => App (subst x v e1) (subst x v e2)
-  | UnOp op e => UnOp op (subst x v e)
-  | BinOp op e1 e2 => BinOp op (subst x v e1) (subst x v e2)
-  | If e0 e1 e2 => If (subst x v e0) (subst x v e1) (subst x v e2)
-  | Pair e1 e2 => Pair (subst x v e1) (subst x v e2)
-  | Fst e => Fst (subst x v e)
-  | Snd e => Snd (subst x v e)
-  | InjL e => InjL (subst x v e)
-  | InjR e => InjR (subst x v e)
-  | Case e0 e1 e2 => Case (subst x v e0) (subst x v e1) (subst x v e2)
-  | Fork e => Fork (subst x v e)
-  | AllocN e1 e2 => AllocN (subst x v e1) (subst x v e2)
-  | Load e => Load (subst x v e)
-  | Store e1 e2 => Store (subst x v e1) (subst x v e2)
-  | CmpXchg e0 e1 e2 => CmpXchg (subst x v e0) (subst x v e1) (subst x v e2)
-  | FAA e1 e2 => FAA (subst x v e1) (subst x v e2)
-  | NewProph => NewProph
-  | Resolve ex e1 e2 => Resolve (subst x v ex) (subst x v e1) (subst x v e2)
-  end.
-
-Definition subst' (mx : binder) (v : val) : expr → expr :=
-  match mx with BNamed x => subst x v | BAnon => id end.
-
-(** The stepping relation *)
-Definition un_op_eval (op : un_op) (v : val) : option val :=
-  match op, v with
-  | NegOp, LitV (LitBool b) => Some $ LitV $ LitBool (negb b)
-  | NegOp, LitV (LitInt n) => Some $ LitV $ LitInt (Z.lnot n)
-  | MinusUnOp, LitV (LitInt n) => Some $ LitV $ LitInt (- n)
-  | _, _ => None
-  end.
-
-Definition bin_op_eval_int (op : bin_op) (n1 n2 : Z) : option base_lit :=
-  match op with
-  | PlusOp => Some $ LitInt (n1 + n2)
-  | MinusOp => Some $ LitInt (n1 - n2)
-  | MultOp => Some $ LitInt (n1 * n2)
-  | QuotOp => Some $ LitInt (n1 `quot` n2)
-  | RemOp => Some $ LitInt (n1 `rem` n2)
-  | AndOp => Some $ LitInt (Z.land n1 n2)
-  | OrOp => Some $ LitInt (Z.lor n1 n2)
-  | XorOp => Some $ LitInt (Z.lxor n1 n2)
-  | ShiftLOp => Some $ LitInt (n1 ≪ n2)
-  | ShiftROp => Some $ LitInt (n1 ≫ n2)
-  | LeOp => Some $ LitBool (bool_decide (n1 ≤ n2))
-  | LtOp => Some $ LitBool (bool_decide (n1 < n2))
-  | EqOp => Some $ LitBool (bool_decide (n1 = n2))
-  | OffsetOp => None (* Pointer arithmetic *)
-  end.
-
-Definition bin_op_eval_bool (op : bin_op) (b1 b2 : bool) : option base_lit :=
-  match op with
-  | PlusOp | MinusOp | MultOp | QuotOp | RemOp => None (* Arithmetic *)
-  | AndOp => Some (LitBool (b1 && b2))
-  | OrOp => Some (LitBool (b1 || b2))
-  | XorOp => Some (LitBool (xorb b1 b2))
-  | ShiftLOp | ShiftROp => None (* Shifts *)
-  | LeOp | LtOp => None (* InEquality *)
-  | EqOp => Some (LitBool (bool_decide (b1 = b2)))
-  | OffsetOp => None (* Pointer arithmetic *)
-  end.
-
-Definition bin_op_eval (op : bin_op) (v1 v2 : val) : option val :=
-  if decide (op = EqOp) then
-    (* Crucially, this compares the same way as [CmpXchg]! *)
-    if decide (vals_compare_safe v1 v2) then
-      Some $ LitV $ LitBool $ bool_decide (v1 = v2)
-    else
-      None
-  else
-    match v1, v2 with
-    | LitV (LitInt n1), LitV (LitInt n2) => LitV <$> bin_op_eval_int op n1 n2
-    | LitV (LitBool b1), LitV (LitBool b2) => LitV <$> bin_op_eval_bool op b1 b2
-    | LitV (LitLoc l), LitV (LitInt off) => Some $ LitV $ LitLoc (l +ₗ off)
-    | _, _ => None
-    end.
-
-Definition state_upd_heap (f: gmap loc val → gmap loc val) (σ: state) : state :=
-  {| heap := f σ.(heap); used_proph_id := σ.(used_proph_id) |}.
-Arguments state_upd_heap _ !_ /.
-
-Definition state_upd_used_proph_id (f: gset proph_id → gset proph_id) (σ: state) : state :=
-  {| heap := σ.(heap); used_proph_id := f σ.(used_proph_id) |}.
-Arguments state_upd_used_proph_id _ !_ /.
-
-Fixpoint heap_array (l : loc) (vs : list val) : gmap loc val :=
-  match vs with
-  | [] => ∅
-  | v :: vs' => {[l := v]} ∪ heap_array (l +ₗ 1) vs'
-  end.
-
-Lemma heap_array_singleton l v : heap_array l [v] = {[l := v]}.
-Proof. by rewrite /heap_array right_id. Qed.
-
-Lemma heap_array_lookup l vs w k :
-  heap_array l vs !! k = Some w ↔
-  ∃ j, 0 ≤ j ∧ k = l +ₗ j ∧ vs !! (Z.to_nat j) = Some w.
-Proof.
-  revert k l; induction vs as [|v' vs IH]=> l' l /=.
-  { rewrite lookup_empty. naive_solver lia. }
-  rewrite -insert_union_singleton_l lookup_insert_Some IH. split.
-  - intros [[-> ->] | (Hl & j & ? & -> & ?)].
-    { exists 0. rewrite loc_add_0. naive_solver lia. }
-    exists (1 + j). rewrite loc_add_assoc !Z.add_1_l Z2Nat.inj_succ; auto with lia.
-  - intros (j & ? & -> & Hil). destruct (decide (j = 0)); simplify_eq/=.
-    { rewrite loc_add_0; eauto. }
-    right. split.
-    { rewrite -{1}(loc_add_0 l). intros ?%(inj _); lia. }
-    assert (Z.to_nat j = S (Z.to_nat (j - 1))) as Hj.
-    { rewrite -Z2Nat.inj_succ; last lia. f_equal; lia. }
-    rewrite Hj /= in Hil.
-    exists (j - 1). rewrite loc_add_assoc Z.add_sub_assoc Z.add_simpl_l.
-    auto with lia.
-Qed.
-
-Lemma heap_array_map_disjoint (h : gmap loc val) (l : loc) (vs : list val) :
-  (∀ i, (0 ≤ i) → (i < length vs) → h !! (l +ₗ i) = None) →
-  (heap_array l vs) ##ₘ h.
-Proof.
-  intros Hdisj. apply map_disjoint_spec=> l' v1 v2.
-  intros (j&?&->&Hj%lookup_lt_Some%inj_lt)%heap_array_lookup.
-  move: Hj. rewrite Z2Nat.id // => ?. by rewrite Hdisj.
-Qed.
-
-(* [h] is added on the right here to make [state_init_heap_singleton] true. *)
-Definition state_init_heap (l : loc) (n : Z) (v : val) (σ : state) : state :=
-  state_upd_heap (λ h, heap_array l (replicate (Z.to_nat n) v) ∪ h) σ.
-
-Lemma state_init_heap_singleton l v σ :
-  state_init_heap l 1 v σ = state_upd_heap <[l:=v]> σ.
-Proof.
-  destruct σ as [h p]. rewrite /state_init_heap /=. f_equiv.
-  rewrite right_id insert_union_singleton_l. done.
-Qed.
-
-Inductive head_step : expr → state → list observation → expr → state → list expr → Prop :=
-  | RecS f x e σ :
-     head_step (Rec f x e) σ [] (Val $ RecV f x e) σ []
-  | PairS v1 v2 σ :
-     head_step (Pair (Val v1) (Val v2)) σ [] (Val $ PairV v1 v2) σ []
-  | InjLS v σ :
-     head_step (InjL $ Val v) σ [] (Val $ InjLV v) σ []
-  | InjRS v σ :
-     head_step (InjR $ Val v) σ [] (Val $ InjRV v) σ []
-  | BetaS f x e1 v2 e' σ :
-     e' = subst' x v2 (subst' f (RecV f x e1) e1) →
-     head_step (App (Val $ RecV f x e1) (Val v2)) σ [] e' σ []
-  | UnOpS op v v' σ :
-     un_op_eval op v = Some v' →
-     head_step (UnOp op (Val v)) σ [] (Val v') σ []
-  | BinOpS op v1 v2 v' σ :
-     bin_op_eval op v1 v2 = Some v' →
-     head_step (BinOp op (Val v1) (Val v2)) σ [] (Val v') σ []
-  | IfTrueS e1 e2 σ :
-     head_step (If (Val $ LitV $ LitBool true) e1 e2) σ [] e1 σ []
-  | IfFalseS e1 e2 σ :
-     head_step (If (Val $ LitV $ LitBool false) e1 e2) σ [] e2 σ []
-  | FstS v1 v2 σ :
-     head_step (Fst (Val $ PairV v1 v2)) σ [] (Val v1) σ []
-  | SndS v1 v2 σ :
-     head_step (Snd (Val $ PairV v1 v2)) σ [] (Val v2) σ []
-  | CaseLS v e1 e2 σ :
-     head_step (Case (Val $ InjLV v) e1 e2) σ [] (App e1 (Val v)) σ []
-  | CaseRS v e1 e2 σ :
-     head_step (Case (Val $ InjRV v) e1 e2) σ [] (App e2 (Val v)) σ []
-  | ForkS e σ:
-     head_step (Fork e) σ [] (Val $ LitV LitUnit) σ [e]
-  | AllocNS n v σ l :
-     0 < n →
-     (∀ i, 0 ≤ i → i < n → σ.(heap) !! (l +ₗ i) = None) →
-     head_step (AllocN (Val $ LitV $ LitInt n) (Val v)) σ
-               []
-               (Val $ LitV $ LitLoc l) (state_init_heap l n v σ)
-               []
-  | LoadS l v σ :
-     σ.(heap) !! l = Some v →
-     head_step (Load (Val $ LitV $ LitLoc l)) σ [] (of_val v) σ []
-  | StoreS l v σ :
-     is_Some (σ.(heap) !! l) →
-     head_step (Store (Val $ LitV $ LitLoc l) (Val v)) σ
-               []
-               (Val $ LitV LitUnit) (state_upd_heap <[l:=v]> σ)
-               []
-  | CmpXchgS l v1 v2 vl σ b :
-     σ.(heap) !! l = Some vl →
-     (* Crucially, this compares the same way as [EqOp]! *)
-     vals_compare_safe vl v1 →
-     b = bool_decide (vl = v1) →
-     head_step (CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2)) σ
-               []
-               (Val $ PairV vl (LitV $ LitBool b)) (if b then state_upd_heap <[l:=v2]> σ else σ)
-               []
-  | FaaS l i1 i2 σ :
-     σ.(heap) !! l = Some (LitV (LitInt i1)) →
-     head_step (FAA (Val $ LitV $ LitLoc l) (Val $ LitV $ LitInt i2)) σ
-               []
-               (Val $ LitV $ LitInt i1) (state_upd_heap <[l:=LitV (LitInt (i1 + i2))]>σ)
-               []
-  | NewProphS σ p :
-     p ∉ σ.(used_proph_id) →
-     head_step NewProph σ
-               []
-               (Val $ LitV $ LitProphecy p) (state_upd_used_proph_id (union {[ p ]}) σ)
-               []
-  | ResolveS p v e σ w σ' κs ts :
-     head_step e σ κs (Val v) σ' ts →
-     head_step (Resolve e (Val $ LitV $ LitProphecy p) (Val w)) σ
-               (κs ++ [(p, (v, w))]) (Val v) σ' ts.
-
-(** Basic properties about the language *)
-Instance fill_item_inj Ki : Inj (=) (=) (fill_item Ki).
-Proof. induction Ki; intros ???; simplify_eq/=; auto with f_equal. Qed.
-
-Lemma fill_item_val Ki e :
-  is_Some (to_val (fill_item Ki e)) → is_Some (to_val e).
-Proof. intros [v ?]. induction Ki; simplify_option_eq; eauto. Qed.
-
-Lemma val_head_stuck e1 σ1 κ e2 σ2 efs : head_step e1 σ1 κ e2 σ2 efs → to_val e1 = None.
-Proof. destruct 1; naive_solver. Qed.
-
-Lemma head_ctx_step_val Ki e σ1 κ e2 σ2 efs :
-  head_step (fill_item Ki e) σ1 κ e2 σ2 efs → is_Some (to_val e).
-Proof. revert κ e2. induction Ki; inversion_clear 1; simplify_option_eq; eauto. Qed.
-
-Lemma fill_item_no_val_inj Ki1 Ki2 e1 e2 :
-  to_val e1 = None → to_val e2 = None →
-  fill_item Ki1 e1 = fill_item Ki2 e2 → Ki1 = Ki2.
-Proof. revert Ki1. induction Ki2, Ki1; naive_solver eauto with f_equal. Qed.
-
-Lemma alloc_fresh v n σ :
-  let l := fresh_locs (dom (gset loc) σ.(heap)) in
-  0 < n →
-  head_step (AllocN ((Val $ LitV $ LitInt $ n)) (Val v)) σ []
-            (Val $ LitV $ LitLoc l) (state_init_heap l n v σ) [].
-Proof.
-  intros.
-  apply AllocNS; first done.
-  intros. apply (not_elem_of_dom (D := gset loc)).
-  by apply fresh_locs_fresh.
-Qed.
-
-Lemma new_proph_id_fresh σ :
-  let p := fresh σ.(used_proph_id) in
-  head_step NewProph σ [] (Val $ LitV $ LitProphecy p) (state_upd_used_proph_id (union {[ p ]}) σ) [].
-Proof. constructor. apply is_fresh. Qed.
-
-Lemma heap_lang_mixin : EctxiLanguageMixin of_val to_val fill_item head_step.
-Proof.
-  split; apply _ || eauto using to_of_val, of_to_val, val_head_stuck,
-    fill_item_val, fill_item_no_val_inj, head_ctx_step_val.
-Qed.
-End heap_lang.
-
-(** Language *)
-Canonical Structure heap_ectxi_lang := EctxiLanguage heap_lang.heap_lang_mixin.
-Canonical Structure heap_ectx_lang := EctxLanguageOfEctxi heap_ectxi_lang.
-Canonical Structure heap_lang := LanguageOfEctx heap_ectx_lang.
-
-Global Instance cfg_eq_dec : EqDecision (cfg heap_lang).
-Proof. solve_decision. Defined.
-
-(* Prefer heap_lang names over ectx_language names. *)
-Export heap_lang.
-
-(* The following lemma is not provable using the axioms of [ectxi_language].
-The proof requires a case analysis over context items ([destruct i] on the
-last line), which in all cases yields a non-value. To prove this lemma for
-[ectxi_language] in general, we would require that a term of the form
-[fill_item i e] is never a value. *)
-Lemma to_val_fill_some K e v : to_val (fill K e) = Some v → K = [] ∧ e = Val v.
-Proof.
-  intro H. destruct K as [|Ki K]; first by apply of_to_val in H. exfalso.
-  assert (to_val e ≠ None) as He.
-  { intro A. by rewrite fill_not_val in H. }
-  assert (∃ w, e = Val w) as [w ->].
-  { destruct e; try done; eauto. }
-  assert (to_val (fill (Ki :: K) (Val w)) = None).
-  { destruct Ki; simpl; apply fill_not_val; done. }
-  by simplify_eq.
-Qed.
-
-Lemma to_val_fill_none e K: to_val e = None → to_val (fill K e) = None.
-Proof.
-  intros H; destruct (to_val (fill K e)) eqn: Hval; auto.
-  apply to_val_fill_some in Hval as [_ ->]. discriminate.
-Qed.
-
-Lemma prim_step_to_val_is_head_step e σ1 κs w σ2 efs :
-  prim_step e σ1 κs (Val w) σ2 efs → head_step e σ1 κs (Val w) σ2 efs.
-Proof.
-  intro H. destruct H as [K e1 e2 H1 H2].
-  assert (to_val (fill K e2) = Some w) as H3; first by rewrite -H2.
-  apply to_val_fill_some in H3 as [-> ->]. subst e. done.
-Qed.
-
-Lemma irreducible_resolve e v1 v2 σ :
-  irreducible e σ → irreducible (Resolve e (Val v1) (Val v2)) σ.
-Proof.
-  intros H κs ** [Ks e1' e2' Hfill -> step]. simpl in *.
-  induction Ks as [|K Ks _] using rev_ind; simpl in Hfill.
-  - subst e1'. inversion step. eapply H. by apply head_prim_step.
-  - rewrite fill_app /= in Hfill.
-    destruct K; (inversion Hfill; subst; clear Hfill; try
-      match goal with | H : Val ?v = fill Ks ?e |- _ =>
-        (assert (to_val (fill Ks e) = Some v) as HEq by rewrite -H //);
-        apply to_val_fill_some in HEq; destruct HEq as [-> ->]; inversion step
-      end).
-    apply (H κs (fill_item K (foldl (flip fill_item) e2' Ks)) σ' efs).
-    econstructor 1 with (K := Ks ++ [K]); last done; simpl; by rewrite fill_app.
-Qed.
diff --git a/theories/heap_lang/lifting.v b/theories/heap_lang/lifting.v
deleted file mode 100644
index 40d499bbe9764fa688d7a797445a864f20ea4b7c..0000000000000000000000000000000000000000
--- a/theories/heap_lang/lifting.v
+++ /dev/null
@@ -1,1349 +0,0 @@
-From iris.algebra Require Import auth gmap.
-From iris.base_logic Require Export gen_heap.
-From iris.base_logic.lib Require Export proph_map.
-From iris.program_logic Require Export weakestpre.
-From iris.program_logic Require Import ectx_lifting.
-From iris.program_logic.refinement Require Export ref_weakestpre.
-From iris.program_logic.refinement Require Import ref_ectx_lifting.
-From iris.heap_lang Require Export lang.
-From iris.heap_lang Require Import tactics notation.
-From iris.proofmode Require Import tactics.
-From stdpp Require Import fin_maps.
-Set Default Proof Using "Type".
-
-
-Class heapPreG {SI} (Σ: gFunctors SI) := HeapPreG {
-  heap_preG_inv :> invPreG Σ;
-  heap_preG_heap :> gen_heapPreG loc val Σ;
-  heap_preG_proph :> proph_mapPreG proph_id (val * val) Σ
-}.
-
-
-Class heapG {SI} (Σ: gFunctors SI) := HeapG {
-  heapG_invG : invG Σ;
-  heapG_gen_heapG :> gen_heapG loc val Σ;
-  heapG_proph_mapG :> proph_mapG proph_id (val * val) Σ
-}.
-
-Instance heapG_irisG {SI} {Σ: gFunctors SI} `{!heapG Σ} : irisG heap_lang Σ := {
-  iris_invG := heapG_invG;
-  state_interp σ κs _ :=
-    (gen_heap_ctx σ.(heap) ∗ proph_map_ctx κs σ.(used_proph_id))%I;
-  fork_post _ := True%I;
-}.
-
-Instance heapG_ref_irisG {SI} {Σ: gFunctors SI} `{!heapG Σ} : ref_irisG heap_lang Σ := {
-  ref_state_interp σ _ := (gen_heap_ctx σ.(heap))%I;
-  ref_fork_post _ := True%I;
-}.
-
-(** Override the notations so that scopes and coercions work out *)
-Notation "l ↦{ q } v" := (mapsto (L:=loc) (V:=val) l q v%V)
-  (at level 20, q at level 50, format "l  ↦{ q }  v") : bi_scope.
-Notation "l ↦ v" :=
-  (mapsto (L:=loc) (V:=val) l 1 v%V) (at level 20) : bi_scope.
-Notation "l ↦{ q } -" := (∃ v, l ↦{q} v)%I
-  (at level 20, q at level 50, format "l  ↦{ q }  -") : bi_scope.
-Notation "l ↦ -" := (l ↦{1} -)%I (at level 20) : bi_scope.
-
-Definition array {SI} {Σ: gFunctors SI} `{!heapG Σ} (l : loc) (vs : list val) : iProp Σ :=
-  ([∗ list] i ↦ v ∈ vs, (l +ₗ i) ↦ v)%I.
-Notation "l ↦∗ vs" := (array l vs)
-  (at level 20, format "l  ↦∗  vs") : bi_scope.
-
-(** The tactic [inv_head_step] performs inversion on hypotheses of the shape
-[head_step]. The tactic will discharge head-reductions starting from values, and
-simplifies hypothesis related to conversions from and to values, and finite map
-operations. This tactic is slightly ad-hoc and tuned for proving our lifting
-lemmas. *)
-Ltac inv_head_step :=
-  repeat match goal with
-  | _ => progress simplify_map_eq/= (* simplify memory stuff *)
-  | H : to_val _ = Some _ |- _ => apply of_to_val in H
-  | H : head_step ?e _ _ _ _ _ |- _ =>
-     try (is_var e; fail 1); (* inversion yields many goals if [e] is a variable
-     and can thus better be avoided. *)
-     inversion H; subst; clear H
-  end.
-
-Local Hint Extern 0 (head_reducible _ _) => eexists _, _, _, _; simpl : core.
-Local Hint Extern 0 (head_reducible_no_obs _ _) => eexists _, _, _; simpl : core.
-
-(* [simpl apply] is too stupid, so we need extern hints here. *)
-Local Hint Extern 1 (head_step _ _ _ _ _ _) => econstructor : core.
-Local Hint Extern 0 (head_step (CmpXchg _ _ _) _ _ _ _ _) => eapply CmpXchgS : core.
-Local Hint Extern 0 (head_step (AllocN _ _) _ _ _ _ _) => apply alloc_fresh : core.
-Local Hint Extern 0 (head_step NewProph _ _ _ _ _) => apply new_proph_id_fresh : core.
-Local Hint Resolve to_of_val : core.
-
-Instance into_val_val v : IntoVal (Val v) v.
-Proof. done. Qed.
-Instance as_val_val v : AsVal (Val v).
-Proof. by eexists. Qed.
-
-Local Ltac solve_atomic :=
-  apply strongly_atomic_atomic, ectx_language_atomic;
-    [inversion 1; naive_solver
-    |apply ectxi_language_sub_redexes_are_values; intros [] **; naive_solver].
-
-Instance alloc_atomic s v w : Atomic s (AllocN (Val v) (Val w)).
-Proof. solve_atomic. Qed.
-Instance load_atomic s v : Atomic s (Load (Val v)).
-Proof. solve_atomic. Qed.
-Instance store_atomic s v1 v2 : Atomic s (Store (Val v1) (Val v2)).
-Proof. solve_atomic. Qed.
-Instance cmpxchg_atomic s v0 v1 v2 : Atomic s (CmpXchg (Val v0) (Val v1) (Val v2)).
-Proof. solve_atomic. Qed.
-Instance faa_atomic s v1 v2 : Atomic s (FAA (Val v1) (Val v2)).
-Proof. solve_atomic. Qed.
-Instance fork_atomic s e : Atomic s (Fork e).
-Proof. solve_atomic. Qed.
-Instance skip_atomic s  : Atomic s Skip.
-Proof. solve_atomic. Qed.
-Instance new_proph_atomic s : Atomic s NewProph.
-Proof. solve_atomic. Qed.
-Instance binop_atomic s op v1 v2 : Atomic s (BinOp op (Val v1) (Val v2)).
-Proof. solve_atomic. Qed.
-
-Instance proph_resolve_atomic s e v1 v2 :
-  Atomic s e → Atomic s (Resolve e (Val v1) (Val v2)).
-Proof.
-  rename e into e1. intros H σ1 e2 κ σ2 efs [Ks e1' e2' Hfill -> step].
-  simpl in *. induction Ks as [|K Ks _] using rev_ind; simpl in Hfill.
-  - subst. inversion_clear step. by apply (H σ1 (Val v) κs σ2 efs), head_prim_step.
-  - rewrite fill_app. rewrite fill_app in Hfill.
-    assert (∀ v, Val v = fill Ks e1' → False) as fill_absurd.
-    { intros v Hv. assert (to_val (fill Ks e1') = Some v) as Htv by by rewrite -Hv.
-      apply to_val_fill_some in Htv. destruct Htv as [-> ->]. inversion step. }
-    destruct K; (inversion Hfill; clear Hfill; subst; try
-      match goal with | H : Val ?v = fill Ks e1' |- _ => by apply fill_absurd in H end).
-    refine (_ (H σ1 (fill (Ks ++ [K]) e2') _ σ2 efs _)).
-    + destruct s; intro Hs; simpl in *.
-      * destruct Hs as [v Hs]. apply to_val_fill_some in Hs. by destruct Hs, Ks.
-      * apply irreducible_resolve. by rewrite fill_app in Hs.
-    + econstructor 1 with (K := Ks ++ [K]); try done. simpl. by rewrite fill_app.
-Qed.
-
-Instance resolve_proph_atomic s v1 v2 : Atomic s (ResolveProph (Val v1) (Val v2)).
-Proof. by apply proph_resolve_atomic, skip_atomic. Qed.
-
-Local Ltac solve_exec_safe := intros; subst; do 3 eexists; econstructor; eauto.
-Local Ltac solve_exec_puredet := simpl; intros; by inv_head_step.
-Local Ltac solve_pure_exec :=
-  subst; intros ?; apply nsteps_once, pure_head_step_pure_step;
-    constructor; [solve_exec_safe | solve_exec_puredet].
-
-(** The behavior of the various [wp_] tactics with regard to lambda differs in
-the following way:
-
-- [wp_pures] does *not* reduce lambdas/recs that are hidden behind a definition.
-- [wp_rec] and [wp_lam] reduce lambdas/recs that are hidden behind a definition.
-
-To realize this behavior, we define the class [AsRecV v f x erec], which takes a
-value [v] as its input, and turns it into a [RecV f x erec] via the instance
-[AsRecV_recv : AsRecV (RecV f x e) f x e]. We register this instance via
-[Hint Extern] so that it is only used if [v] is syntactically a lambda/rec, and
-not if [v] contains a lambda/rec that is hidden behind a definition.
-
-To make sure that [wp_rec] and [wp_lam] do reduce lambdas/recs that are hidden
-behind a definition, we activate [AsRecV_recv] by hand in these tactics. *)
-Class AsRecV (v : val) (f x : binder) (erec : expr) :=
-  as_recv : v = RecV f x erec.
-Hint Mode AsRecV ! - - - : typeclass_instances.
-Definition AsRecV_recv f x e : AsRecV (RecV f x e) f x e := eq_refl.
-Hint Extern 0 (AsRecV (RecV _ _ _) _ _ _) =>
-  apply AsRecV_recv : typeclass_instances.
-
-Instance pure_recc f x (erec : expr) :
-  PureExec True 1 (Rec f x erec) (Val $ RecV f x erec).
-Proof. solve_pure_exec. Qed.
-Instance pure_pairc (v1 v2 : val) :
-  PureExec True 1 (Pair (Val v1) (Val v2)) (Val $ PairV v1 v2).
-Proof. solve_pure_exec. Qed.
-Instance pure_injlc (v : val) :
-  PureExec True 1 (InjL $ Val v) (Val $ InjLV v).
-Proof. solve_pure_exec. Qed.
-Instance pure_injrc (v : val) :
-  PureExec True 1 (InjR $ Val v) (Val $ InjRV v).
-Proof. solve_pure_exec. Qed.
-
-Instance pure_beta f x (erec : expr) (v1 v2 : val) `{!AsRecV v1 f x erec} :
-  PureExec True 1 (App (Val v1) (Val v2)) (subst' x v2 (subst' f v1 erec)).
-Proof. unfold AsRecV in *. solve_pure_exec. Qed.
-
-Instance pure_unop op v v' :
-  PureExec (un_op_eval op v = Some v') 1 (UnOp op (Val v)) (Val v').
-Proof. solve_pure_exec. Qed.
-
-Instance pure_binop op v1 v2 v' :
-  PureExec (bin_op_eval op v1 v2 = Some v') 1 (BinOp op (Val v1) (Val v2)) (Val v') | 10.
-Proof. solve_pure_exec. Qed.
-(* Higher-priority instance for EqOp. *)
-Instance pure_eqop v1 v2 :
-  PureExec (vals_compare_safe v1 v2) 1
-    (BinOp EqOp (Val v1) (Val v2))
-    (Val $ LitV $ LitBool $ bool_decide (v1 = v2)) | 1.
-Proof.
-  intros Hcompare.
-  cut (bin_op_eval EqOp v1 v2 = Some $ LitV $ LitBool $ bool_decide (v1 = v2)).
-  { intros. revert Hcompare. solve_pure_exec. }
-  rewrite /bin_op_eval /= decide_True //.
-Qed.
-
-Instance pure_if_true e1 e2 : PureExec True 1 (If (Val $ LitV $ LitBool true) e1 e2) e1.
-Proof. solve_pure_exec. Qed.
-
-Instance pure_if_false e1 e2 : PureExec True 1 (If (Val $ LitV  $ LitBool false) e1 e2) e2.
-Proof. solve_pure_exec. Qed.
-
-Instance pure_fst v1 v2 :
-  PureExec True 1 (Fst (Val $ PairV v1 v2)) (Val v1).
-Proof. solve_pure_exec. Qed.
-
-Instance pure_snd v1 v2 :
-  PureExec True 1 (Snd (Val $ PairV v1 v2)) (Val v2).
-Proof. solve_pure_exec. Qed.
-
-Instance pure_case_inl v e1 e2 :
-  PureExec True 1 (Case (Val $ InjLV v) e1 e2) (App e1 (Val v)).
-Proof. solve_pure_exec. Qed.
-
-Instance pure_case_inr v e1 e2 :
-  PureExec True 1 (Case (Val $ InjRV v) e1 e2) (App e2 (Val v)).
-Proof. solve_pure_exec. Qed.
-
-Section lifting.
-Context {SI} {Σ: gFunctors SI} `{!heapG Σ}.
-Implicit Types P Q : iProp Σ.
-Implicit Types Φ : val → iProp Σ.
-Implicit Types efs : list expr.
-Implicit Types σ : state.
-Implicit Types v : val.
-Implicit Types vs : list val.
-Implicit Types l : loc.
-Implicit Types sz off : nat.
-
-(** Fork: Not using Texan triples to avoid some unnecessary [True] *)
-Lemma wp_fork s E e Φ :
-  ▷ WP e @ s; ⊤ {{ _, True }} -∗ ▷ Φ (LitV LitUnit) -∗ WP Fork e @ s; E {{ Φ }}.
-Proof.
-  iIntros "He HΦ". iApply wp_lift_atomic_head_step; [done|].
-  iIntros (σ1 κ κs n) "Hσ !>"; iSplit; first by eauto.
-  iNext; iIntros (v2 σ2 efs Hstep); inv_head_step. by iFrame.
-Qed.
-Lemma swp_fork k s E e Φ :
-  ▷ WP e @ s; ⊤ {{ _, True }} -∗ ▷ Φ (LitV LitUnit) -∗ SWP Fork e at k @ s; E {{ Φ }}.
-Proof.
-  iIntros "He HΦ". iApply swp_lift_atomic_head_step.
-  iIntros (σ1 κ κs n) "Hσ !>"; iSplit; first by eauto.
-  iNext; iIntros (v2 σ2 efs Hstep); inv_head_step. by iFrame.
-Qed.
-(*
-Lemma twp_fork s E e Φ :
-  WP e @ s; ⊤ [{ _, True }] -∗ Φ (LitV LitUnit) -∗ WP Fork e @ s; E [{ Φ }].
-Proof.
-  iIntros "He HΦ". iApply twp_lift_atomic_head_step; [done|].
-  iIntros (σ1 κs n) "Hσ !>"; iSplit; first by eauto.
-  iIntros (κ v2 σ2 efs Hstep); inv_head_step. by iFrame.
-Qed.
- *)
-
-Lemma array_nil l : l ↦∗ [] ⊣⊢ emp.
-Proof. by rewrite /array. Qed.
-
-Lemma array_singleton l v : l ↦∗ [v] ⊣⊢ l ↦ v.
-Proof. by rewrite /array /= right_id loc_add_0. Qed.
-
-Lemma array_app l vs ws :
-  l ↦∗ (vs ++ ws) ⊣⊢ l ↦∗ vs ∗ (l +ₗ length vs) ↦∗ ws.
-Proof.
-  rewrite /array big_sepL_app.
-  setoid_rewrite Nat2Z.inj_add.
-  by setoid_rewrite loc_add_assoc.
-Qed.
-
-Lemma array_cons l v vs : l ↦∗ (v :: vs) ⊣⊢ l ↦ v ∗ (l +ₗ 1) ↦∗ vs.
-Proof.
-  rewrite /array big_sepL_cons loc_add_0.
-  setoid_rewrite loc_add_assoc.
-  setoid_rewrite Nat2Z.inj_succ.
-  by setoid_rewrite Z.add_1_l.
-Qed.
-
-Lemma heap_array_to_array l vs :
-  ([∗ map] l' ↦ v ∈ heap_array l vs, l' ↦ v) -∗ l ↦∗ vs.
-Proof.
-  iIntros "Hvs". iInduction vs as [|v vs] "IH" forall (l); simpl.
-  { by rewrite /array. }
-  rewrite big_opM_union; last first.
-  { apply map_disjoint_spec=> l' v1 v2 /lookup_singleton_Some [-> _].
-    intros (j&?&Hjl&_)%heap_array_lookup.
-    rewrite loc_add_assoc -{1}[l']loc_add_0 in Hjl. simplify_eq; lia. }
-  rewrite array_cons.
-  rewrite big_opM_singleton; iDestruct "Hvs" as "[$ Hvs]".
-  by iApply "IH".
-Qed.
-
-Lemma heap_array_to_seq_meta l vs n :
-  length vs = n →
-  ([∗ map] l' ↦ _ ∈ heap_array l vs, meta_token l' ⊤) -∗
-  [∗ list] i ∈ seq 0 n, meta_token (l +ₗ (i : nat)) ⊤.
-Proof.
-  iIntros (<-) "Hvs". iInduction vs as [|v vs] "IH" forall (l)=> //=.
-  rewrite big_opM_union; last first.
-  { apply map_disjoint_spec=> l' v1 v2 /lookup_singleton_Some [-> _].
-    intros (j&?&Hjl&_)%heap_array_lookup.
-    rewrite loc_add_assoc -{1}[l']loc_add_0 in Hjl. simplify_eq; lia. }
-  rewrite loc_add_0 -fmap_S_seq big_sepL_fmap.
-  setoid_rewrite Nat2Z.inj_succ. setoid_rewrite <-Z.add_1_l.
-  setoid_rewrite <-loc_add_assoc.
-  rewrite big_opM_singleton; iDestruct "Hvs" as "[$ Hvs]". by iApply "IH".
-Qed.
-
-Lemma update_array l vs off v :
-  vs !! off = Some v →
-  sbi_emp_valid (l ↦∗ vs -∗ ((l +ₗ off) ↦ v ∗ ∀ v', (l +ₗ off) ↦ v' -∗ l ↦∗ <[off:=v']>vs))%I.
-Proof.
-  iIntros (Hlookup) "Hl".
-  rewrite -[X in (l ↦∗ X)%I](take_drop_middle _ off v); last done.
-  iDestruct (array_app with "Hl") as "[Hl1 Hl]".
-  iDestruct (array_cons with "Hl") as "[Hl2 Hl3]".
-  assert (off < length vs)%nat as H by (apply lookup_lt_is_Some; by eexists).
-  rewrite take_length min_l; last by lia. iFrame "Hl2".
-  iIntros (w) "Hl2".
-  clear Hlookup. assert (<[off:=w]> vs !! off = Some w) as Hlookup.
-  { apply list_lookup_insert. lia. }
-  rewrite -[in (l ↦∗ <[off:=w]> vs)%I](take_drop_middle (<[off:=w]> vs) off w Hlookup).
-  iApply array_app. rewrite take_insert; last by lia. iFrame.
-  iApply array_cons. rewrite take_length min_l; last by lia. iFrame.
-  rewrite drop_insert; last by lia. done.
-Qed.
-
-(** Heap *)
-Lemma wp_allocN s E v n :
-  0 < n →
-  {{{ True }}} AllocN (Val $ LitV $ LitInt $ n) (Val v) @ s; E
-  {{{ l, RET LitV (LitLoc l); l ↦∗ replicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ }}}.
-Proof.
-  iIntros (Hn Φ) "_ HΦ". iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs k) "[Hσ Hκs] !>"; iSplit; first by auto with lia.
-  iNext; iIntros (v2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_alloc_gen with "Hσ") as "(Hσ & Hl & Hm)".
-  { apply (heap_array_map_disjoint _ l (replicate (Z.to_nat n) v)); eauto.
-    rewrite replicate_length Z2Nat.id; auto with lia. }
-  iModIntro; iSplit; first done. iFrame "Hσ Hκs". iApply "HΦ". iSplitL "Hl".
-  - by iApply heap_array_to_array.
-  - iApply (heap_array_to_seq_meta with "Hm"). by rewrite replicate_length.
-Qed.
-Lemma swp_allocN k s E v n :
-  0 < n →
-  {{{ True }}} AllocN (Val $ LitV $ LitInt $ n) (Val v) at k @ s; E
-  {{{ l, RET LitV (LitLoc l); l ↦∗ replicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ }}}.
-Proof.
-  iIntros (Hn Φ) "_ HΦ". iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs k') "[Hσ Hκs] !>"; iSplit; first by auto with lia.
-  iNext; iIntros (v2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_alloc_gen with "Hσ") as "(Hσ & Hl & Hm)".
-  { apply (heap_array_map_disjoint _ l (replicate (Z.to_nat n) v)); eauto.
-    rewrite replicate_length Z2Nat.id; auto with lia. }
-  iModIntro; iSplit; first done. iFrame "Hσ Hκs". iApply "HΦ". iSplitL "Hl".
-  - by iApply heap_array_to_array.
-  - iApply (heap_array_to_seq_meta with "Hm"). by rewrite replicate_length.
-Qed.
-
-(*Lemma twp_allocN s E v n :
-  0 < n →
-  [[{ True }]] AllocN (Val $ LitV $ LitInt $ n) (Val v) @ s; E
-  [[{ l, RET LitV (LitLoc l); l ↦∗ replicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ }]].
-Proof.
-  iIntros (Hn Φ) "_ HΦ". iApply twp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κs k) "[Hσ Hκs] !>"; iSplit; first by destruct n; auto with lia.
-  iIntros (κ v2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_alloc_gen with "Hσ") as "(Hσ & Hl & Hm)".
-  { apply (heap_array_map_disjoint _ l (replicate (Z.to_nat n) v)); eauto.
-    rewrite replicate_length Z2Nat.id; auto with lia. }
-  iModIntro; do 2 (iSplit; first done). iFrame "Hσ Hκs". iApply "HΦ". iSplitL "Hl".
-  - by iApply heap_array_to_array.
-  - iApply (heap_array_to_seq_meta with "Hm"). by rewrite replicate_length.
-Qed.*)
-
-Lemma wp_alloc s E v :
-  {{{ True }}} Alloc (Val v) @ s; E {{{ l, RET LitV (LitLoc l); l ↦ v ∗ meta_token l ⊤ }}}.
-Proof.
-  iIntros (Φ) "_ HΦ". iApply wp_allocN; auto with lia.
-  iIntros "!>" (l) "/= (? & ? & _)".
-  rewrite array_singleton loc_add_0. iApply "HΦ"; iFrame.
-Qed.
-Lemma swp_alloc k s E v :
-  {{{ True }}} Alloc (Val v) at k @ s; E {{{ l, RET LitV (LitLoc l); l ↦ v ∗ meta_token l ⊤ }}}.
-Proof.
-  iIntros (Φ) "_ HΦ". iApply swp_allocN; auto with lia.
-  iIntros "!>" (l) "/= (? & ? & _)".
-  rewrite array_singleton loc_add_0. iApply "HΦ"; iFrame.
-Qed.
-
-(*Lemma twp_alloc s E v :
-  [[{ True }]] Alloc (Val v) @ s; E [[{ l, RET LitV (LitLoc l); l ↦ v ∗ meta_token l ⊤ }]].
-Proof.
-  iIntros (Φ) "_ HΦ". iApply twp_allocN; auto with lia.
-  iIntros (l) "/= (? & ? & _)".
-  rewrite array_singleton loc_add_0. iApply "HΦ"; iFrame.
-Qed.*)
-
-Lemma wp_load s E l q v :
-  {{{ ▷ l ↦{q} v }}} Load (Val $ LitV $ LitLoc l) @ s; E {{{ RET v; l ↦{q} v }}}.
-Proof.
-  iIntros (Φ) ">Hl HΦ". iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2 σ2 efs Hstep); inv_head_step.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-Lemma swp_load k s E l q v :
-  {{{ ▷ l ↦{q} v }}} Load (Val $ LitV $ LitLoc l) at k @ s; E {{{ RET v; l ↦{q} v }}}.
-Proof.
-  iIntros (Φ) ">Hl HΦ". iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2 σ2 efs Hstep); inv_head_step.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-
-(*Lemma twp_load s E l q v :
-  [[{ l ↦{q} v }]] Load (Val $ LitV $ LitLoc l) @ s; E [[{ RET v; l ↦{q} v }]].
-Proof.
-  iIntros (Φ) "Hl HΦ". iApply twp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iIntros (κ v2 σ2 efs Hstep); inv_head_step.
-  iModIntro; iSplit=> //. iSplit; first done. iFrame. by iApply "HΦ".
-Qed.*)
-
-Lemma wp_store s E l v' v :
-  {{{ ▷ l ↦ v' }}} Store (Val $ LitV (LitLoc l)) (Val v) @ s; E
-  {{{ RET LitV LitUnit; l ↦ v }}}.
-Proof.
-  iIntros (Φ) ">Hl HΦ".
-  iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-Lemma swp_store k s E l v' v :
-  {{{ ▷ l ↦ v' }}} Store (Val $ LitV (LitLoc l)) (Val v) at k @ s; E
-  {{{ RET LitV LitUnit; l ↦ v }}}.
-Proof.
-  iIntros (Φ) ">Hl HΦ".
-  iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-
-(*Lemma twp_store s E l v' v :
-  [[{ l ↦ v' }]] Store (Val $ LitV $ LitLoc l) (Val v) @ s; E
-  [[{ RET LitV LitUnit; l ↦ v }]].
-Proof.
-  iIntros (Φ) "Hl HΦ".
-  iApply twp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iIntros (κ v2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iSplit; first done. iFrame. by iApply "HΦ".
-Qed.*)
-
-Lemma wp_cmpxchg_fail s E l q v' v1 v2 :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  {{{ ▷ l ↦{q} v' }}} CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) @ s; E
-  {{{ RET PairV v' (LitV $ LitBool false); l ↦{q} v' }}}.
-Proof.
-  iIntros (?? Φ) ">Hl HΦ". iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs Hstep); inv_head_step.
-  rewrite bool_decide_false //.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-Lemma swp_cmpxchg_fail k s E l q v' v1 v2 :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  {{{ ▷ l ↦{q} v' }}} CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) at k @ s; E
-  {{{ RET PairV v' (LitV $ LitBool false); l ↦{q} v' }}}.
-Proof.
-  iIntros (?? Φ) ">Hl HΦ". iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs Hstep); inv_head_step.
-  rewrite bool_decide_false //.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-(*Lemma twp_cmpxchg_fail s E l q v' v1 v2 :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  [[{ l ↦{q} v' }]] CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) @ s; E
-  [[{ RET PairV v' (LitV $ LitBool false); l ↦{q} v' }]].
-Proof.
-  iIntros (?? Φ) "Hl HΦ". iApply twp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iIntros (κ v2' σ2 efs Hstep); inv_head_step.
-  rewrite bool_decide_false //.
-  iModIntro; iSplit=> //. iSplit; first done. iFrame. by iApply "HΦ".
-Qed.*)
-
-Lemma wp_cmpxchg_suc s E l v1 v2 v' :
-  v' = v1 → vals_compare_safe v' v1 →
-  {{{ ▷ l ↦ v' }}} CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) @ s; E
-  {{{ RET PairV v' (LitV $ LitBool true); l ↦ v2 }}}.
-Proof.
-  iIntros (?? Φ) ">Hl HΦ". iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs Hstep); inv_head_step.
-  rewrite bool_decide_true //.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-Lemma swp_cmpxchg_suc k s E l v1 v2 v' :
-  v' = v1 → vals_compare_safe v' v1 →
-  {{{ ▷ l ↦ v' }}} CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) at k @ s; E
-  {{{ RET PairV v' (LitV $ LitBool true); l ↦ v2 }}}.
-Proof.
-  iIntros (?? Φ) ">Hl HΦ". iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs Hstep); inv_head_step.
-  rewrite bool_decide_true //.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-(*Lemma twp_cmpxchg_suc s E l v1 v2 v' :
-  v' = v1 → vals_compare_safe v' v1 →
-  [[{ l ↦ v' }]] CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) @ s; E
-  [[{ RET PairV v' (LitV $ LitBool true); l ↦ v2 }]].
-Proof.
-  iIntros (?? Φ) "Hl HΦ". iApply twp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iIntros (κ v2' σ2 efs Hstep); inv_head_step.
-  rewrite bool_decide_true //.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iSplit; first done. iFrame. by iApply "HΦ".
-Qed.*)
-
-Lemma wp_faa s E l i1 i2 :
-  {{{ ▷ l ↦ LitV (LitInt i1) }}} FAA (Val $ LitV $ LitLoc l) (Val $ LitV $ LitInt i2) @ s; E
-  {{{ RET LitV (LitInt i1); l ↦ LitV (LitInt (i1 + i2)) }}}.
-Proof.
-  iIntros (Φ) ">Hl HΦ". iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-Lemma swp_faa k s E l i1 i2 :
-  {{{ ▷ l ↦ LitV (LitInt i1) }}} FAA (Val $ LitV $ LitLoc l) (Val $ LitV $ LitInt i2) at k @ s; E
-  {{{ RET LitV (LitInt i1); l ↦ LitV (LitInt (i1 + i2)) }}}.
-Proof.
-  iIntros (Φ) ">Hl HΦ". iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-(*Lemma twp_faa s E l i1 i2 :
-  [[{ l ↦ LitV (LitInt i1) }]] FAA (Val $ LitV $ LitLoc l) (Val $ LitV $ LitInt i2) @ s; E
-  [[{ RET LitV (LitInt i1); l ↦ LitV (LitInt (i1 + i2)) }]].
-Proof.
-  iIntros (Φ) "Hl HΦ". iApply twp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κs n) "[Hσ Hκs] !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iIntros (κ e2 σ2 efs Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iSplit; first done. iFrame. by iApply "HΦ".
-Qed.*)
-
-Lemma wp_new_proph s E :
-  {{{ True }}}
-    NewProph @ s; E
-  {{{ pvs p, RET (LitV (LitProphecy p)); proph p pvs }}}.
-Proof.
-  iIntros (Φ) "_ HΦ". iApply wp_lift_atomic_head_step_no_fork; auto.
-  iIntros (σ1 κ κs n) "[Hσ HR] !>". iSplit; first by eauto.
-  iNext; iIntros (v2 σ2 efs Hstep). inv_head_step.
-  iMod (proph_map_new_proph p with "HR") as "[HR Hp]"; first done.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-Lemma swp_new_proph k s E :
-  {{{ True }}}
-    NewProph at k @ s; E
-  {{{ pvs p, RET (LitV (LitProphecy p)); proph p pvs }}}.
-Proof.
-  iIntros (Φ) "_ HΦ". iApply swp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 κ κs n) "[Hσ HR] !>". iSplit; first by eauto.
-  iNext; iIntros (v2 σ2 efs Hstep). inv_head_step.
-  iMod (proph_map_new_proph p with "HR") as "[HR Hp]"; first done.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-
-(* In the following, strong atomicity is required due to the fact that [e] must
-be able to make a head step for [Resolve e _ _] not to be (head) stuck. *)
-
-Lemma resolve_reducible e σ (p : proph_id) v :
-  Atomic StronglyAtomic e → reducible e σ →
-  reducible (Resolve e (Val (LitV (LitProphecy p))) (Val v)) σ.
-Proof.
-  intros A (κ & e' & σ' & efs & H).
-  exists (κ ++ [(p, (default v (to_val e'), v))]), e', σ', efs.
-  eapply Ectx_step with (K:=[]); try done.
-  assert (∃w, Val w = e') as [w <-].
-  { unfold Atomic in A. apply (A σ e' κ σ' efs) in H. unfold is_Some in H.
-    destruct H as [w H]. exists w. simpl in H. by apply (of_to_val _ _ H). }
-  simpl. constructor. by apply prim_step_to_val_is_head_step.
-Qed.
-
-Lemma step_resolve e vp vt σ1 κ e2 σ2 efs :
-  Atomic StronglyAtomic e →
-  prim_step (Resolve e (Val vp) (Val vt)) σ1 κ e2 σ2 efs →
-  head_step (Resolve e (Val vp) (Val vt)) σ1 κ e2 σ2 efs.
-Proof.
-  intros A [Ks e1' e2' Hfill -> step]. simpl in *.
-  induction Ks as [|K Ks _] using rev_ind.
-  + simpl in *. subst. inversion step. by constructor.
-  + rewrite fill_app /= in Hfill. destruct K; inversion Hfill; subst; clear Hfill.
-    - assert (fill_item K (fill Ks e1') = fill (Ks ++ [K]) e1') as Eq1;
-        first by rewrite fill_app.
-      assert (fill_item K (fill Ks e2') = fill (Ks ++ [K]) e2') as Eq2;
-        first by rewrite fill_app.
-      rewrite fill_app /=. rewrite Eq1 in A.
-      assert (is_Some (to_val (fill (Ks ++ [K]) e2'))) as H.
-      { apply (A σ1 _ κ σ2 efs). eapply Ectx_step with (K0 := Ks ++ [K]); done. }
-      destruct H as [v H]. apply to_val_fill_some in H. by destruct H, Ks.
-    - assert (to_val (fill Ks e1') = Some vp); first by rewrite -H1 //.
-      apply to_val_fill_some in H. destruct H as [-> ->]. inversion step.
-    - assert (to_val (fill Ks e1') = Some vt); first by rewrite -H2 //.
-      apply to_val_fill_some in H. destruct H as [-> ->]. inversion step.
-Qed.
-
-
-Arguments gstep : simpl never.
-Existing Instance elim_gstep.
-Lemma wp_resolve s E e Φ (p : proph_id) v (pvs : list (val * val)) :
-  Atomic StronglyAtomic e →
-  to_val e = None →
-  proph p pvs -∗
-  WP e @ s; E {{ r, ∀ pvs', ⌜pvs = (r, v)::pvs'⌝ -∗ proph p pvs' -∗ Φ r }} -∗
-  WP Resolve e (Val $ LitV $ LitProphecy p) (Val v) @ s; E {{ Φ }}.
-Proof.
-  (* TODO we should try to use a generic lifting lemma (and avoid [wp_unfold])
-     here, since this breaks the WP abstraction. *)
-  iIntros (A He) "Hp WPe". rewrite !wp_unfold /wp_pre /= He. simpl in *.
-  iIntros (σ1 κ κs n) "[Hσ Hκ]". destruct κ as [|[p' [w' v']] κ' _] using rev_ind.
-  - iMod ("WPe" $! σ1 [] κs n with "[$Hσ $Hκ]") as "[Hs WPe]".
-    iSplit.
-    { iDestruct "Hs" as "%". iPureIntro. destruct s; [ by apply resolve_reducible | done]. }
-    iIntros (e2 σ2 efs step). exfalso. apply step_resolve in step; last done.
-    inversion step. match goal with H: ?κs ++ [_] = [] |- _ => by destruct κs end.
-  - rewrite -app_assoc.
-    iMod ("WPe" $! σ1 _ _ n with "[$Hσ $Hκ]") as "[Hs WPe]".
-    iSplit.
-    { iDestruct "Hs" as %?. iPureIntro. destruct s; [ by apply resolve_reducible | done]. }
-    iIntros (e2 σ2 efs step). apply step_resolve in step; last done.
-    inversion step; simplify_list_eq.
-    iMod ("WPe" $! (Val w') σ2 efs with "[%]") as "WPe".
-    { by eexists [] _ _. }
-    iModIntro. iNext. iMod "WPe" as "[[$ Hκ] WPe]".
-    iMod (proph_map_resolve_proph p' (w',v') κs with "[$Hκ $Hp]") as (vs' ->) "[$ HPost]".
-    iModIntro. rewrite !wp_unfold /wp_pre /=. iDestruct "WPe" as "[HΦ $]".
-    iMod "HΦ". iModIntro. by iApply "HΦ".
-Qed.
-
-Arguments gstepN : simpl never.
-Existing Instance elim_gstepN.
-Lemma swp_resolve k s E e Φ (p : proph_id) v (pvs : list (val * val)) :
-  Atomic StronglyAtomic e →
-  proph p pvs -∗
-  SWP e at k @ s; E {{ r, ∀ pvs', ⌜pvs = (r, v)::pvs'⌝ -∗ proph p pvs' -∗ Φ r }} -∗
-  SWP Resolve e (Val $ LitV $ LitProphecy p) (Val v) at k @ s; E {{ Φ }}.
-Proof.
-  (* TODO we should try to use a generic lifting lemma (and avoid [wp_unfold])
-     here, since this breaks the WP abstraction. *)
-  iIntros (A) "Hp WPe". rewrite !swp_unfold /swp_def /=. simpl in *.
-  iIntros (σ1 κ κs n) "[Hσ Hκ]". destruct κ as [|[p' [w' v']] κ' _] using rev_ind.
-  - iMod ("WPe" $! σ1 [] κs n with "[$Hσ $Hκ]") as "[Hs WPe]". iSplit.
-    { iDestruct "Hs" as "%". iPureIntro. destruct s; [ by apply resolve_reducible | done]. }
-    iIntros (e2 σ2 efs step). exfalso. apply step_resolve in step; last done.
-    inversion step. match goal with H: ?κs ++ [_] = [] |- _ => by destruct κs end.
-  - rewrite -app_assoc.
-    iMod ("WPe" $! σ1 _ _ n with "[$Hσ $Hκ]") as "[Hs WPe]". iSplit.
-    { iDestruct "Hs" as %?. iPureIntro. destruct s; [ by apply resolve_reducible | done]. }
-    iIntros (e2 σ2 efs step). apply step_resolve in step; last done.
-    inversion step; simplify_list_eq.
-    iMod ("WPe" $! (Val w') σ2 efs with "[%]") as "WPe".
-    { by eexists [] _ _. }
-    iModIntro. iNext. iMod "WPe" as "[[$ Hκ] WPe]".
-    iMod (proph_map_resolve_proph p' (w',v') κs with "[$Hκ $Hp]") as (vs' ->) "[$ HPost]".
-    iModIntro. rewrite !wp_unfold /wp_pre /=. iDestruct "WPe" as "[HΦ $]".
-    iMod "HΦ". iModIntro. by iApply "HΦ".
-Qed.
-
-(** Lemmas for some particular expression inside the [Resolve]. *)
-Lemma wp_resolve_proph s E (p : proph_id) (pvs : list (val * val)) v :
-  {{{ proph p pvs }}}
-    ResolveProph (Val $ LitV $ LitProphecy p) (Val v) @ s; E
-  {{{ pvs', RET (LitV LitUnit); ⌜pvs = (LitV LitUnit, v)::pvs'⌝ ∗ proph p pvs' }}}.
-Proof.
-  iIntros (Φ) "Hp HΦ". iApply (wp_resolve with "Hp"); first done.
-  iApply wp_pure_step_later=> //=. iApply wp_value.
-  iIntros "!>" (vs') "HEq Hp". iApply "HΦ". iFrame.
-Qed.
-
-Lemma swp_resolve_proph k s E (p : proph_id) (pvs : list (val * val)) v :
-  {{{ proph p pvs }}}
-    ResolveProph (Val $ LitV $ LitProphecy p) (Val v) at k @ s; E
-  {{{ pvs', RET (LitV LitUnit); ⌜pvs = (LitV LitUnit, v)::pvs'⌝ ∗ proph p pvs' }}}.
-Proof.
-  iIntros (Φ) "Hp HΦ". iApply (swp_resolve with "Hp").
-  iApply swp_pure_step_later=> //=. iApply wp_value.
-  iIntros "!>" (vs') "HEq Hp". iApply "HΦ". iFrame.
-Qed.
-
-Lemma wp_resolve_cmpxchg_suc s E l (p : proph_id) (pvs : list (val * val)) v1 v2 v :
-  vals_compare_safe v1 v1 →
-  {{{ proph p pvs ∗ ▷ l ↦ v1 }}}
-    Resolve (CmpXchg #l v1 v2) #p v @ s; E
-  {{{ RET (v1, #true) ; ∃ pvs', ⌜pvs = ((v1, #true)%V, v)::pvs'⌝ ∗ proph p pvs' ∗ l ↦ v2 }}}.
-Proof.
-  iIntros (Hcmp Φ) "[Hp Hl] HΦ".
-  iApply (wp_resolve with "Hp"); first done.
-  assert (val_is_unboxed v1) as Hv1; first by destruct Hcmp.
-  iApply (wp_cmpxchg_suc with "Hl"); [done..|]. iIntros "!> Hl".
-  iIntros (pvs' ->) "Hp". iApply "HΦ". eauto with iFrame.
-Qed.
-
-Lemma swp_resolve_cmpxchg_suc k s E l (p : proph_id) (pvs : list (val * val)) v1 v2 v :
-  vals_compare_safe v1 v1 →
-  {{{ proph p pvs ∗ ▷ l ↦ v1 }}}
-    Resolve (CmpXchg #l v1 v2) #p v at k @ s; E
-  {{{ RET (v1, #true) ; ∃ pvs', ⌜pvs = ((v1, #true)%V, v)::pvs'⌝ ∗ proph p pvs' ∗ l ↦ v2 }}}.
-Proof.
-  iIntros (Hcmp Φ) "[Hp Hl] HΦ".
-  iApply (swp_resolve with "Hp").
-  assert (val_is_unboxed v1) as Hv1; first by destruct Hcmp.
-  iApply (swp_cmpxchg_suc with "Hl"); [done..|]. iIntros "!> Hl".
-  iIntros (pvs' ->) "Hp". iApply "HΦ". eauto with iFrame.
-Qed.
-
-Lemma wp_resolve_cmpxchg_fail s E l (p : proph_id) (pvs : list (val * val)) q v' v1 v2 v :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  {{{ proph p pvs ∗ ▷ l ↦{q} v' }}}
-    Resolve (CmpXchg #l v1 v2) #p v @ s; E
-  {{{ RET (v', #false) ; ∃ pvs', ⌜pvs = ((v', #false)%V, v)::pvs'⌝ ∗ proph p pvs' ∗ l ↦{q} v' }}}.
-Proof.
-  iIntros (NEq Hcmp Φ) "[Hp Hl] HΦ".
-  iApply (wp_resolve with "Hp"); first done.
-  iApply (wp_cmpxchg_fail with "Hl"); [done..|]. iIntros "!> Hl".
-  iIntros (pvs' ->) "Hp". iApply "HΦ". eauto with iFrame.
-Qed.
-
-Lemma swp_resolve_cmpxchg_fail k s E l (p : proph_id) (pvs : list (val * val)) q v' v1 v2 v :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  {{{ proph p pvs ∗ ▷ l ↦{q} v' }}}
-    Resolve (CmpXchg #l v1 v2) #p v at k @ s; E
-  {{{ RET (v', #false) ; ∃ pvs', ⌜pvs = ((v', #false)%V, v)::pvs'⌝ ∗ proph p pvs' ∗ l ↦{q} v' }}}.
-Proof.
-  iIntros (NEq Hcmp Φ) "[Hp Hl] HΦ".
-  iApply (swp_resolve with "Hp").
-  iApply (swp_cmpxchg_fail with "Hl"); [done..|]. iIntros "!> Hl".
-  iIntros (pvs' ->) "Hp". iApply "HΦ". eauto with iFrame.
-Qed.
-
-(** Array lemmas *)
-Lemma wp_allocN_vec s E v n :
-  0 < n →
-  {{{ True }}}
-    AllocN #n v @ s ; E
-  {{{ l, RET #l; l ↦∗ vreplicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ }}}.
-Proof.
-  iIntros (Hzs Φ) "_ HΦ". iApply wp_allocN; [ lia | done | .. ]. iNext.
-  iIntros (l) "[Hl Hm]". iApply "HΦ". rewrite vec_to_list_replicate. iFrame.
-Qed.
-
-Lemma swp_allocN_vec k s E v n :
-  0 < n →
-  {{{ True }}}
-    AllocN #n v at k @ s ; E
-  {{{ l, RET #l; l ↦∗ vreplicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ }}}.
-Proof.
-  iIntros (Hzs Φ) "_ HΦ". iApply swp_allocN; [ lia | done | .. ]. iNext.
-  iIntros (l) "[Hl Hm]". iApply "HΦ". rewrite vec_to_list_replicate. iFrame.
-Qed.
-
-Lemma wp_load_offset s E l off vs v :
-  vs !! off = Some v →
-  {{{ ▷ l ↦∗ vs }}} ! #(l +ₗ off) @ s; E {{{ RET v; l ↦∗ vs }}}.
-Proof.
-  iIntros (Hlookup Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (wp_load with "Hl1"). iIntros "!> Hl1". iApply "HΦ".
-  iDestruct ("Hl2" $! v) as "Hl2". rewrite list_insert_id; last done.
-  iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma swp_load_offset k s E l off vs v :
-  vs !! off = Some v →
-  {{{ ▷ l ↦∗ vs }}} ! #(l +ₗ off) at k @ s; E {{{ RET v; l ↦∗ vs }}}.
-Proof.
-  iIntros (Hlookup Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (swp_load with "Hl1"). iIntros "!> Hl1". iApply "HΦ".
-  iDestruct ("Hl2" $! v) as "Hl2". rewrite list_insert_id; last done.
-  iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma wp_load_offset_vec s E l sz (off : fin sz) (vs : vec val sz) :
-  {{{ ▷ l ↦∗ vs }}} ! #(l +ₗ off) @ s; E {{{ RET vs !!! off; l ↦∗ vs }}}.
-Proof. apply wp_load_offset. by apply vlookup_lookup. Qed.
-
-Lemma swp_load_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) :
-  {{{ ▷ l ↦∗ vs }}} ! #(l +ₗ off) at k @ s; E {{{ RET vs !!! off; l ↦∗ vs }}}.
-Proof. apply swp_load_offset. by apply vlookup_lookup. Qed.
-
-
-Lemma wp_store_offset s E l off vs v :
-  is_Some (vs !! off) →
-  {{{ ▷ l ↦∗ vs }}} #(l +ₗ off) <- v @ s; E {{{ RET #(); l ↦∗ <[off:=v]> vs }}}.
-Proof.
-  iIntros ([w Hlookup] Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (wp_store with "Hl1"). iNext. iIntros "Hl1".
-  iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-Lemma swp_store_offset k s E l off vs v :
-  is_Some (vs !! off) →
-  {{{ ▷ l ↦∗ vs }}} #(l +ₗ off) <- v at k @ s; E {{{ RET #(); l ↦∗ <[off:=v]> vs }}}.
-Proof.
-  iIntros ([w Hlookup] Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (swp_store with "Hl1"). iNext. iIntros "Hl1".
-  iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma wp_store_offset_vec s E l sz (off : fin sz) (vs : vec val sz) v :
-  {{{ ▷ l ↦∗ vs }}} #(l +ₗ off) <- v @ s; E {{{ RET #(); l ↦∗ vinsert off v vs }}}.
-Proof.
-  setoid_rewrite vec_to_list_insert. apply wp_store_offset.
-  eexists. by apply vlookup_lookup.
-Qed.
-Lemma swp_store_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) v :
-  {{{ ▷ l ↦∗ vs }}} #(l +ₗ off) <- v at k @ s; E {{{ RET #(); l ↦∗ vinsert off v vs }}}.
-Proof.
-  setoid_rewrite vec_to_list_insert. apply swp_store_offset.
-  eexists. by apply vlookup_lookup.
-Qed.
-
-
-Lemma wp_cmpxchg_suc_offset s E l off vs v' v1 v2 :
-  vs !! off = Some v' →
-  v' = v1 →
-  vals_compare_safe v' v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  {{{ RET (v', #true); l ↦∗ <[off:=v2]> vs }}}.
-Proof.
-  iIntros (Hlookup ?? Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (wp_cmpxchg_suc with "Hl1"); [done..|].
-  iNext. iIntros "Hl1". iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-Lemma swp_cmpxchg_suc_offset k s E l off vs v' v1 v2 :
-  vs !! off = Some v' →
-  v' = v1 →
-  vals_compare_safe v' v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  {{{ RET (v', #true); l ↦∗ <[off:=v2]> vs }}}.
-Proof.
-  iIntros (Hlookup ?? Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (swp_cmpxchg_suc with "Hl1"); [done..|].
-  iNext. iIntros "Hl1". iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma wp_cmpxchg_suc_offset_vec s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off = v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  {{{ RET (vs !!! off, #true); l ↦∗ vinsert off v2 vs }}}.
-Proof.
-  intros. setoid_rewrite vec_to_list_insert. eapply wp_cmpxchg_suc_offset=> //.
-  by apply vlookup_lookup.
-Qed.
-Lemma swp_cmpxchg_suc_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off = v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  {{{ RET (vs !!! off, #true); l ↦∗ vinsert off v2 vs }}}.
-Proof.
-  intros. setoid_rewrite vec_to_list_insert. eapply swp_cmpxchg_suc_offset=> //.
-  by apply vlookup_lookup.
-Qed.
-
-Lemma wp_cmpxchg_fail_offset s E l off vs v0 v1 v2 :
-  vs !! off = Some v0 →
-  v0 ≠ v1 →
-  vals_compare_safe v0 v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  {{{ RET (v0, #false); l ↦∗ vs }}}.
-Proof.
-  iIntros (Hlookup HNEq Hcmp Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (wp_cmpxchg_fail with "Hl1"); first done.
-  { destruct Hcmp; by [ left | right ]. }
-  iIntros "!> Hl1". iApply "HΦ". iDestruct ("Hl2" $! v0) as "Hl2".
-  rewrite list_insert_id; last done. iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma swp_cmpxchg_fail_offset k s E l off vs v0 v1 v2 :
-  vs !! off = Some v0 →
-  v0 ≠ v1 →
-  vals_compare_safe v0 v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  {{{ RET (v0, #false); l ↦∗ vs }}}.
-Proof.
-  iIntros (Hlookup HNEq Hcmp Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (swp_cmpxchg_fail with "Hl1"); first done.
-  { destruct Hcmp; by [ left | right ]. }
-  iIntros "!> Hl1". iApply "HΦ". iDestruct ("Hl2" $! v0) as "Hl2".
-  rewrite list_insert_id; last done. iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma wp_cmpxchg_fail_offset_vec s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off ≠ v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  {{{ RET (vs !!! off, #false); l ↦∗ vs }}}.
-Proof. intros. eapply wp_cmpxchg_fail_offset=> //. by apply vlookup_lookup. Qed.
-Lemma swp_cmpxchg_fail_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off ≠ v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  {{{ ▷ l ↦∗ vs }}}
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  {{{ RET (vs !!! off, #false); l ↦∗ vs }}}.
-Proof. intros. eapply swp_cmpxchg_fail_offset=> //. by apply vlookup_lookup. Qed.
-
-Lemma wp_faa_offset s E l off vs (i1 i2 : Z) :
-  vs !! off = Some #i1 →
-  {{{ ▷ l ↦∗ vs }}} FAA #(l +ₗ off) #i2 @ s; E
-  {{{ RET LitV (LitInt i1); l ↦∗ <[off:=#(i1 + i2)]> vs }}}.
-Proof.
-  iIntros (Hlookup Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (wp_faa with "Hl1").
-  iNext. iIntros "Hl1". iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-Lemma swp_faa_offset k s E l off vs (i1 i2 : Z) :
-  vs !! off = Some #i1 →
-  {{{ ▷ l ↦∗ vs }}} FAA #(l +ₗ off) #i2 at k @ s; E
-  {{{ RET LitV (LitInt i1); l ↦∗ <[off:=#(i1 + i2)]> vs }}}.
-Proof.
-  iIntros (Hlookup Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (swp_faa with "Hl1").
-  iNext. iIntros "Hl1". iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma wp_faa_offset_vec s E l sz (off : fin sz) (vs : vec val sz) (i1 i2 : Z) :
-  vs !!! off = #i1 →
-  {{{ ▷ l ↦∗ vs }}} FAA #(l +ₗ off) #i2 @ s; E
-  {{{ RET LitV (LitInt i1); l ↦∗ vinsert off #(i1 + i2) vs }}}.
-Proof.
-  intros. setoid_rewrite vec_to_list_insert. apply wp_faa_offset=> //.
-  by apply vlookup_lookup.
-Qed.
-Lemma swp_faa_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) (i1 i2 : Z) :
-  vs !!! off = #i1 →
-  {{{ ▷ l ↦∗ vs }}} FAA #(l +ₗ off) #i2 at k @ s; E
-  {{{ RET LitV (LitInt i1); l ↦∗ vinsert off #(i1 + i2) vs }}}.
-Proof.
-  intros. setoid_rewrite vec_to_list_insert. apply swp_faa_offset=> //.
-  by apply vlookup_lookup.
-Qed.
-
-End lifting.
-
-
-
-Section refinements.
-
-  Context {SI} {Σ: gFunctors SI} {A: Type} `{!source Σ A} `{!heapG Σ}.
-  Implicit Types P Q : iProp Σ.
-  Implicit Types Φ : val → iProp Σ.
-  Implicit Types efs : list expr.
-  Implicit Types σ : state.
-  Implicit Types v : val.
-  Implicit Types vs : list val.
-  Implicit Types l : loc.
-  Implicit Types sz off : nat.
-
-  (* TODO: Uniform approch to where the refinement *)
-  Existing Instance heapG_invG.
-
-(** Fork: Not using Texan triples to avoid some unnecessary [True] *)
-Lemma rswp_fork k s E e Φ :
-  RWP e @ s; ⊤ ⟨⟨ _, True ⟩⟩ -∗ Φ (LitV LitUnit) -∗ RSWP Fork e at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "He HΦ". iApply rswp_lift_atomic_head_step.
-  iIntros (σ1 n) "Hσ !>"; iSplit; first by eauto.
-  iNext; iIntros (v2 σ2 efs κ Hstep); inv_head_step. by iFrame.
-Qed.
-
-(** Heap *)
-Lemma rswp_allocN k s E v n :
-  0 < n →
-  ⟨⟨⟨ True ⟩⟩⟩ AllocN (Val $ LitV $ LitInt $ n) (Val v) at k @ s; E
-  ⟨⟨⟨ l, RET LitV (LitLoc l); l ↦∗ replicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ ⟩⟩⟩.
-Proof.
-  iIntros (Hn Φ) "_ HΦ". iApply rswp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 k') "Hσ !>"; iSplit; first by auto with lia.
-  iNext; iIntros (v2 σ2 efs κ Hstep); inv_head_step.
-  iMod (@gen_heap_alloc_gen with "Hσ") as "(Hσ & Hl & Hm)".
-  { apply (heap_array_map_disjoint _ l (replicate (Z.to_nat n) v)); eauto.
-    rewrite replicate_length Z2Nat.id; auto with lia. }
-  iModIntro; iSplit; first done. iFrame "Hσ". iApply "HΦ". iSplitL "Hl".
-  - by iApply heap_array_to_array.
-  - iApply (heap_array_to_seq_meta with "Hm"). by rewrite replicate_length.
-Qed.
-
-Lemma rswp_alloc k s E v :
-  ⟨⟨⟨ True ⟩⟩⟩ Alloc (Val v) at k @ s; E ⟨⟨⟨ l, RET LitV (LitLoc l); l ↦ v ∗ meta_token l ⊤ ⟩⟩⟩.
-Proof.
-  iIntros (Φ) "_ HΦ". iApply rswp_allocN; auto with lia.
-  iIntros "!>" (l) "/= (? & ? & _)".
-  rewrite array_singleton loc_add_0. iApply "HΦ"; iFrame.
-Qed.
-
-(* TODO: we can always get rid of the later if the goal is a WP anyway. Having it in the rule seems unnecessary.*)
-Lemma rswp_load k s E l q v :
-  ⟨⟨⟨ ▷ l ↦{q} v ⟩⟩⟩ Load (Val $ LitV $ LitLoc l) at k @ s; E ⟨⟨⟨ RET v; l ↦{q} v ⟩⟩⟩.
-Proof.
-  iIntros (Φ) ">Hl HΦ". iApply rswp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 n) "Hσ !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2 σ2 efs κ Hstep); inv_head_step.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-
-(* TODO: we can always get rid of the later if the goal is a WP anyway. Having it in the rule seems unnecessary.*)
-Lemma rswp_store k s E l v' v :
-  ⟨⟨⟨ ▷ l ↦ v' ⟩⟩⟩ Store (Val $ LitV (LitLoc l)) (Val v) at k @ s; E
-  ⟨⟨⟨ RET LitV LitUnit; l ↦ v ⟩⟩⟩.
-Proof.
-  iIntros (Φ) ">Hl HΦ".
-  iApply rswp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 n) "Hσ !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2 σ2 efs κ Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-
-Lemma rswp_cmpxchg_fail k s E l q v' v1 v2 :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  ⟨⟨⟨ ▷ l ↦{q} v' ⟩⟩⟩ CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) at k @ s; E
-  ⟨⟨⟨ RET PairV v' (LitV $ LitBool false); l ↦{q} v' ⟩⟩⟩.
-Proof.
-  iIntros (?? Φ) ">Hl HΦ". iApply rswp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 n) "Hσ !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs κ Hstep); inv_head_step.
-  rewrite bool_decide_false //.
-  iModIntro; iSplit=> //. iFrame. by iApply "HΦ".
-Qed.
-
-Lemma rswp_cmpxchg_suc k s E l v1 v2 v' :
-  v' = v1 → vals_compare_safe v' v1 →
-  ⟨⟨⟨ ▷ l ↦ v' ⟩⟩⟩ CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) at k @ s; E
-  ⟨⟨⟨ RET PairV v' (LitV $ LitBool true); l ↦ v2 ⟩⟩⟩.
-Proof.
-  iIntros (?? Φ) ">Hl HΦ". iApply rswp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 n) "Hσ !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs κ Hstep); inv_head_step.
-  rewrite bool_decide_true //.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-
-Lemma rswp_faa k s E l i1 i2 :
-  ⟨⟨⟨ ▷ l ↦ LitV (LitInt i1) ⟩⟩⟩ FAA (Val $ LitV $ LitLoc l) (Val $ LitV $ LitInt i2) at k @ s; E
-  ⟨⟨⟨ RET LitV (LitInt i1); l ↦ LitV (LitInt (i1 + i2)) ⟩⟩⟩.
-Proof.
-  iIntros (Φ) ">Hl HΦ". iApply rswp_lift_atomic_head_step_no_fork.
-  iIntros (σ1 n) "Hσ !>". iDestruct (@gen_heap_valid with "Hσ Hl") as %?.
-  iSplit; first by eauto. iNext; iIntros (v2' σ2 efs κ Hstep); inv_head_step.
-  iMod (@gen_heap_update with "Hσ Hl") as "[$ Hl]".
-  iModIntro. iSplit=>//. iFrame. by iApply "HΦ".
-Qed.
-
-Lemma rswp_allocN_vec k s E v n :
-  0 < n →
-  ⟨⟨⟨ True ⟩⟩⟩
-    AllocN #n v at k @ s ; E
-  ⟨⟨⟨ l, RET #l; l ↦∗ vreplicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ ⟩⟩⟩.
-Proof.
-  iIntros (Hzs Φ) "_ HΦ". iApply rswp_allocN; [ lia | done | .. ]. iNext.
-  iIntros (l) "[Hl Hm]". iApply "HΦ". rewrite vec_to_list_replicate. iFrame.
-Qed.
-
-Lemma rswp_load_offset k s E l off vs v :
-  vs !! off = Some v →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ ! #(l +ₗ off) at k @ s; E ⟨⟨⟨ RET v; l ↦∗ vs ⟩⟩⟩.
-Proof.
-  iIntros (Hlookup Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (rswp_load with "Hl1"). iIntros "!> Hl1". iApply "HΦ".
-  iDestruct ("Hl2" $! v) as "Hl2". rewrite list_insert_id; last done.
-  iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma rswp_load_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) :
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ ! #(l +ₗ off) at k @ s; E ⟨⟨⟨ RET vs !!! off; l ↦∗ vs ⟩⟩⟩.
-Proof. apply rswp_load_offset. by apply vlookup_lookup. Qed.
-
-Lemma rswp_store_offset k s E l off vs v :
-  is_Some (vs !! off) →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ #(l +ₗ off) <- v at k @ s; E ⟨⟨⟨ RET #(); l ↦∗ <[off:=v]> vs ⟩⟩⟩.
-Proof.
-  iIntros ([w Hlookup] Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (rswp_store with "Hl1"). iNext. iIntros "Hl1".
-  iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma rswp_store_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) v :
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ #(l +ₗ off) <- v at k @ s; E ⟨⟨⟨ RET #(); l ↦∗ vinsert off v vs ⟩⟩⟩.
-Proof.
-  setoid_rewrite vec_to_list_insert. apply rswp_store_offset.
-  eexists. by apply vlookup_lookup.
-Qed.
-
-Lemma rswp_cmpxchg_suc_offset k s E l off vs v' v1 v2 :
-  vs !! off = Some v' →
-  v' = v1 →
-  vals_compare_safe v' v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  ⟨⟨⟨ RET (v', #true); l ↦∗ <[off:=v2]> vs ⟩⟩⟩.
-Proof.
-  iIntros (Hlookup ?? Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (rswp_cmpxchg_suc with "Hl1"); [done..|].
-  iNext. iIntros "Hl1". iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma rswp_cmpxchg_suc_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off = v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  ⟨⟨⟨ RET (vs !!! off, #true); l ↦∗ vinsert off v2 vs ⟩⟩⟩.
-Proof.
-  intros. setoid_rewrite vec_to_list_insert. eapply rswp_cmpxchg_suc_offset=> //.
-  by apply vlookup_lookup.
-Qed.
-
-Lemma rswp_cmpxchg_fail_offset k s E l off vs v0 v1 v2 :
-  vs !! off = Some v0 →
-  v0 ≠ v1 →
-  vals_compare_safe v0 v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  ⟨⟨⟨ RET (v0, #false); l ↦∗ vs ⟩⟩⟩.
-Proof.
-  iIntros (Hlookup HNEq Hcmp Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (rswp_cmpxchg_fail with "Hl1"); first done.
-  { destruct Hcmp; by [ left | right ]. }
-  iIntros "!> Hl1". iApply "HΦ". iDestruct ("Hl2" $! v0) as "Hl2".
-  rewrite list_insert_id; last done. iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma rswp_cmpxchg_fail_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off ≠ v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 at k @ s; E
-  ⟨⟨⟨ RET (vs !!! off, #false); l ↦∗ vs ⟩⟩⟩.
-Proof. intros. eapply rswp_cmpxchg_fail_offset=> //. by apply vlookup_lookup. Qed.
-
-Lemma rswp_faa_offset k s E l off vs (i1 i2 : Z) :
-  vs !! off = Some #i1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ FAA #(l +ₗ off) #i2 at k @ s; E
-  ⟨⟨⟨ RET LitV (LitInt i1); l ↦∗ <[off:=#(i1 + i2)]> vs ⟩⟩⟩.
-Proof.
-  iIntros (Hlookup Φ) ">Hl HΦ".
-  iDestruct (update_array l _ _ _ Hlookup with "Hl") as "[Hl1 Hl2]".
-  iApply (rswp_faa with "Hl1").
-  iNext. iIntros "Hl1". iApply "HΦ". iApply "Hl2". iApply "Hl1".
-Qed.
-
-Lemma rswp_faa_offset_vec k s E l sz (off : fin sz) (vs : vec val sz) (i1 i2 : Z) :
-  vs !!! off = #i1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ FAA #(l +ₗ off) #i2 at k @ s; E
-  ⟨⟨⟨ RET LitV (LitInt i1); l ↦∗ vinsert off #(i1 + i2) vs ⟩⟩⟩.
-Proof.
-  intros. setoid_rewrite vec_to_list_insert. apply rswp_faa_offset=> //.
-  by apply vlookup_lookup.
-Qed.
-
-
-(* refinement weakest pre versions *)
-(** Fork: Not using Texan triples to avoid some unnecessary [True] *)
-Lemma rwp_fork s E e Φ :
-  RWP e @ s; ⊤ ⟨⟨ _, True ⟩⟩ -∗ Φ (LitV LitUnit) -∗ RWP Fork e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_fork with "H HΦ").
-Qed.
-
-(** Heap *)
-Lemma rwp_allocN s E v n :
-  0 < n →
-  ⟨⟨⟨ True ⟩⟩⟩ AllocN (Val $ LitV $ LitInt $ n) (Val v) @ s; E
-  ⟨⟨⟨ l, RET LitV (LitLoc l); l ↦∗ replicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ ⟩⟩⟩.
-Proof.
-  iIntros (Hn Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_allocN _ _ _ _ _ Hn Φ with "H HΦ").
-Qed.
-
-Lemma rwp_alloc s E v :
-  ⟨⟨⟨ True ⟩⟩⟩ Alloc (Val v) @ s; E ⟨⟨⟨ l, RET LitV (LitLoc l); l ↦ v ∗ meta_token l ⊤ ⟩⟩⟩.
-Proof.
-  iIntros (Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_alloc with "H HΦ").
-Qed.
-
-Lemma rwp_load s E l q v :
-  ⟨⟨⟨ ▷ l ↦{q} v ⟩⟩⟩ Load (Val $ LitV $ LitLoc l) @ s; E ⟨⟨⟨ RET v; l ↦{q} v ⟩⟩⟩.
-Proof.
-  iIntros (Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_load with "H HΦ").
-Qed.
-
-Lemma rwp_store s E l v' v :
-  ⟨⟨⟨ ▷ l ↦ v' ⟩⟩⟩ Store (Val $ LitV (LitLoc l)) (Val v) @ s; E
-  ⟨⟨⟨ RET LitV LitUnit; l ↦ v ⟩⟩⟩.
-Proof.
-  iIntros (Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_store with "H HΦ").
-Qed.
-
-Lemma rwp_cmpxchg_fail s E l q v' v1 v2 :
-  v' ≠ v1 → vals_compare_safe v' v1 →
-  ⟨⟨⟨ ▷ l ↦{q} v' ⟩⟩⟩ CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) @ s; E
-  ⟨⟨⟨ RET PairV v' (LitV $ LitBool false); l ↦{q} v' ⟩⟩⟩.
-Proof.
-  iIntros (?? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_cmpxchg_fail with "H HΦ").
-Qed.
-
-Lemma rwp_cmpxchg_suc s E l v1 v2 v' :
-  v' = v1 → vals_compare_safe v' v1 →
-  ⟨⟨⟨ ▷ l ↦ v' ⟩⟩⟩ CmpXchg (Val $ LitV $ LitLoc l) (Val v1) (Val v2) @ s; E
-  ⟨⟨⟨ RET PairV v' (LitV $ LitBool true); l ↦ v2 ⟩⟩⟩.
-Proof.
-  iIntros (?? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_cmpxchg_suc with "H HΦ").
-Qed.
-
-Lemma rwp_faa s E l i1 i2 :
-  ⟨⟨⟨ ▷ l ↦ LitV (LitInt i1) ⟩⟩⟩ FAA (Val $ LitV $ LitLoc l) (Val $ LitV $ LitInt i2) @ s; E
-  ⟨⟨⟨ RET LitV (LitInt i1); l ↦ LitV (LitInt (i1 + i2)) ⟩⟩⟩.
-Proof.
-  iIntros (Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_faa with "H HΦ").
-Qed.
-
-Lemma rwp_allocN_vec s E v n :
-  0 < n →
-  ⟨⟨⟨ True ⟩⟩⟩
-    AllocN #n v @ s ; E
-  ⟨⟨⟨ l, RET #l; l ↦∗ vreplicate (Z.to_nat n) v ∗
-         [∗ list] i ∈ seq 0 (Z.to_nat n), meta_token (l +ₗ (i : nat)) ⊤ ⟩⟩⟩.
-Proof.
-  iIntros (? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_allocN_vec with "H HΦ").
-Qed.
-
-Lemma rwp_load_offset s E l off vs v :
-  vs !! off = Some v →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ ! #(l +ₗ off) @ s; E ⟨⟨⟨ RET v; l ↦∗ vs ⟩⟩⟩.
-Proof.
-  iIntros (? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_load_offset with "H HΦ").
-Qed.
-
-Lemma rwp_load_offset_vec s E l sz (off : fin sz) (vs : vec val sz) :
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ ! #(l +ₗ off) @ s; E ⟨⟨⟨ RET vs !!! off; l ↦∗ vs ⟩⟩⟩.
-Proof. apply rwp_load_offset. by apply vlookup_lookup. Qed.
-
-Lemma rwp_store_offset s E l off vs v :
-  is_Some (vs !! off) →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ #(l +ₗ off) <- v @ s; E ⟨⟨⟨ RET #(); l ↦∗ <[off:=v]> vs ⟩⟩⟩.
-Proof.
-  iIntros (? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_store_offset with "H HΦ").
-Qed.
-
-Lemma rwp_store_offset_vec s E l sz (off : fin sz) (vs : vec val sz) v :
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ #(l +ₗ off) <- v @ s; E ⟨⟨⟨ RET #(); l ↦∗ vinsert off v vs ⟩⟩⟩.
-Proof.
-  iIntros (Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_store_offset_vec with "H HΦ").
-Qed.
-
-Lemma rwp_cmpxchg_suc_offset s E l off vs v' v1 v2 :
-  vs !! off = Some v' →
-  v' = v1 →
-  vals_compare_safe v' v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  ⟨⟨⟨ RET (v', #true); l ↦∗ <[off:=v2]> vs ⟩⟩⟩.
-Proof.
-  iIntros (??? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_cmpxchg_suc_offset with "H HΦ").
-Qed.
-
-Lemma rwp_cmpxchg_suc_offset_vec s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off = v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  ⟨⟨⟨ RET (vs !!! off, #true); l ↦∗ vinsert off v2 vs ⟩⟩⟩.
-Proof.
-  iIntros (?? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_cmpxchg_suc_offset_vec with "H HΦ").
-Qed.
-
-Lemma rwp_cmpxchg_fail_offset s E l off vs v0 v1 v2 :
-  vs !! off = Some v0 →
-  v0 ≠ v1 →
-  vals_compare_safe v0 v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  ⟨⟨⟨ RET (v0, #false); l ↦∗ vs ⟩⟩⟩.
-Proof.
-  iIntros (??? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_cmpxchg_fail_offset with "H HΦ").
-Qed.
-
-Lemma rwp_cmpxchg_fail_offset_vec s E l sz (off : fin sz) (vs : vec val sz) v1 v2 :
-  vs !!! off ≠ v1 →
-  vals_compare_safe (vs !!! off) v1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩
-    CmpXchg #(l +ₗ off) v1 v2 @ s; E
-  ⟨⟨⟨ RET (vs !!! off, #false); l ↦∗ vs ⟩⟩⟩.
-Proof. intros. eapply rwp_cmpxchg_fail_offset=> //. by apply vlookup_lookup. Qed.
-
-Lemma rwp_faa_offset s E l off vs (i1 i2 : Z) :
-  vs !! off = Some #i1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ FAA #(l +ₗ off) #i2 @ s; E
-  ⟨⟨⟨ RET LitV (LitInt i1); l ↦∗ <[off:=#(i1 + i2)]> vs ⟩⟩⟩.
-Proof.
-  iIntros (? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_faa_offset with "H HΦ").
-Qed.
-
-Lemma rwp_faa_offset_vec s E l sz (off : fin sz) (vs : vec val sz) (i1 i2 : Z) :
-  vs !!! off = #i1 →
-  ⟨⟨⟨ ▷ l ↦∗ vs ⟩⟩⟩ FAA #(l +ₗ off) #i2 @ s; E
-  ⟨⟨⟨ RET LitV (LitInt i1); l ↦∗ vinsert off #(i1 + i2) vs ⟩⟩⟩.
-Proof.
-  iIntros (? Φ) "H HΦ"; iApply rwp_no_step; auto; last by iApply (rswp_faa_offset_vec with "H HΦ").
-Qed.
-End refinements.
diff --git a/theories/heap_lang/locations.v b/theories/heap_lang/locations.v
deleted file mode 100644
index 7484c98ab8e5870ca92fe0992009c0586d9fdd7c..0000000000000000000000000000000000000000
--- a/theories/heap_lang/locations.v
+++ /dev/null
@@ -1,45 +0,0 @@
-From iris.algebra Require Import base.
-From stdpp Require Import countable numbers gmap.
-
-Record loc := { loc_car : Z }.
-
-Instance loc_eq_decision : EqDecision loc.
-Proof. solve_decision. Qed.
-
-Instance loc_inhabited : Inhabited loc := populate {|loc_car := 0 |}.
-
-Instance loc_countable : Countable loc.
-Proof. by apply (inj_countable' loc_car (λ i, {| loc_car := i |})); intros []. Qed.
-
-Program Instance loc_infinite : Infinite loc :=
-  inj_infinite (λ p, {| loc_car := p |}) (λ l, Some (loc_car l)) _.
-Next Obligation. done. Qed.
-
-Definition loc_add (l : loc) (off : Z) : loc :=
-  {| loc_car := loc_car l + off|}.
-
-Notation "l +ₗ off" :=
-  (loc_add l off) (at level 50, left associativity) : stdpp_scope.
-
-Lemma loc_add_assoc l i j : l +ₗ i +ₗ j = l +ₗ (i + j).
-Proof. destruct l; rewrite /loc_add /=; f_equal; lia. Qed.
-
-Lemma loc_add_0 l : l +ₗ 0 = l.
-Proof. destruct l; rewrite /loc_add /=; f_equal; lia. Qed.
-
-Instance loc_add_inj l : Inj eq eq (loc_add l).
-Proof. destruct l; rewrite /Inj /loc_add /=; intros; simplify_eq; lia. Qed.
-
-Definition fresh_locs (ls : gset loc) : loc :=
-  {| loc_car := set_fold (λ k r, (1 + loc_car k) `max` r)%Z 1%Z ls |}.
-
-Lemma fresh_locs_fresh ls i :
-  (0 ≤ i)%Z → fresh_locs ls +ₗ i ∉ ls.
-Proof.
-  intros Hi. cut (∀ l, l ∈ ls → loc_car l < loc_car (fresh_locs ls) + i)%Z.
-  { intros help Hf%help. simpl in *. lia. }
-  apply (set_fold_ind_L (λ r ls, ∀ l, l ∈ ls → (loc_car l < r + i)%Z));
-    set_solver by eauto with lia.
-Qed.
-
-Global Opaque fresh_locs.
diff --git a/theories/heap_lang/metatheory.v b/theories/heap_lang/metatheory.v
deleted file mode 100644
index 9df37184bacf13d0a4d26fa7f33a4967e6d467ef..0000000000000000000000000000000000000000
--- a/theories/heap_lang/metatheory.v
+++ /dev/null
@@ -1,224 +0,0 @@
-From iris.heap_lang Require Export lang.
-From stdpp Require Import gmap.
-
-(* This file contains some metatheory about the heap_lang language,
-  which is not needed for verifying programs. *)
-
-(* Closed expressions and values. *)
-Fixpoint is_closed_expr (X : list string) (e : expr) : bool :=
-  match e with
-  | Val v => is_closed_val v
-  | Var x => bool_decide (x ∈ X)
-  | Rec f x e => is_closed_expr (f :b: x :b: X) e
-  | UnOp _ e | Fst e | Snd e | InjL e | InjR e | Fork e | Load e =>
-     is_closed_expr X e
-  | App e1 e2 | BinOp _ e1 e2 | Pair e1 e2 | AllocN e1 e2 | Store e1 e2 | FAA e1 e2 =>
-     is_closed_expr X e1 && is_closed_expr X e2
-  | If e0 e1 e2 | Case e0 e1 e2 | CmpXchg e0 e1 e2 | Resolve e0 e1 e2 =>
-     is_closed_expr X e0 && is_closed_expr X e1 && is_closed_expr X e2
-  | NewProph => true
-  end
-with is_closed_val (v : val) : bool :=
-  match v with
-  | LitV _ => true
-  | RecV f x e => is_closed_expr (f :b: x :b: []) e
-  | PairV v1 v2 => is_closed_val v1 && is_closed_val v2
-  | InjLV v | InjRV v => is_closed_val v
-  end.
-
-Lemma is_closed_weaken X Y e : is_closed_expr X e → X ⊆ Y → is_closed_expr Y e.
-Proof. revert X Y; induction e; naive_solver (eauto; set_solver). Qed.
-
-Lemma is_closed_weaken_nil X e : is_closed_expr [] e → is_closed_expr X e.
-Proof. intros. by apply is_closed_weaken with [], list_subseteq_nil. Qed.
-
-Lemma is_closed_subst X e x v :
-  is_closed_val v → is_closed_expr (x :: X) e → is_closed_expr X (subst x v e).
-Proof.
-  intros Hv. revert X.
-  induction e=> X /= ?; destruct_and?; split_and?; simplify_option_eq;
-    try match goal with
-    | H : ¬(_ ∧ _) |- _ => apply not_and_l in H as [?%dec_stable|?%dec_stable]
-    end; eauto using is_closed_weaken with set_solver.
-Qed.
-Lemma is_closed_subst' X e x v :
-  is_closed_val v → is_closed_expr (x :b: X) e → is_closed_expr X (subst' x v e).
-Proof. destruct x; eauto using is_closed_subst. Qed.
-
-(* Substitution *)
-Lemma subst_is_closed X e x es : is_closed_expr X e → x ∉ X → subst x es e = e.
-Proof.
-  revert X. induction e=> X /=; rewrite ?bool_decide_spec ?andb_True=> ??;
-    repeat case_decide; simplify_eq/=; f_equal; intuition eauto with set_solver.
-Qed.
-
-Lemma subst_is_closed_nil e x v : is_closed_expr [] e → subst x v e = e.
-Proof. intros. apply subst_is_closed with []; set_solver. Qed.
-
-Lemma subst_subst e x v v' :
-  subst x v (subst x v' e) = subst x v' e.
-Proof.
-  intros. induction e; simpl; try (f_equal; by auto);
-    simplify_option_eq; auto using subst_is_closed_nil with f_equal.
-Qed.
-Lemma subst_subst' e x v v' :
-  subst' x v (subst' x v' e) = subst' x v' e.
-Proof. destruct x; simpl; auto using subst_subst. Qed.
-
-Lemma subst_subst_ne e x y v v' :
-  x ≠ y → subst x v (subst y v' e) = subst y v' (subst x v e).
-Proof.
-  intros. induction e; simpl; try (f_equal; by auto);
-    simplify_option_eq; auto using eq_sym, subst_is_closed_nil with f_equal.
-Qed.
-Lemma subst_subst_ne' e x y v v' :
-  x ≠ y → subst' x v (subst' y v' e) = subst' y v' (subst' x v e).
-Proof. destruct x, y; simpl; auto using subst_subst_ne with congruence. Qed.
-
-Lemma subst_rec' f y e x v :
-  x = f ∨ x = y ∨ x = BAnon →
-  subst' x v (Rec f y e) = Rec f y e.
-Proof. intros. destruct x; simplify_option_eq; naive_solver. Qed.
-Lemma subst_rec_ne' f y e x v :
-  (x ≠ f ∨ f = BAnon) → (x ≠ y ∨ y = BAnon) →
-  subst' x v (Rec f y e) = Rec f y (subst' x v e).
-Proof. intros. destruct x; simplify_option_eq; naive_solver. Qed.
-
-Lemma  bin_op_eval_closed op v1 v2 v':
-  is_closed_val v1 → is_closed_val v2 → bin_op_eval op v1 v2 = Some v' →
-  is_closed_val v'.
-Proof.
-  rewrite /bin_op_eval /bin_op_eval_bool /bin_op_eval_int;
-    repeat case_match; by naive_solver.
-Qed.
-
-Lemma heap_closed_alloc σ l n w :
-  0 < n →
-  is_closed_val w →
-  map_Forall (λ _ v, is_closed_val v) (heap σ) →
-  (∀ i : Z, 0 ≤ i → i < n → heap σ !! (l +ₗ i) = None) →
-  map_Forall (λ _ v, is_closed_val v)
-             (heap_array l (replicate (Z.to_nat n) w) ∪ heap σ).
-Proof.
-  intros Hn Hw Hσ Hl.
-  eapply (map_Forall_ind
-            (λ k v, ((heap_array l (replicate (Z.to_nat n) w) ∪ heap σ)
-                       !! k = Some v))).
-  - apply map_Forall_empty.
-  - intros m i x Hi Hix Hkwm Hm.
-    apply map_Forall_insert_2; auto.
-    apply lookup_union_Some in Hix; last first.
-    { eapply heap_array_map_disjoint;
-        rewrite replicate_length Z2Nat.id; auto with lia. }
-    destruct Hix as [(?&?&?&[-> Hlt%inj_lt]%lookup_replicate_1)%heap_array_lookup|
-                     [j Hj]%elem_of_map_to_list%elem_of_list_lookup_1].
-    + rewrite !Z2Nat.id in Hlt; eauto with lia.
-    + apply map_Forall_to_list in Hσ.
-      by eapply Forall_lookup in Hσ; eauto; simpl in *.
-  - apply map_Forall_to_list, Forall_forall.
-    intros [? ?]; apply elem_of_map_to_list.
-Qed.
-
-(* The stepping relation preserves closedness *)
-Lemma head_step_is_closed e1 σ1 obs e2 σ2 es :
-  is_closed_expr [] e1 →
-  map_Forall (λ _ v, is_closed_val v) σ1.(heap) →
-  head_step e1 σ1 obs e2 σ2 es →
-
-  is_closed_expr [] e2 ∧ Forall (is_closed_expr []) es ∧
-  map_Forall (λ _ v, is_closed_val v) σ2.(heap).
-Proof.
-  intros Cl1 Clσ1 STEP.
-  induction STEP; simpl in *; split_and!;
-    try apply map_Forall_insert_2; try by naive_solver.
-  - subst. repeat apply is_closed_subst'; naive_solver.
-  - unfold un_op_eval in *. repeat case_match; naive_solver.
-  - eapply bin_op_eval_closed; eauto; naive_solver.
-  - by apply heap_closed_alloc.
-  - case_match; try apply map_Forall_insert_2; by naive_solver.
-Qed.
-
-(* Parallel substitution with maps of values indexed by strings *)
-Definition binder_delete {A} (x : binder) (vs : gmap string A) : gmap string A :=
-  if x is BNamed x' then delete x' vs else vs.
-Definition binder_insert {A} (x : binder) (v : A) (vs : gmap string A) : gmap string A :=
-  if x is BNamed x' then <[x':=v]>vs else vs.
-
-Lemma binder_insert_fmap {A B : Type} (f : A → B) (x : A) b vs :
-  f <$> binder_insert b x vs = binder_insert b (f x) (f <$> vs).
-Proof. destruct b; rewrite ?fmap_insert //. Qed.
-Lemma lookup_binder_delete_None {A : Type} (vs : gmap string A) x y :
-  binder_delete x vs !! y = None ↔ x = BNamed y ∨ vs !! y = None.
-Proof. destruct x; rewrite /= ?lookup_delete_None; naive_solver. Qed.
-
-Fixpoint subst_map (vs : gmap string val) (e : expr) : expr :=
-  match e with
-  | Val _ => e
-  | Var y => if vs !! y is Some v then Val v else Var y
-  | Rec f y e => Rec f y (subst_map (binder_delete y (binder_delete f vs)) e)
-  | App e1 e2 => App (subst_map vs e1) (subst_map vs e2)
-  | UnOp op e => UnOp op (subst_map vs e)
-  | BinOp op e1 e2 => BinOp op (subst_map vs e1) (subst_map vs e2)
-  | If e0 e1 e2 => If (subst_map vs e0) (subst_map vs e1) (subst_map vs e2)
-  | Pair e1 e2 => Pair (subst_map vs e1) (subst_map vs e2)
-  | Fst e => Fst (subst_map vs e)
-  | Snd e => Snd (subst_map vs e)
-  | InjL e => InjL (subst_map vs e)
-  | InjR e => InjR (subst_map vs e)
-  | Case e0 e1 e2 => Case (subst_map vs e0) (subst_map vs e1) (subst_map vs e2)
-  | Fork e => Fork (subst_map vs e)
-  | AllocN e1 e2 => AllocN (subst_map vs e1) (subst_map vs e2)
-  | Load e => Load (subst_map vs e)
-  | Store e1 e2 => Store (subst_map vs e1) (subst_map vs e2)
-  | CmpXchg e0 e1 e2 => CmpXchg (subst_map vs e0) (subst_map vs e1) (subst_map vs e2)
-  | FAA e1 e2 => FAA (subst_map vs e1) (subst_map vs e2)
-  | NewProph => NewProph
-  | Resolve e0 e1 e2 => Resolve (subst_map vs e0) (subst_map vs e1) (subst_map vs e2)
-  end.
-
-Lemma subst_map_empty e : subst_map ∅ e = e.
-Proof.
-  assert (∀ x, binder_delete x (∅:gmap _ val) = ∅) as Hdel.
-  { intros [|x]; by rewrite /= ?delete_empty. }
-  induction e; simplify_map_eq; rewrite ?Hdel; auto with f_equal.
-Qed.
-Lemma subst_map_insert x v vs e :
-  subst_map (<[x:=v]>vs) e = subst x v (subst_map (delete x vs) e).
-Proof.
-  revert vs. assert (∀ (y : binder) (vs : gmap _ val), y ≠ BNamed x →
-    binder_delete y (<[x:=v]> vs) = <[x:=v]> (binder_delete y vs)) as Hins.
-  { intros [|y] vs ?; rewrite /= ?delete_insert_ne //; congruence. }
-  assert (∀ (y : binder) (vs : gmap _ val),
-    binder_delete y (delete x vs) = delete x (binder_delete y vs)) as Hdel.
-  { by intros [|y] ?; rewrite /= 1?delete_commute. }
-  induction e=> vs; simplify_map_eq; auto with f_equal.
-  - match goal with
-    | |- context [ <[?x:=_]> _ !! ?y ] =>
-       destruct (decide (x = y)); simplify_map_eq=> //
-    end. by case (vs !! _); simplify_option_eq.
-  - destruct (decide _) as [[??]|[<-%dec_stable|[<-%dec_stable ?]]%not_and_l_alt].
-    + rewrite !Hins // !Hdel. eauto with f_equal.
-    + by rewrite /= delete_insert_delete delete_idemp.
-    + by rewrite /= Hins // delete_insert_delete !Hdel delete_idemp.
-Qed.
-Lemma subst_map_binder_insert b v vs e :
-  subst_map (binder_insert b v vs) e =
-  subst' b v (subst_map (binder_delete b vs) e).
-Proof. destruct b; rewrite ?subst_map_insert //. Qed.
-
-(* subst_map on closed expressions *)
-Lemma subst_map_is_closed X e vs :
-  is_closed_expr X e →
-  (∀ x, x ∈ X → vs !! x = None) →
-  subst_map vs e = e.
-Proof.
-  revert X vs. assert (∀ x x1 x2 X (vs : gmap string val),
-    (∀ x, x ∈ X → vs !! x = None) →
-    x ∈ x2 :b: x1 :b: X →
-    binder_delete x1 (binder_delete x2 vs) !! x = None).
-  { intros x x1 x2 X vs ??. rewrite !lookup_binder_delete_None. set_solver. }
-  induction e=> X vs /= ? HX; repeat case_match; naive_solver eauto with f_equal.
-Qed.
-
-Lemma subst_map_is_closed_nil e vs : is_closed_expr [] e → subst_map vs e = e.
-Proof. intros. apply subst_map_is_closed with []; set_solver. Qed.
diff --git a/theories/heap_lang/notation.v b/theories/heap_lang/notation.v
deleted file mode 100644
index 07e5df43260a4ac277bf6ecb0b51b9d5b97c54db..0000000000000000000000000000000000000000
--- a/theories/heap_lang/notation.v
+++ /dev/null
@@ -1,162 +0,0 @@
-From iris.program_logic Require Import language.
-From iris.heap_lang Require Export lang.
-Set Default Proof Using "Type".
-
-Delimit Scope expr_scope with E.
-Delimit Scope val_scope with V.
-
-(** Coercions to make programs easier to type. *)
-Coercion LitInt : Z >-> base_lit.
-Coercion LitBool : bool >-> base_lit.
-Coercion LitLoc : loc >-> base_lit.
-Coercion LitProphecy : proph_id >-> base_lit.
-
-Coercion App : expr >-> Funclass.
-
-Coercion Val : val >-> expr.
-Coercion Var : string >-> expr.
-
-(** Define some derived forms. *)
-Notation Lam x e := (Rec BAnon x e) (only parsing).
-Notation Let x e1 e2 := (App (Lam x e2) e1) (only parsing).
-Notation Seq e1 e2 := (Let BAnon e1 e2) (only parsing).
-Notation LamV x e := (RecV BAnon x e) (only parsing).
-Notation LetCtx x e2 := (AppRCtx (LamV x e2)) (only parsing).
-Notation SeqCtx e2 := (LetCtx BAnon e2) (only parsing).
-Notation Match e0 x1 e1 x2 e2 := (Case e0 (Lam x1 e1) (Lam x2 e2)) (only parsing).
-Notation Alloc e := (AllocN (Val $ LitV $ LitInt 1) e) (only parsing).
-(** Compare-and-set (CAS) returns just a boolean indicating success or failure. *)
-Notation CAS l e1 e2 := (Snd (CmpXchg l e1 e2)) (only parsing).
-
-(* Skip should be atomic, we sometimes open invariants around
-   it. Hence, we need to explicitly use LamV instead of e.g., Seq. *)
-Notation Skip := (App (Val $ LamV BAnon (Val $ LitV LitUnit)) (Val $ LitV LitUnit)).
-
-(* No scope for the values, does not conflict and scope is often not inferred
-properly. *)
-Notation "# l" := (LitV l%Z%V%stdpp) (at level 8, format "# l").
-
-(** Syntax inspired by Coq/Ocaml. Constructions with higher precedence come
-    first. *)
-Notation "( e1 , e2 , .. , en )" := (Pair .. (Pair e1 e2) .. en) : expr_scope.
-Notation "( e1 , e2 , .. , en )" := (PairV .. (PairV e1 e2) .. en) : val_scope.
-
-(*
-Using the '[hv' ']' printing box, we make sure that when the notation for match
-does not fit on a single line, line breaks will be inserted for *each* breaking
-point '/'. Note that after each breaking point /, one can put n spaces (for
-example '/  '). That way, when the breaking point is turned into a line break,
-indentation of n spaces will appear after the line break. As such, when the
-match does not fit on one line, it will print it like:
-
-  match: e0 with
-    InjL x1 => e1
-  | InjR x2 => e2
-  end
-
-Moreover, if the branches do not fit on a single line, it will be printed as:
-
-  match: e0 with
-    InjL x1 =>
-    lots of stuff bla bla bla bla bla bla bla bla
-  | InjR x2 =>
-    even more stuff bla bla bla bla bla bla bla bla
-  end
-*)
-Notation "'match:' e0 'with' 'InjL' x1 => e1 | 'InjR' x2 => e2 'end'" :=
-  (Match e0 x1%binder e1 x2%binder e2)
-  (e0, x1, e1, x2, e2 at level 200,
-   format "'[hv' 'match:'  e0  'with'  '/  ' '[' 'InjL'  x1  =>  '/  ' e1 ']'  '/' '[' |  'InjR'  x2  =>  '/  ' e2 ']'  '/' 'end' ']'") : expr_scope.
-Notation "'match:' e0 'with' 'InjR' x1 => e1 | 'InjL' x2 => e2 'end'" :=
-  (Match e0 x2%binder e2 x1%binder e1)
-  (e0, x1, e1, x2, e2 at level 200, only parsing) : expr_scope.
-
-Notation "()" := LitUnit : val_scope.
-Notation "! e" := (Load e%E) (at level 9, right associativity) : expr_scope.
-Notation "'ref' e" := (Alloc e%E) (at level 10) : expr_scope.
-Notation "- e" := (UnOp MinusUnOp e%E) : expr_scope.
-
-Notation "e1 + e2" := (BinOp PlusOp e1%E e2%E) : expr_scope.
-Notation "e1 +ₗ e2" := (BinOp OffsetOp e1%E e2%E) : expr_scope.
-Notation "e1 - e2" := (BinOp MinusOp e1%E e2%E) : expr_scope.
-Notation "e1 * e2" := (BinOp MultOp e1%E e2%E) : expr_scope.
-Notation "e1 `quot` e2" := (BinOp QuotOp e1%E e2%E) : expr_scope.
-Notation "e1 `rem` e2" := (BinOp RemOp e1%E e2%E) : expr_scope.
-Notation "e1 ≪ e2" := (BinOp ShiftLOp e1%E e2%E) : expr_scope.
-Notation "e1 ≫ e2" := (BinOp ShiftROp e1%E e2%E) : expr_scope.
-
-Notation "e1 ≤ e2" := (BinOp LeOp e1%E e2%E) : expr_scope.
-Notation "e1 < e2" := (BinOp LtOp e1%E e2%E) : expr_scope.
-Notation "e1 = e2" := (BinOp EqOp e1%E e2%E) : expr_scope.
-Notation "e1 ≠ e2" := (UnOp NegOp (BinOp EqOp e1%E e2%E)) : expr_scope.
-
-Notation "~ e" := (UnOp NegOp e%E) (at level 75, right associativity) : expr_scope.
-(* The unicode ← is already part of the notation "_ ← _; _" for bind. *)
-Notation "e1 <- e2" := (Store e1%E e2%E) (at level 80) : expr_scope.
-
-(* The breaking point '/  ' makes sure that the body of the rec is indented
-by two spaces in case the whole rec does not fit on a single line. *)
-Notation "'rec:' f x := e" := (Rec f%binder x%binder e%E)
-  (at level 200, f at level 1, x at level 1, e at level 200,
-   format "'[' 'rec:'  f  x  :=  '/  ' e ']'") : expr_scope.
-Notation "'rec:' f x := e" := (RecV f%binder x%binder e%E)
-  (at level 200, f at level 1, x at level 1, e at level 200,
-   format "'[' 'rec:'  f  x  :=  '/  ' e ']'") : val_scope.
-Notation "'if:' e1 'then' e2 'else' e3" := (If e1%E e2%E e3%E)
-  (at level 200, e1, e2, e3 at level 200) : expr_scope.
-
-(** Derived notions, in order of declaration. The notations for let and seq
-are stated explicitly instead of relying on the Notations Let and Seq as
-defined above. This is needed because App is now a coercion, and these
-notations are otherwise not pretty printed back accordingly. *)
-Notation "'rec:' f x y .. z := e" := (Rec f%binder x%binder (Lam y%binder .. (Lam z%binder e%E) ..))
-  (at level 200, f, x, y, z at level 1, e at level 200,
-   format "'[' 'rec:'  f  x  y  ..  z  :=  '/  ' e ']'") : expr_scope.
-Notation "'rec:' f x y .. z := e" := (RecV f%binder x%binder (Lam y%binder .. (Lam z%binder e%E) ..))
-  (at level 200, f, x, y, z at level 1, e at level 200,
-   format "'[' 'rec:'  f  x  y  ..  z  :=  '/  ' e ']'") : val_scope.
-
-(* The breaking point '/  ' makes sure that the body of the λ: is indented
-by two spaces in case the whole λ: does not fit on a single line. *)
-Notation "λ: x , e" := (Lam x%binder e%E)
-  (at level 200, x at level 1, e at level 200,
-   format "'[' 'λ:'  x ,  '/  ' e ']'") : expr_scope.
-Notation "λ: x y .. z , e" := (Lam x%binder (Lam y%binder .. (Lam z%binder e%E) ..))
-  (at level 200, x, y, z at level 1, e at level 200,
-   format "'[' 'λ:'  x  y  ..  z ,  '/  ' e ']'") : expr_scope.
-
-Notation "λ: x , e" := (LamV x%binder e%E)
-  (at level 200, x at level 1, e at level 200,
-   format "'[' 'λ:'  x ,  '/  ' e ']'") : val_scope.
-Notation "λ: x y .. z , e" := (LamV x%binder (Lam y%binder .. (Lam z%binder e%E) .. ))
-  (at level 200, x, y, z at level 1, e at level 200,
-   format "'[' 'λ:'  x  y  ..  z ,  '/  ' e ']'") : val_scope.
-
-Notation "'let:' x := e1 'in' e2" := (Lam x%binder e2%E e1%E)
-  (at level 200, x at level 1, e1, e2 at level 200,
-   format "'[' 'let:'  x  :=  '[' e1 ']'  'in'  '/' e2 ']'") : expr_scope.
-Notation "e1 ;; e2" := (Lam BAnon e2%E e1%E)
-  (at level 100, e2 at level 200,
-   format "'[' '[hv' '[' e1 ']'  ;;  ']' '/' e2 ']'") : expr_scope.
-
-(* Shortcircuit Boolean connectives *)
-Notation "e1 && e2" :=
-  (If e1%E e2%E (LitV (LitBool false))) (only parsing) : expr_scope.
-Notation "e1 || e2" :=
-  (If e1%E (LitV (LitBool true)) e2%E) (only parsing) : expr_scope.
-
-(** Notations for option *)
-Notation NONE := (InjL (LitV LitUnit)) (only parsing).
-Notation NONEV := (InjLV (LitV LitUnit)) (only parsing).
-Notation SOME x := (InjR x) (only parsing).
-Notation SOMEV x := (InjRV x) (only parsing).
-
-Notation "'match:' e0 'with' 'NONE' => e1 | 'SOME' x => e2 'end'" :=
-  (Match e0 BAnon e1 x%binder e2)
-  (e0, e1, x, e2 at level 200, only parsing) : expr_scope.
-Notation "'match:' e0 'with' 'SOME' x => e2 | 'NONE' => e1 'end'" :=
-  (Match e0 BAnon e1 x%binder e2)
-  (e0, e1, x, e2 at level 200, only parsing) : expr_scope.
-
-Notation ResolveProph e1 e2 := (Resolve Skip e1 e2) (only parsing).
-Notation "'resolve_proph:' p 'to:' v" := (ResolveProph p v) (at level 100) : expr_scope.
diff --git a/theories/heap_lang/proofmode.v b/theories/heap_lang/proofmode.v
deleted file mode 100644
index a48afd52172b301ec359b1481caf65ef3b1e6849..0000000000000000000000000000000000000000
--- a/theories/heap_lang/proofmode.v
+++ /dev/null
@@ -1,1007 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.program_logic.refinement Require Export ref_weakestpre tc_weakestpre.
-From iris.proofmode Require Import coq_tactics reduction.
-From iris.proofmode Require Export tactics.
-From iris.heap_lang Require Export tactics lifting.
-From iris.heap_lang Require Import notation.
-Set Default Proof Using "Type".
-Import uPred.
-
-Lemma tac_wp_expr_eval {SI} {Σ: gFunctors SI} `{!heapG Σ} Δ s E Φ e e' :
-  (∀ (e'':=e'), e = e'') →
-  envs_entails Δ (WP e' @ s; E {{ Φ }}) → envs_entails Δ (WP e @ s; E {{ Φ }}).
-Proof. by intros ->. Qed.
-Lemma tac_swp_expr_eval {SI} {Σ: gFunctors SI} `{!heapG Σ} k Δ s E Φ e e' :
-  (∀ (e'':=e'), e = e'') →
-  envs_entails Δ (SWP e' at k @ s; E {{ Φ }}) → envs_entails Δ (SWP e at k @ s; E {{ Φ }}).
-Proof. by intros ->. Qed.
-Lemma tac_rwp_expr_eval {SI A} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} Δ s E Φ e e' :
-  (∀ (e'':=e'), e = e'') →
-  envs_entails Δ (RWP e' @ s; E ⟨⟨ Φ ⟩⟩) → envs_entails Δ (RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-Proof. by intros ->. Qed.
-Lemma tac_rswp_expr_eval {SI A} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} k Δ s E Φ e e' :
-  (∀ (e'':=e'), e = e'') →
-  envs_entails Δ (RSWP e' at k @ s; E ⟨⟨ Φ ⟩⟩) → envs_entails Δ (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof. by intros ->. Qed.
-Lemma tac_twp_expr_eval {SI} {Σ: gFunctors SI} `{!heapG Σ} `{tcG Σ} Δ s E Φ e e' :
-  (∀ (e'':=e'), e = e'') →
-  envs_entails Δ (WP e' @ s; E [{ Φ }]) → envs_entails Δ (WP e @ s; E [{ Φ }]).
-Proof. by intros ->. Qed.
-
-Tactic Notation "wp_expr_eval" tactic(t) :=
-  iStartProof;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    eapply tac_wp_expr_eval;
-    [let x := fresh in intros x; t; unfold x; reflexivity|]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    eapply tac_swp_expr_eval;
-    [let x := fresh in intros x; t; unfold x; reflexivity|]
-  | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-    eapply tac_rwp_expr_eval;
-    [let x := fresh in intros x; t; unfold x; reflexivity|]
-  | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-    eapply tac_rswp_expr_eval;
-    [let x := fresh in intros x; t; unfold x; reflexivity|]
-  | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-    eapply tac_twp_expr_eval;
-      [let x := fresh in intros x; t; unfold x; reflexivity|]
-  | _ => fail "wp_expr_eval: not a 'wp'"
-  end.
-
-Lemma tac_wp_pure {SI} {Σ: gFunctors SI} `{!heapG Σ} Δ Δ' s E e1 e2 φ n Φ :
-  PureExec φ n e1 e2 →
-  φ →
-  MaybeIntoLaterNEnvs n Δ Δ' →
-  envs_entails Δ' (WP e2 @ s; E {{ Φ }}) →
-  envs_entails Δ (WP e1 @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ??? HΔ'. rewrite into_laterN_env_sound /=.
-  rewrite HΔ' -lifting.wp_pure_step_later //.
-Qed.
-Lemma tac_swp_pure {SI} {Σ: gFunctors SI} `{!heapG Σ} k Δ Δ' s E e1 e2 φ n Φ :
-  PureExec φ (S n) e1 e2 →
-  φ →
-  MaybeIntoLaterNEnvs (S n) Δ Δ' →
-  envs_entails Δ' (WP e2 @ s; E {{ Φ }}) →
-  envs_entails Δ (SWP e1 at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> Hsteps H ? HΔ'. rewrite into_laterN_env_sound /=.
-  rewrite HΔ'. by rewrite -lifting.swp_pure_step_later //.
-Qed.
-Lemma tac_rwp_pure {SI A} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} Δ s E e1 e2 φ n Φ :
-  PureExec φ n e1 e2 →
-  φ →
-  envs_entails Δ (RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (RWP e1 @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ??. rewrite -ref_lifting.rwp_pure_step //.
-Qed.
-Lemma tac_rswp_pure {SI A} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} Δ Δ' s E k e1 e2 φ Φ :
-  PureExec φ 1 e1 e2 →
-  φ →
-  MaybeIntoLaterNEnvs k Δ Δ' →
-  envs_entails Δ' (RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> Hsteps Hφ ? HΔ'. rewrite into_laterN_env_sound /=.
-  rewrite HΔ'. by rewrite -ref_lifting.rswp_pure_step_later //.
-Qed.
-Lemma tac_twp_pure {SI} {Σ: gFunctors SI} `{!heapG Σ} `{tcG Σ} Δ s E e1 e2 φ n Φ :
-  PureExec φ n e1 e2 →
-  φ →
-  envs_entails Δ (WP e2 @ s; E [{ Φ }]) →
-  envs_entails Δ (WP e1 @ s; E [{ Φ }]).
-Proof.
-  apply tac_rwp_pure.
-Qed.
-
-Lemma tac_wp_value {SI} {Σ: gFunctors SI} `{!heapG Σ} Δ s E Φ v :
-  envs_entails Δ (Φ v) → envs_entails Δ (WP (Val v) @ s; E {{ Φ }}).
-Proof. rewrite envs_entails_eq=> ->. by apply wp_value. Qed.
-Lemma tac_rwp_value {SI} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} Δ s E Φ v :
-  envs_entails Δ (Φ v) → envs_entails Δ (RWP (Val v) @ s; E ⟨⟨ Φ ⟩⟩).
-Proof. rewrite envs_entails_eq=> ->. by apply rwp_value. Qed.
-Lemma tac_twp_value {SI} {Σ: gFunctors SI} `{!heapG Σ} `{tcG Σ} Δ s E Φ v :
-  envs_entails Δ (Φ v) → envs_entails Δ (WP (Val v) @ s; E [{ Φ }]).
-Proof. apply tac_rwp_value. Qed.
-
-Ltac wp_expr_simpl := wp_expr_eval simpl.
-
-Ltac wp_value_head :=
-  first [eapply tac_wp_value || eapply tac_rwp_value || eapply tac_twp_value].
-
-Ltac wp_finish :=
-  wp_expr_simpl;      (* simplify occurences of subst/fill *)
-  try wp_value_head;  (* in case we have reached a value, get rid of the WP *)
-  pm_prettify.        (* prettify ▷s caused by [MaybeIntoLaterNEnvs] and
-                         λs caused by wp_value *)
-
-Ltac solve_vals_compare_safe :=
-  (* The first branch is for when we have [vals_compare_safe] in the context.
-     The other two branches are for when either one of the branches reduces to
-     [True] or we have it in the context. *)
-  fast_done || (left; fast_done) || (right; fast_done).
-
-(** The argument [efoc] can be used to specify the construct that should be
-reduced. For example, you can write [wp_pure (EIf _ _ _)], which will search
-for an [EIf _ _ _] in the expression, and reduce it.
-
-The use of [open_constr] in this tactic is essential. It will convert all holes
-(i.e. [_]s) into evars, that later get unified when an occurences is found
-(see [unify e' efoc] in the code below). *)
-Tactic Notation "wp_pure" open_constr(efoc) :=
-  iStartProof;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    let e := eval simpl in e in
-    reshape_expr e ltac:(fun K e' =>
-      unify e' efoc;
-      eapply (tac_wp_pure _ _ _ _ (fill K e'));
-      [iSolveTC                       (* PureExec *)
-      |try solve_vals_compare_safe    (* The pure condition for PureExec -- handles trivial goals, including [vals_compare_safe] *)
-      |iSolveTC                       (* IntoLaters *)
-      |wp_finish                      (* new goal *)
-      ])
-    || fail "wp_pure: cannot find" efoc "in" e "or" efoc "is not a redex"
-  | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-    let e := eval simpl in e in
-    reshape_expr e ltac:(fun K e' =>
-      unify e' efoc;
-      eapply (tac_rwp_pure _ _ _ (fill K e'));
-      [iSolveTC                       (* PureExec *)
-      |try fast_done                  (* The pure condition for PureExec *)
-      |wp_finish                      (* new goal *)
-      ])
-    || fail "wp_pure – rwp: cannot find" efoc "in" e "or" efoc "is not a redex"
-  | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-    let e := eval simpl in e in
-    reshape_expr e ltac:(fun K e' =>
-      unify e' efoc;
-      eapply (tac_twp_pure _ _ _ (fill K e'));
-      [iSolveTC                       (* PureExec *)
-      |try fast_done                  (* The pure condition for PureExec *)
-      |wp_finish                      (* new goal *)
-      ])
-    || fail "wp_pure – twp: cannot find" efoc "in" e "or" efoc "is not a redex"
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    let e := eval simpl in e in
-    reshape_expr e ltac:(fun K e' =>
-      unify e' efoc;
-      eapply (tac_swp_pure _ _ _ _ _ (fill K e'));
-      [ iSolveTC                       (* PureExec *)
-      | try fast_done                  (* The pure condition for PureExec *)
-      | apply _
-      | simpl; wp_finish                      (* new goal *)
-      ])
-    || fail "wp_pure: cannot find" efoc "in" e "or" efoc "is not a redex"
-  | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-    let e := eval simpl in e in
-    reshape_expr e ltac:(fun K e' =>
-      unify e' efoc;
-      eapply (tac_rswp_pure _ _ _ _ _ (fill K e'));
-      [ iSolveTC                       (* PureExec *)
-      | try fast_done                  (* The pure condition for PureExec *)
-      | apply _
-      | simpl; wp_finish                      (* new goal *)
-      ])
-    || fail "wp_pure: cannot find" efoc "in" e "or" efoc "is not a redex"
-  | _ => fail "wp_pure: not a 'wp'"
-  end.
-
-(* TODO: do this in one go, without [repeat]. *)
-Ltac wp_pures :=
-  iStartProof;
-  repeat (wp_pure _; []). (* The `;[]` makes sure that no side-condition
-                             magically spawns. *)
-
-(** Unlike [wp_pures], the tactics [wp_rec] and [wp_lam] should also reduce
-lambdas/recs that are hidden behind a definition, i.e. they should use
-[AsRecV_recv] as a proper instance instead of a [Hint Extern].
-
-We achieve this by putting [AsRecV_recv] in the current environment so that it
-can be used as an instance by the typeclass resolution system. We then perform
-the reduction, and finally we clear this new hypothesis. *)
-Tactic Notation "wp_rec" :=
-  let H := fresh in
-  assert (H := AsRecV_recv);
-  wp_pure (App _ _);
-  clear H.
-
-Tactic Notation "wp_if" := wp_pure (If _ _ _).
-Tactic Notation "wp_if_true" := wp_pure (If (LitV (LitBool true)) _ _).
-Tactic Notation "wp_if_false" := wp_pure (If (LitV (LitBool false)) _ _).
-Tactic Notation "wp_unop" := wp_pure (UnOp _ _).
-Tactic Notation "wp_binop" := wp_pure (BinOp _ _ _).
-Tactic Notation "wp_op" := wp_unop || wp_binop.
-Tactic Notation "wp_lam" := wp_rec.
-Tactic Notation "wp_let" := wp_pure (Rec BAnon (BNamed _) _); wp_lam.
-Tactic Notation "wp_seq" := wp_pure (Rec BAnon BAnon _); wp_lam.
-Tactic Notation "wp_proj" := wp_pure (Fst _) || wp_pure (Snd _).
-Tactic Notation "wp_case" := wp_pure (Case _ _ _).
-Tactic Notation "wp_match" := wp_case; wp_pure (Rec _ _ _); wp_lam.
-Tactic Notation "wp_inj" := wp_pure (InjL _) || wp_pure (InjR _).
-Tactic Notation "wp_pair" := wp_pure (Pair _ _).
-Tactic Notation "wp_closure" := wp_pure (Rec _ _ _).
-
-
-(* SWP Tactics *)
-(* TODO: figure out the right tactics here *)
-Tactic Notation "wp_swp" constr(k) := iApply (swp_wp k); first done.
-Tactic Notation "wp_swp" := iApply (swp_wp _); first done.
-Tactic Notation "swp_step" := iApply (swp_step _).
-Tactic Notation "swp_last_step" := swp_step; iApply swp_finish. 
-Tactic Notation "swp_finish" := iApply swp_finish.
-
-Lemma tac_wp_bind {SI} {Σ: gFunctors SI} `{!heapG Σ} K Δ s E Φ e f :
-  f = (λ e, fill K e) → (* as an eta expanded hypothesis so that we can `simpl` it *)
-  envs_entails Δ (WP e @ s; E {{ v, WP f (Val v) @ s; E {{ Φ }} }})%I →
-  envs_entails Δ (WP fill K e @ s; E {{ Φ }}).
-Proof. rewrite envs_entails_eq=> -> ->. by apply: wp_bind. Qed.
-Lemma tac_swp_bind {SI} {Σ: gFunctors SI} `{!heapG Σ} k K Δ s E Φ e f :
-  language.to_val e = None →
-  f = (λ e, fill K e) → (* as an eta expanded hypothesis so that we can `simpl` it *)
-  envs_entails Δ (SWP e at k @ s; E {{ v, WP f (Val v) @ s; E {{ Φ }} }})%I →
-  envs_entails Δ (SWP fill K e at k @ s; E {{ Φ }}).
-Proof. rewrite envs_entails_eq=> ? -> ->. by apply: swp_bind. Qed.
-Lemma tac_rwp_bind {SI A} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} K Δ s E Φ e f :
-  f = (λ e, fill K e) → (* as an eta expanded hypothesis so that we can `simpl` it *)
-  envs_entails Δ (RWP e @ s; E ⟨⟨ v, RWP f (Val v) @ s; E ⟨⟨ Φ ⟩⟩ ⟩⟩)%I →
-  envs_entails Δ (RWP fill K e @ s; E ⟨⟨ Φ ⟩⟩).
-Proof. rewrite envs_entails_eq=> -> ->. by apply: rwp_bind. Qed.
-Lemma tac_rswp_bind {SI A} {Σ: gFunctors SI} `{!heapG Σ} `{!source Σ A} k K Δ s E Φ e f :
-  language.to_val e = None →
-  f = (λ e, fill K e) → (* as an eta expanded hypothesis so that we can `simpl` it *)
-  envs_entails Δ (RSWP e at k @ s; E ⟨⟨ v, RWP f (Val v) @ s; E ⟨⟨ Φ ⟩⟩ ⟩⟩)%I →
-  envs_entails Δ (RSWP fill K e at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof. rewrite envs_entails_eq=> ? -> ->. by apply: rswp_bind. Qed.
-Lemma tac_twp_bind {SI} {Σ: gFunctors SI}  `{!heapG Σ} `{tcG Σ} K Δ s E Φ e f :
-  f = (λ e, fill K e) → (* as an eta expanded hypothesis so that we can `simpl` it *)
-  envs_entails Δ (WP e @ s; E [{ v, WP f (Val v) @ s; E [{ Φ }] }])%I →
-  envs_entails Δ (WP fill K e @ s; E [{ Φ }]).
-Proof. rewrite envs_entails_eq=> -> ->. by apply: rwp_bind. Qed.
-
-Ltac wp_bind_core K :=
-  lazymatch eval hnf in K with
-  | [] => idtac
-  | _ => eapply (tac_wp_bind K); [simpl; reflexivity|reduction.pm_prettify]
-  end.
-Ltac swp_bind_core K :=
-  lazymatch eval hnf in K with
-  | [] => idtac
-  | _ => eapply (tac_swp_bind _ K);[done| simpl; reflexivity|reduction.pm_prettify]
-  end.
-Ltac rwp_bind_core K :=
-  lazymatch eval hnf in K with
-  | [] => idtac
-  | _ => eapply (tac_rwp_bind K); [simpl; reflexivity|reduction.pm_prettify]
-  end.
-Ltac rswp_bind_core K :=
-  lazymatch eval hnf in K with
-  | [] => idtac
-  | _ => eapply (tac_rswp_bind _ K);[done| simpl; reflexivity|reduction.pm_prettify]
-  end.
-Ltac twp_bind_core K :=
-  lazymatch eval hnf in K with
-  | [] => idtac
-  | _ => eapply (tac_twp_bind K); [simpl; reflexivity|reduction.pm_prettify]
-  end.
-
-Tactic Notation "wp_bind" open_constr(efoc) :=
-  iStartProof;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    reshape_expr e ltac:(fun K e' => unify e' efoc; wp_bind_core K)
-    || fail "wp_bind: cannot find" efoc "in" e
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    reshape_expr e ltac:(fun K e' => unify e' efoc; swp_bind_core K)
-    || fail "wp_bind: cannot find" efoc "in" e
-  | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-    reshape_expr e ltac:(fun K e' => unify e' efoc; rwp_bind_core K)
-    || fail "wp_bind: cannot find" efoc "in" e
-  | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-    reshape_expr e ltac:(fun K e' => unify e' efoc; rswp_bind_core K)
-    || fail "wp_bind: cannot find" efoc "in" e
-  | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-    reshape_expr e ltac:(fun K e' => unify e' efoc; twp_bind_core K)
-    || fail "wp_bind: cannot find" efoc "in" e
-  | _ => fail "wp_bind: not a 'wp'"
-  end.
-
-(** Heap tactics *)
-Section heap.
-Context {SI} {Σ: gFunctors SI} `{!heapG Σ} .
-Implicit Types P Q : iProp Σ.
-Implicit Types Φ : val → iProp Σ.
-Implicit Types Δ : envs (uPredI (iResUR Σ)).
-Implicit Types v : val.
-Implicit Types z : Z.
-
-Lemma tac_wp_allocN Δ Δ' s E j K v n Φ :
-  0 < n →
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (array l (replicate (Z.to_nat n) v))) Δ' = Some Δ'' ∧
-    envs_entails Δ'' (WP fill K (Val $ LitV $ LitLoc l) @ s; E {{ Φ }})) →
-  envs_entails Δ (WP fill K (AllocN (Val $ LitV $ LitInt n) (Val v)) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ? ? HΔ.
-  rewrite -wp_bind. eapply wand_apply; first exact: wp_allocN.
-  rewrite left_id into_laterN_env_sound; apply later_mono, forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦∗ _)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_swp_allocN k Δ Δ' s E j K v n Φ :
-  0 < n →
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (array l (replicate (Z.to_nat n) v))) Δ' = Some Δ'' ∧
-    envs_entails Δ'' (WP fill K (Val $ LitV $ LitLoc l) @ s; E {{ Φ }})) →
-  envs_entails Δ (SWP fill K (AllocN (Val $ LitV $ LitInt n) (Val v)) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ? ? HΔ.
-  rewrite -swp_bind; last done. eapply wand_apply; first exact: swp_allocN.
-  rewrite left_id into_laterN_env_sound; apply later_mono, forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦∗ _)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_rwp_allocN {A} `{!source Σ A} Δ s E j K v n Φ :
-  0 < n →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (array l (replicate (Z.to_nat n) v))) Δ = Some Δ'' ∧
-    envs_entails Δ'' (RWP fill K (Val $ LitV $ LitLoc l) @ s; E ⟨⟨ Φ ⟩⟩)) →
-  envs_entails Δ (RWP fill K (AllocN (Val $ LitV $ LitInt n) (Val v)) @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ? HΔ.
-  rewrite -rwp_bind. eapply wand_apply; first exact: rwp_allocN.
-  rewrite left_id; apply forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦∗ _)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_rswp_allocN {A} `{!source Σ A} k Δ Δ' s E j K v n Φ :
-  0 < n →
-  MaybeIntoLaterNEnvs k Δ Δ' →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (array l (replicate (Z.to_nat n) v))) Δ' = Some Δ'' ∧
-    envs_entails Δ'' (RWP fill K (Val $ LitV $ LitLoc l) @ s; E ⟨⟨ Φ ⟩⟩)) →
-  envs_entails Δ (RSWP fill K (AllocN (Val $ LitV $ LitInt n) (Val v)) at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ? ? HΔ.
-  rewrite -rswp_bind; last done. eapply wand_apply; first exact: rswp_allocN.
-  rewrite left_id into_laterN_env_sound; apply laterN_mono, forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦∗ _)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_twp_allocN `{!tcG Σ} Δ s E j K v n Φ :
-  0 < n →
-  (∀ l, ∃ Δ',
-    envs_app false (Esnoc Enil j (array l (replicate (Z.to_nat n) v))) Δ
-    = Some Δ' ∧
-    envs_entails Δ' (WP fill K (Val $ LitV $ LitLoc l) @ s; E [{ Φ }])) →
-  envs_entails Δ (WP fill K (AllocN (Val $ LitV $ LitInt n) (Val v)) @ s; E [{ Φ }]).
-Proof.
-  apply tac_rwp_allocN.
-Qed.
-
-Lemma tac_wp_alloc Δ Δ' s E j K v Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (l ↦ v)) Δ' = Some Δ'' ∧
-    envs_entails Δ'' (WP fill K (Val $ LitV l) @ s; E {{ Φ }})) →
-  envs_entails Δ (WP fill K (Alloc (Val v)) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ? HΔ.
-  rewrite -wp_bind. eapply wand_apply; first exact: wp_alloc.
-  rewrite left_id into_laterN_env_sound; apply later_mono, forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦ v)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_swp_alloc k Δ Δ' s E j K v Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (l ↦ v)) Δ' = Some Δ'' ∧
-    envs_entails Δ'' (WP fill K (Val $ LitV l) @ s; E {{ Φ }})) →
-  envs_entails Δ (SWP fill K (Alloc (Val v)) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ? HΔ.
-  rewrite -swp_bind; last done. eapply wand_apply; first exact: swp_alloc.
-  rewrite left_id into_laterN_env_sound; apply later_mono, forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦ v)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_rwp_alloc {A} `{!source Σ A} Δ s E j K v Φ :
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (l ↦ v)) Δ = Some Δ'' ∧
-    envs_entails Δ'' (RWP fill K (Val $ LitV l) @ s; E ⟨⟨ Φ ⟩⟩)) →
-  envs_entails Δ (RWP fill K (Alloc (Val v)) @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> HΔ.
-  rewrite -rwp_bind. eapply wand_apply; first exact: rwp_alloc.
-  rewrite left_id; apply forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦ v)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_rswp_alloc {A} `{!source Σ A} k Δ Δ' s E j K v Φ :
-  MaybeIntoLaterNEnvs k Δ Δ' →
-  (∀ l, ∃ Δ'',
-    envs_app false (Esnoc Enil j (l ↦ v)) Δ' = Some Δ'' ∧
-    envs_entails Δ'' (RWP fill K (Val $ LitV l) @ s; E ⟨⟨ Φ ⟩⟩)) →
-  envs_entails Δ (RSWP fill K (Alloc (Val v)) at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ? HΔ.
-  rewrite -rswp_bind; last done. eapply wand_apply; first exact: rswp_alloc.
-  rewrite left_id into_laterN_env_sound; apply laterN_mono, forall_intro=> l.
-  destruct (HΔ l) as (Δ''&?&HΔ'). rewrite envs_app_sound //; simpl.
-  apply wand_intro_l. by rewrite (sep_elim_l (l ↦ v)%I) right_id wand_elim_r.
-Qed.
-Lemma tac_twp_alloc `{!tcG Σ} Δ s E j K v Φ :
-  (∀ l, ∃ Δ',
-    envs_app false (Esnoc Enil j (l ↦ v)) Δ = Some Δ' ∧
-    envs_entails Δ' (WP fill K (Val $ LitV $ LitLoc l) @ s; E [{ Φ }])) →
-  envs_entails Δ (WP fill K (Alloc (Val v)) @ s; E [{ Φ }]).
-Proof.
-  apply tac_rwp_alloc.
-Qed.
-
-Lemma tac_wp_load Δ Δ' s E i K l q v Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  envs_lookup i Δ' = Some (false, l ↦{q} v)%I →
-  envs_entails Δ' (WP fill K (Val v) @ s; E {{ Φ }}) →
-  envs_entails Δ (WP fill K (Load (LitV l)) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ???.
-  rewrite -wp_bind -(swp_wp 1) // -swp_step  into_laterN_env_sound.
-  apply later_mono.
-  eapply wand_apply; first exact: swp_load.
-  rewrite envs_lookup_split // -!later_intro; simpl.
-  by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_swp_load k Δ s E i K l q v Φ :
-  envs_lookup i Δ = Some (false, l ↦{q} v)%I →
-  envs_entails Δ (WP fill K (Val v) @ s; E {{ Φ }}) →
-  envs_entails Δ (SWP fill K (Load (LitV l)) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ??.
-  rewrite -swp_bind; last done. eapply wand_apply; first exact: swp_load.
-  rewrite envs_lookup_split // -!later_intro; simpl.
-  by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_rswp_load {A} `{!source Σ A} k Δ s E i K l q v Φ :
-  envs_lookup i Δ = Some (false, l ↦{q} v)%I →
-  envs_entails Δ (RWP fill K (Val v) @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (RSWP fill K (Load (LitV l)) at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=> ? HΔ.
-  rewrite -rswp_bind; last done. eapply wand_apply; first exact: rswp_load.
-  rewrite envs_lookup_split//; simpl.
-  by rewrite -!later_intro -laterN_intro HΔ.
-Qed.
-Lemma tac_rwp_load {A} `{!source Σ A} Δ s E i K l q v Φ :
-  envs_lookup i Δ = Some (false, l ↦{q} v)%I →
-  envs_entails Δ (RWP fill K (Val v) @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (RWP fill K (Load (LitV l)) @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  intros ??. rewrite -rwp_no_step; first by eapply tac_rswp_load.
-  by eapply to_val_fill_none.
-Qed.
-Lemma tac_twp_load `{!tcG Σ}  Δ s E i K l q v Φ :
-  envs_lookup i Δ = Some (false, l ↦{q} v)%I →
-  envs_entails Δ (WP fill K (Val v) @ s; E [{Φ}]) →
-  envs_entails Δ (WP fill K (Load (LitV l)) @ s; E [{Φ}]).
-Proof.
-  apply tac_rwp_load.
-Qed.
-
-Lemma tac_wp_store Δ Δ' Δ'' s E i K l v v' Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  envs_lookup i Δ' = Some (false, l ↦ v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v')) Δ' = Some Δ'' →
-  envs_entails Δ'' (WP fill K (Val $ LitV LitUnit) @ s; E {{ Φ }}) →
-  envs_entails Δ (WP fill K (Store (LitV l) (Val v')) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ????.
-  rewrite -wp_bind -(swp_wp 1) // -swp_step into_laterN_env_sound.
-  eapply later_mono, wand_apply; first by eapply swp_store.
-  rewrite  -!later_intro envs_simple_replace_sound //; simpl.
-  rewrite right_id. by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_swp_store k Δ Δ' s E i K l v v' Φ :
-  envs_lookup i Δ = Some (false, l ↦ v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v')) Δ = Some Δ' →
-  envs_entails Δ' (WP fill K (Val $ LitV LitUnit) @ s; E {{ Φ }}) →
-  envs_entails Δ (SWP fill K (Store (LitV l) v') at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq. intros. rewrite -swp_bind; last done.
-  eapply wand_apply; first by eapply swp_store.
-  rewrite envs_simple_replace_sound // -!later_intro; simpl.
-  rewrite right_id. by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_rswp_store {A} `{!source Σ A} k Δ Δ' s E i K l v v' Φ :
-  envs_lookup i Δ = Some (false, l ↦ v')%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v)) Δ = Some Δ' →
-  envs_entails Δ' (RWP fill K (Val $ LitV LitUnit) @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (RSWP fill K (Store (LitV l) v) at k @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  rewrite envs_entails_eq=>?? HΔ. rewrite -rswp_bind; last done.
-  eapply wand_apply; first by exact: rswp_store.
-  rewrite envs_simple_replace_sound // -!later_intro -laterN_intro; simpl.
-  rewrite right_id HΔ. by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_rwp_store {A} `{!source Σ A} Δ Δ' s E i K l v v' Φ :
-  envs_lookup i Δ = Some (false, l ↦ v')%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v)) Δ = Some Δ' →
-  envs_entails Δ' (RWP fill K (Val $ LitV LitUnit) @ s; E ⟨⟨ Φ ⟩⟩) →
-  envs_entails Δ (RWP fill K (Store (LitV l) v) @ s; E ⟨⟨ Φ ⟩⟩).
-Proof.
-  intros ???. rewrite -rwp_no_step; first by eapply tac_rswp_store.
-  by eapply to_val_fill_none.
-Qed.
-Lemma tac_twp_store `{tcG Σ} Δ Δ' s E i K l v v' Φ :
-  envs_lookup i Δ = Some (false, l ↦ v')%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v)) Δ = Some Δ' →
-  envs_entails Δ' (WP fill K (Val $ LitV LitUnit) @ s; E [{ Φ }]) →
-  envs_entails Δ (WP fill K (Store (LitV l) v) @ s; E [{ Φ }]).
-Proof.
-  apply tac_rwp_store.
-Qed.
-
-(* TODO: atomic operations for the refinement weakest preconditions *)
-Lemma tac_wp_cmpxchg Δ Δ' Δ'' s E i K l v v1 v2 Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  envs_lookup i Δ' = Some (false, l ↦ v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v2)) Δ' = Some Δ'' →
-  vals_compare_safe v v1 →
-  (v = v1 →
-   envs_entails Δ'' (WP fill K (Val $ PairV v (LitV $ LitBool true)) @ s; E {{ Φ }})) →
-  (v ≠ v1 →
-   envs_entails Δ' (WP fill K (Val $ PairV v (LitV $ LitBool false)) @ s; E {{ Φ }})) →
-  envs_entails Δ (WP fill K (CmpXchg (LitV l) (Val v1) (Val v2)) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ???? Hsuc Hfail.
-  destruct (decide (v = v1)) as [Heq|Hne].
-  - rewrite -wp_bind -(swp_wp 1) // -swp_step into_laterN_env_sound. eapply later_mono, wand_apply.
-    { eapply swp_cmpxchg_suc; eauto. }
-    rewrite -!later_intro /= {1}envs_simple_replace_sound //; simpl.
-    apply sep_mono_r. rewrite right_id. apply wand_mono; auto.
-  - rewrite -wp_bind -(swp_wp 1) // -swp_step into_laterN_env_sound. eapply later_mono, wand_apply.
-    { eapply swp_cmpxchg_fail; eauto. }
-    rewrite -!later_intro /= {1}envs_lookup_split //; simpl.
-    apply sep_mono_r. apply wand_mono; auto.
-Qed.
-Lemma tac_swp_cmpxchg k Δ Δ' s E i K l v v1 v2 Φ :
-  envs_lookup i Δ = Some (false, l ↦ v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v2)) Δ = Some Δ' →
-  vals_compare_safe v v1 →
-  (v = v1 →
-   envs_entails Δ' (WP fill K (Val $ PairV v (LitV $ LitBool true)) @ s; E {{ Φ }})) →
-  (v ≠ v1 →
-   envs_entails Δ (WP fill K (Val $ PairV v (LitV $ LitBool false)) @ s; E {{ Φ }})) →
-  envs_entails Δ (SWP fill K (CmpXchg (LitV l) v1 v2) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ??? Hsuc Hfail.
-  destruct (decide (v = v1)) as [Heq|Hne].
-  - rewrite -swp_bind //. eapply wand_apply.
-    { eapply swp_cmpxchg_suc; eauto. }
-    rewrite /= {1}envs_simple_replace_sound // -!later_intro; simpl.
-    apply sep_mono_r. rewrite right_id. apply wand_mono; auto.
-  - rewrite -swp_bind //. eapply wand_apply.
-    { eapply swp_cmpxchg_fail; eauto. }
-    rewrite /= {1}envs_lookup_split // -!later_intro; simpl.
-    apply sep_mono_r. apply wand_mono; auto.
-Qed.
-
-Lemma tac_wp_cmpxchg_fail Δ Δ' s E i K l q v v1 v2 Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  envs_lookup i Δ' = Some (false, l ↦{q} v)%I →
-  v ≠ v1 → vals_compare_safe v v1 →
-  envs_entails Δ' (WP fill K (Val $ PairV v (LitV $ LitBool false)) @ s; E {{ Φ }}) →
-  envs_entails Δ (WP fill K (CmpXchg (LitV l) v1 v2) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ?????.
-  rewrite -wp_bind -(swp_wp 1) // -swp_step into_laterN_env_sound.
-  eapply later_mono, wand_apply; first exact: swp_cmpxchg_fail.
-  rewrite -!later_intro envs_lookup_split //; simpl.
-  by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_swp_cmpxchg_fail k Δ s E i K l q v v1 v2 Φ :
-  envs_lookup i Δ = Some (false, l ↦{q} v)%I →
-  v ≠ v1 → vals_compare_safe v v1 →
-  envs_entails Δ (WP fill K (Val $ PairV v (LitV $ LitBool false)) @ s; E {{ Φ }}) →
-  envs_entails Δ (SWP fill K (CmpXchg (LitV l) v1 v2) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq. intros. rewrite -swp_bind //.
-  eapply wand_apply; first exact: swp_cmpxchg_fail.
-  rewrite -!later_intro envs_lookup_split //; simpl. by do 2 f_equiv.
-Qed.
-
-Lemma tac_wp_cmpxchg_suc Δ Δ' Δ'' s E i K l v v1 v2 Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  envs_lookup i Δ' = Some (false, l ↦ v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v2)) Δ' = Some Δ'' →
-  v = v1 → vals_compare_safe v v1 →
-  envs_entails Δ'' (WP fill K (Val $ PairV v (LitV $ LitBool true)) @ s; E {{ Φ }}) →
-  envs_entails Δ (WP fill K (CmpXchg (LitV l) v1 v2) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ??????; subst.
-  rewrite -wp_bind -(swp_wp 1) // -swp_step into_laterN_env_sound. eapply later_mono, wand_apply.
-  { eapply swp_cmpxchg_suc; eauto. }
-  rewrite  -!later_intro envs_simple_replace_sound //; simpl.
-  rewrite right_id. by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_swp_cmpxchg_suc k Δ Δ' s E i K l v v1 v2 Φ :
-  envs_lookup i Δ = Some (false, l ↦ v)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ v2)) Δ = Some Δ' →
-  v = v1 → vals_compare_safe v v1 →
-  envs_entails Δ' (WP fill K (Val $ PairV v (LitV $ LitBool true)) @ s; E {{ Φ }}) →
-  envs_entails Δ (SWP fill K (CmpXchg (LitV l) v1 v2) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=>?????; subst.
-  rewrite -swp_bind //. eapply wand_apply.
-  { eapply swp_cmpxchg_suc; eauto. }
-  rewrite envs_simple_replace_sound //; simpl.
-  rewrite right_id -!later_intro. by apply sep_mono_r, wand_mono.
-Qed.
-
-Lemma tac_wp_faa Δ Δ' Δ'' s E i K l z1 z2 Φ :
-  MaybeIntoLaterNEnvs 1 Δ Δ' →
-  envs_lookup i Δ' = Some (false, l ↦ LitV z1)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ LitV (z1 + z2))) Δ' = Some Δ'' →
-  envs_entails Δ'' (WP fill K (Val $ LitV z1) @ s; E {{ Φ }}) →
-  envs_entails Δ (WP fill K (FAA (LitV l) (LitV z2)) @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ????.
-  rewrite -wp_bind -(swp_wp 1) // -swp_step into_laterN_env_sound.
-  eapply later_mono, wand_apply; first exact: (swp_faa _ _ _ _ z1 z2).
-  rewrite -!later_intro envs_simple_replace_sound //; simpl.
-  rewrite right_id. by apply sep_mono_r, wand_mono.
-Qed.
-Lemma tac_swp_faa k Δ Δ' s E i K l z1 z2 Φ :
-  envs_lookup i Δ = Some (false, l ↦ LitV z1)%I →
-  envs_simple_replace i false (Esnoc Enil i (l ↦ LitV (z1 + z2))) Δ = Some Δ' →
-  envs_entails Δ' (WP fill K (Val $ LitV z1) @ s; E {{ Φ }}) →
-  envs_entails Δ (SWP fill K (FAA (LitV l) (LitV z2)) at k @ s; E {{ Φ }}).
-Proof.
-  rewrite envs_entails_eq=> ???.
-  rewrite -swp_bind //. eapply wand_apply; first exact: (swp_faa _ _ _ _ z1 z2).
-  rewrite envs_simple_replace_sound //; simpl.
-  rewrite right_id -!later_intro. by apply sep_mono_r, wand_mono.
-Qed.
-End heap.
-
-(** Evaluate [lem] to a hypothesis [H] that can be applied, and then run
-[wp_bind K; tac H] for every possible evaluation context.  [tac] can do
-[iApplyHyp H] to actually apply the hypothesis.  TC resolution of [lem] premises
-happens *after* [tac H] got executed. *)
-Tactic Notation "wp_apply_core" open_constr(lem) tactic(tac) :=
-  wp_pures;
-  iPoseProofCore lem as false (fun H =>
-    lazymatch goal with
-    | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-      reshape_expr e ltac:(fun K e' =>
-        wp_bind_core K; tac H) ||
-      lazymatch iTypeOf H with
-      | Some (_,?P) => fail "wp_apply: cannot apply" P
-      end
-    | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-      reshape_expr e ltac:(fun K e' =>
-        swp_bind_core K; tac H) ||
-      lazymatch iTypeOf H with
-      | Some (_,?P) => fail "wp_apply: cannot apply" P
-      end
-    | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-      reshape_expr e ltac:(fun K e' =>
-        rwp_bind_core K; tac H) ||
-      lazymatch iTypeOf H with
-      | Some (_,?P) => fail "wp_apply: cannot apply" P
-      end
-    | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-      reshape_expr e ltac:(fun K e' =>
-        rswp_bind_core K; tac H) ||
-      lazymatch iTypeOf H with
-      | Some (_,?P) => fail "wp_apply: cannot apply" P
-    end
-    | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-      reshape_expr e ltac:(fun K e' =>
-        twp_bind_core K; tac H) ||
-      lazymatch iTypeOf H with
-      | Some (_,?P) => fail "wp_apply: cannot apply" P
-      end
-    | _ => fail "wp_apply: not a 'wp'"
-    end).
-Tactic Notation "wp_apply" open_constr(lem) :=
-  wp_apply_core lem (fun H => iApplyHyp H; try iNext; try wp_expr_simpl).
-
-(*(** Tactic tailored for atomic triples: the first, simple one just runs
-[iAuIntro] on the goal, as atomic triples always have an atomic update as their
-premise.  The second one additionaly does some framing: it gets rid of [Hs] from
-the context, which is intended to be the non-laterable assertions that iAuIntro
-would choke on.  You get them all back in the continuation of the atomic
-operation. *)
-Tactic Notation "awp_apply" open_constr(lem) :=
-  wp_apply_core lem (fun H => iApplyHyp H; last iAuIntro).
-Tactic Notation "awp_apply" open_constr(lem) "without" constr(Hs) :=
-  wp_apply_core lem (fun H => iApply wp_frame_wand_l; iSplitL Hs; [iAccu|iApplyHyp H; last iAuIntro]).
- *)
-
-Tactic Notation "wp_alloc" ident(l) "as" constr(H) :=
-  let Htmp := iFresh in
-  let finish _ :=
-    first [intros l | fail 1 "wp_alloc:" l "not fresh"];
-      eexists; split;
-        [pm_reflexivity || fail "wp_alloc:" H "not fresh"
-        |iDestructHyp Htmp as H; wp_finish] in
-  wp_pures;
-  (** The code first tries to use allocation lemma for a single reference,
-     ie, [tac_wp_alloc] (respectively, [tac_twp_alloc]).
-     If that fails, it tries to use the lemma [tac_wp_allocN]
-     (respectively, [tac_twp_allocN]) for allocating an array.
-     Notice that we could have used the array allocation lemma also for single
-     references. However, that would produce the resource l ↦∗ [v] instead of
-     l ↦ v for single references. These are logically equivalent assertions
-     but are not equal. *)
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    let process_single _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_wp_alloc _ _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        [iSolveTC
-        |finish ()]
-    in
-    let process_array _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_wp_allocN _ _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        [idtac|iSolveTC
-         |finish ()]
-    in (process_single ()) || (process_array ())
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    let process_single _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_swp_alloc _ _ _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        finish ()
-    in
-    let process_array _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_swp_allocN _ _ _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        finish ()
-    in (process_single ()) || (process_array ())
-  | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-    let process_single _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_rwp_alloc _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        finish ()
-    in
-    let process_array _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_rwp_allocN _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-          finish ()
-    in (process_single ()) || (process_array ())
-  | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-    let process_single _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_rswp_alloc _ _ _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        [iSolveTC|finish ()]
-    in
-    let process_array _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_rswp_allocN _ _ _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        [idtac|iSolveTC
-          |finish ()]
-    in (process_single ()) || (process_array ())
-  | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-    let process_single _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_twp_alloc _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        finish ()
-    in
-    let process_array _ :=
-        first
-          [reshape_expr e ltac:(fun K e' => eapply (tac_twp_allocN _ _ _ Htmp K))
-          |fail 1 "wp_alloc: cannot find 'Alloc' in" e];
-        [idtac| finish ()]
-    in (process_single ()) || (process_array ())
-  | _ => fail "wp_alloc: not a 'wp'"
-  end.
-
-Tactic Notation "wp_alloc" ident(l) :=
-  wp_alloc l as "?".
-
-Tactic Notation "wp_load" :=
-  let solve_mapsto _ :=
-    let l := match goal with |- _ = Some (_, (?l ↦{_} _)%I) => l end in
-    iAssumptionCore || fail "wp_load: cannot find" l "↦ ?" in
-  wp_pures;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_wp_load _ _ _ _ _ K))
-      |fail 1 "wp_load: cannot find 'Load' in" e];
-    [iSolveTC
-    |solve_mapsto ()
-    |wp_finish]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_swp_load _ _ _ _ _ K))
-      |fail 1 "wp_load: cannot find 'Load' in" e];
-    [solve_mapsto ()
-    |wp_finish]
-  | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_rwp_load _ _ _ _ K))
-      |fail 1 "wp_load: cannot find 'Load' in" e];
-    [solve_mapsto ()
-    |wp_finish]
-  | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_rswp_load _ _ _ _ _ K))
-      |fail 1 "wp_load: cannot find 'Load' in" e];
-    [solve_mapsto ()
-    |wp_finish]
-  | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_twp_load _ _ _ _ K))
-      |fail 1 "wp_load: cannot find 'Load' in" e];
-    [solve_mapsto ()
-    |wp_finish]
-  | _ => fail "wp_load: not a 'wp'"
-  end.
-
-Tactic Notation "wp_store" :=
-  let solve_mapsto _ :=
-    let l := match goal with |- _ = Some (_, (?l ↦{_} _)%I) => l end in
-    iAssumptionCore || fail "wp_store: cannot find" l "↦ ?" in
-  wp_pures;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_wp_store _ _ _ _ _ _ K))
-      |fail 1 "wp_store: cannot find 'Store' in" e];
-    [iSolveTC
-    |solve_mapsto ()
-    |pm_reflexivity
-    |first [wp_seq|wp_finish]]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_swp_store _ _ _ _ _ _ K))
-      |fail 1 "wp_store: cannot find 'Store' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |first [wp_seq|wp_finish]]
-  | |- envs_entails _ (rwp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_rwp_store _ _ _ _ _ K))
-      |fail 1 "wp_store: cannot find 'Store' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |first [wp_seq|wp_finish]]
-  | |- envs_entails _ (rswp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_rswp_store _ _ _ _ _ _ K))
-      |fail 1 "wp_store: cannot find 'Store' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |first [wp_seq|wp_finish]]
-  | |- envs_entails _ (twp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_twp_store _ _ _ _ _ K))
-      |fail 1 "wp_store: cannot find 'Store' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |first [wp_seq|wp_finish]]
-  | _ => fail "wp_store: not a 'wp'"
-  end.
-
-(* TODO: refinement versions *)
-Tactic Notation "wp_cmpxchg" "as" simple_intropattern(H1) "|" simple_intropattern(H2) :=
-  let solve_mapsto _ :=
-    let l := match goal with |- _ = Some (_, (?l ↦{_} _)%I) => l end in
-    iAssumptionCore || fail "wp_cmpxchg: cannot find" l "↦ ?" in
-  wp_pures;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_wp_cmpxchg _ _ _ _ _ _ K))
-      |fail 1 "wp_cmpxchg: cannot find 'CmpXchg' in" e];
-    [iSolveTC
-    |solve_mapsto ()
-    |pm_reflexivity
-    |try solve_vals_compare_safe
-    |intros H1; wp_finish
-    |intros H2; wp_finish]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_swp_cmpxchg _ _ _ _ _ _ K))
-      |fail 1 "wp_cmpxchg: cannot find 'CmpXchg' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |try solve_vals_compare_safe
-    |intros H1; wp_finish
-    |intros H2; wp_finish]
-  | _ => fail "wp_cmpxchg: not a 'wp'"
-  end.
-
-Tactic Notation "wp_cmpxchg_fail" :=
-  let solve_mapsto _ :=
-    let l := match goal with |- _ = Some (_, (?l ↦{_} _)%I) => l end in
-    iAssumptionCore || fail "wp_cmpxchg_fail: cannot find" l "↦ ?" in
-  wp_pures;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_wp_cmpxchg_fail _ _ _ _ _ K))
-      |fail 1 "wp_cmpxchg_fail: cannot find 'CmpXchg' in" e];
-    [iSolveTC
-    |solve_mapsto ()
-    |try (simpl; congruence) (* value inequality *)
-    |try solve_vals_compare_safe
-    |wp_finish]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_swp_cmpxchg_fail _ _ _ _ _ K))
-      |fail 1 "wp_cmpxchg_fail: cannot find 'CmpXchg' in" e];
-    [solve_mapsto ()
-    |try (simpl; congruence) (* value inequality *)
-    |try solve_vals_compare_safe
-    |wp_finish]
-  | _ => fail "wp_cmpxchg_fail: not a 'wp'"
-  end.
-
-Tactic Notation "wp_cmpxchg_suc" :=
-  let solve_mapsto _ :=
-    let l := match goal with |- _ = Some (_, (?l ↦{_} _)%I) => l end in
-    iAssumptionCore || fail "wp_cmpxchg_suc: cannot find" l "↦ ?" in
-  wp_pures;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_wp_cmpxchg_suc _ _ _ _ _ _ K))
-      |fail 1 "wp_cmpxchg_suc: cannot find 'CmpXchg' in" e];
-    [iSolveTC
-    |solve_mapsto ()
-    |pm_reflexivity
-    |try (simpl; congruence) (* value equality *)
-    |try solve_vals_compare_safe
-    |wp_finish]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_swp_cmpxchg_suc _ _ _ _ _ _ K))
-      |fail 1 "wp_cmpxchg_suc: cannot find 'CmpXchg' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |try (simpl; congruence) (* value equality *)
-    |try solve_vals_compare_safe
-    |wp_finish]
-  | _ => fail "wp_cmpxchg_suc: not a 'wp'"
-  end.
-
-Tactic Notation "wp_faa" :=
-  let solve_mapsto _ :=
-    let l := match goal with |- _ = Some (_, (?l ↦{_} _)%I) => l end in
-    iAssumptionCore || fail "wp_faa: cannot find" l "↦ ?" in
-  wp_pures;
-  lazymatch goal with
-  | |- envs_entails _ (wp ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_wp_faa _ _ _ _ _ _ K))
-      |fail 1 "wp_faa: cannot find 'FAA' in" e];
-    [iSolveTC
-    |solve_mapsto ()
-    |pm_reflexivity
-    |wp_finish]
-  | |- envs_entails _ (swp ?k ?s ?E ?e ?Q) =>
-    first
-      [reshape_expr e ltac:(fun K e' => eapply (tac_swp_faa _ _ _ _ _ _ K))
-      |fail 1 "wp_faa: cannot find 'FAA' in" e];
-    [solve_mapsto ()
-    |pm_reflexivity
-    |wp_finish]
-  | _ => fail "wp_faa: not a 'wp'"
-  end.
diff --git a/theories/heap_lang/tactics.v b/theories/heap_lang/tactics.v
deleted file mode 100644
index 368f202fe40127e70e64b10c6bf0bf755bef4cab..0000000000000000000000000000000000000000
--- a/theories/heap_lang/tactics.v
+++ /dev/null
@@ -1,53 +0,0 @@
-From iris.heap_lang Require Export lang.
-Set Default Proof Using "Type".
-Import heap_lang.
-
-(** The tactic [reshape_expr e tac] decomposes the expression [e] into an
-evaluation context [K] and a subexpression [e']. It calls the tactic [tac K e']
-for each possible decomposition until [tac] succeeds. *)
-Ltac reshape_expr e tac :=
-  (* Note that the current context is spread into a list of fully-constructed
-     items [K], and a list of pairs of values [vs] (prophecy identifier and
-     resolution value) that is only non-empty if a [ResolveLCtx] item (maybe
-     having several levels) is in the process of being constructed. Note that
-     a fully-constructed item is inserted into [K] by calling [add_item], and
-     that is only the case when a non-[ResolveLCtx] item is built. When [vs]
-     is non-empty, [add_item] also wraps the item under several [ResolveLCtx]
-     constructors: one for each pair in [vs]. *)
-  let rec go K vs e :=
-    match e with
-    | _                               => lazymatch vs with [] => tac K e | _ => fail end
-    | App ?e (Val ?v)                 => add_item (AppLCtx v) vs K e
-    | App ?e1 ?e2                     => add_item (AppRCtx e1) vs K e2
-    | UnOp ?op ?e                     => add_item (UnOpCtx op) vs K e
-    | BinOp ?op ?e (Val ?v)           => add_item (BinOpLCtx op v) vs K e
-    | BinOp ?op ?e1 ?e2               => add_item (BinOpRCtx op e1) vs K e2
-    | If ?e0 ?e1 ?e2                  => add_item (IfCtx e1 e2) vs K e0
-    | Pair ?e (Val ?v)                => add_item (PairLCtx v) vs K e
-    | Pair ?e1 ?e2                    => add_item (PairRCtx e1) vs K e2
-    | Fst ?e                          => add_item FstCtx vs K e
-    | Snd ?e                          => add_item SndCtx vs K e
-    | InjL ?e                         => add_item InjLCtx vs K e
-    | InjR ?e                         => add_item InjRCtx vs K e
-    | Case ?e0 ?e1 ?e2                => add_item (CaseCtx e1 e2) vs K e0
-    | AllocN ?e (Val ?v)              => add_item (AllocNLCtx v) vs K e
-    | AllocN ?e1 ?e2                  => add_item (AllocNRCtx e1) vs K e2
-    | Load ?e                         => add_item LoadCtx vs K e
-    | Store ?e (Val ?v)               => add_item (StoreLCtx v) vs K e
-    | Store ?e1 ?e2                   => add_item (StoreRCtx e1) vs K e2
-    | CmpXchg ?e0 (Val ?v1) (Val ?v2) => add_item (CmpXchgLCtx v1 v2) vs K e0
-    | CmpXchg ?e0 ?e1 (Val ?v2)       => add_item (CmpXchgMCtx e0 v2) vs K e1
-    | CmpXchg ?e0 ?e1 ?e2             => add_item (CmpXchgRCtx e0 e1) vs K e2
-    | FAA ?e (Val ?v)                 => add_item (FaaLCtx v) vs K e
-    | FAA ?e1 ?e2                     => add_item (FaaRCtx e1) vs K e2
-    | Resolve ?ex (Val ?v1) (Val ?v2) => go K ((v1,v2) :: vs) ex
-    | Resolve ?ex ?e1 (Val ?v2)       => add_item (ResolveMCtx ex v2) vs K e1
-    | Resolve ?ex ?e1 ?e2             => add_item (ResolveRCtx ex e1) vs K e2
-    end
-  with add_item Ki vs K e :=
-    lazymatch vs with
-    | []               => go (Ki :: K) (@nil (val * val)) e
-    | (?v1,?v2) :: ?vs => add_item (ResolveLCtx Ki v1 v2) vs K e
-    end
-  in
-  go (@nil ectx_item) (@nil (val * val)) e.
diff --git a/theories/program_logic/adequacy.v b/theories/program_logic/adequacy.v
deleted file mode 100644
index 100a4b3218558267bce41b69cb00d11c686a9e9e..0000000000000000000000000000000000000000
--- a/theories/program_logic/adequacy.v
+++ /dev/null
@@ -1,283 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.algebra Require Import gmap auth agree gset coPset.
-From iris.base_logic.lib Require Import wsat.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-Import uPred.
-
-(** This file contains the adequacy statements of the Iris program logic. First we prove a number of auxilary results. *)
-
-Lemma lstep_fupd_soundness {SI} {Σ: gFunctors SI} `{TransfiniteIndex SI} `{!invPreG Σ} φ n:
-  (∀ Hinv : invG Σ, @sbi_emp_valid SI (iPropSI Σ) (>={⊤}=={⊤}=>^n ⌜φ⌝)%I) → φ.
-Proof.
-  intros Hiter. assert ((True ⊢ ⧍^n ⌜φ⌝ : iProp Σ)%I → φ) as Hlater;
-                  last (apply Hlater).
-  { intros H1. 
-    eapply pure_soundness, uPred_primitive.big_laterN_soundness, H1. 
-  }
-  apply (fupd_plain_soundness ⊤ ⊤ _)=> Hinv.
-  iPoseProof (Hiter Hinv) as "H". by iApply lstep_fupdN_plain.
-Qed.
-
-Section adequacy.
-Context {SI} {Σ: gFunctors SI} `{!irisG Λ Σ}.
-Implicit Types e : expr Λ.
-Implicit Types P Q : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types Φs : list (val Λ → iProp Σ).
-
-
-
-Notation wptp s t := ([∗ list] ef ∈ t, WP ef @ s; ⊤ {{ fork_post }})%I.
-
-Existing Instance elim_eventuallyN.
-Existing Instance elim_gstep. 
-Lemma wp_step s e1 σ1 κ κs e2 σ2 efs m Φ :
-  prim_step e1 σ1 κ e2 σ2 efs →
-  state_interp σ1 (κ ++ κs) m -∗ WP e1 @ s; ⊤ {{ Φ }} -∗ >={⊤}=={⊤}=>
-  (state_interp σ2 κs (length efs + m) ∗ WP e2 @ s; ⊤ {{ Φ }} ∗ wptp s efs).
-Proof.
-  rewrite {1}wp_unfold /wp_pre. iIntros (?) "Hσ H".
-  rewrite (val_stuck e1 σ1 κ e2 σ2 efs) //.
-  iMod ("H" $! σ1 with "Hσ") as "H". iMod "H". 
-  iDestruct "H" as (n) "H". 
-  iApply (gstepN_gstep _ _ _ (S n)). iModIntro. 
-  replace (S n) with (n + 1) by lia. iApply eventuallyN_compose. iMod "H". 
-  iMod "H" as "[% H]". iMod ("H" $! e2 σ2 efs with "[//]") as "H".
-  by iIntros "!> !> !> !>".
-Qed.
-
-Lemma wptp_step s e1 t1 t2 κ κs σ1 σ2 Φ :
-  step (e1 :: t1,σ1) κ (t2, σ2) →
-  state_interp σ1 (κ ++ κs) (length t1) -∗ WP e1 @ s; ⊤ {{ Φ }} -∗ wptp s t1 -∗
-  ∃ e2 t2', ⌜t2 = e2 :: t2'⌝ ∗
-  >={⊤}=={⊤}=> (state_interp σ2 κs (pred (length t2)) ∗ WP e2 @ s; ⊤ {{ Φ }} ∗ wptp s t2').
-Proof.
-  iIntros (Hstep) "Hσ He Ht".
-  destruct Hstep as [e1' σ1' e2' σ2' efs [|? t1'] t2' ?? Hstep]; simplify_eq/=.
-  - iExists e2', (t2' ++ efs). iSplitR; first by eauto.
-    iMod (wp_step with "Hσ He") as "(Hσ & He2 & Hefs)"; first done.
-    rewrite Nat.add_comm app_length. iFrame.
-  - iExists e, (t1' ++ e2' :: t2' ++ efs); iSplitR; first eauto.
-    iDestruct "Ht" as "(Ht1 & He1 & Ht2)".
-    iMod (wp_step with "Hσ He1") as "(Hσ & He2 & Hefs)"; first done.
-    rewrite !app_length /= !app_length.
-    replace (length t1' + S (length t2' + length efs))
-      with (length efs + (length t1' + S (length t2'))) by omega. iFrame.
-Qed.
-
-Lemma wptp_steps s n e1 t1 κs κs' t2 σ1 σ2 Φ :
-  nsteps n (e1 :: t1, σ1) κs (t2, σ2) →
-  state_interp σ1 (κs ++ κs') (length t1) -∗ WP e1 @ s; ⊤ {{ Φ }} -∗ wptp s t1
-  -∗ (>={⊤}=={⊤}=>^n
-  (∃ e2 t2', ⌜t2 = e2 :: t2'⌝ ∗
-    state_interp σ2 κs' (pred (length t2)) ∗
-    WP e2 @ s; ⊤ {{ Φ }} ∗ wptp s t2')). 
-Proof.
-  revert e1 t1 κs κs' t2 σ1 σ2; simpl.
-  induction n as [|n IH]=> e1 t1 κs κs' t2 σ1 σ2 /=.
-  { inversion_clear 1; iIntros "???"; iExists e1, t1; iFrame; eauto 10. }
-  iIntros (Hsteps) "Hσ He Ht". inversion_clear Hsteps as [|?? [t1' σ1']].
-  rewrite -(assoc_L (++)).
-  iPoseProof (wptp_step with "Hσ He Ht")  as (e1' t1'' ?) ">(Hσ & He & Ht)"; first eauto. 
-  simplify_eq. by iApply (IH with "Hσ He Ht").
-Qed.
-
-Lemma wp_safe κs m e σ Φ :
-  state_interp σ κs m -∗
-  WP e {{ Φ }} ={⊤}=∗ ⧍ ⌜is_Some (to_val e) ∨ reducible e σ⌝.
-Proof.
-  rewrite wp_unfold /wp_pre. iIntros "Hσ H".
-  destruct (to_val e) as [v|] eqn:?; first by eauto.
-  iSpecialize ("H" $! σ [] κs with "Hσ").
-  iAssert (|={⊤,∅}=> ⧍ ⌜reducible e σ⌝)%I with "[H]" as "H".
-  { iMod "H". iMod (eventually_plain with "[H]") as "H"; last by iModIntro. apply _.
-    iMod "H" as (n) "H". iModIntro. iExists (S n). replace (S n) with (n + 1)by lia. iApply eventuallyN_compose. 
-    iMod "H". by iMod "H" as "[$ _]". } 
-  iMod (fupd_plain_mask with "H") as "H"; eauto.
-  iModIntro. iMod "H" as "%". by iRight.
-Qed.
-
-Lemma list_big_later {X} (L: list X) (P: X → iProp Σ): ([∗ list] x ∈ L, ⧍ P x) ⊢ ⧍ [∗ list] x ∈ L, P x.
-Proof.
-  iInduction L as [|L] "IH"; simpl.
-  - iIntros "_". by iExists 0.
-  - iIntros "[H1 H2]". iSpecialize ("IH" with "H2").
-    iDestruct "H1" as (n1) "H1". iDestruct "IH" as (n2) "IH".
-    iExists (n1 + n2). iNext. iFrame.
-Qed.
-
-Lemma big_later_eventually P E: ⧍ P -∗ <E> P.
-Proof.
-  iDestruct 1 as (n) "H". iExists n. 
-  iModIntro. iInduction n as [ | n] "IH"; simpl; eauto. 
-  iModIntro. iNext. iModIntro. by iApply "IH". 
-Qed.
-
-Existing Instance elim_gstep_N. 
-Lemma wptp_strong_adequacy Φ κs' s n e1 t1 κs e2 t2 σ1 σ2 :
-  nsteps n (e1 :: t1, σ1) κs (t2, σ2) →
-  state_interp σ1 (κs ++ κs') (length t1) -∗
-  WP e1 @ s; ⊤ {{ Φ }} -∗
-  wptp s t1 -∗ >={⊤}=={⊤}=>^(S n) ∃ e2 t2',
-    ⌜ t2 = e2 :: t2' ⌝ ∗
-    ⌜ ∀ e2, s = NotStuck → e2 ∈ t2 → (is_Some (to_val e2) ∨ reducible e2 σ2) ⌝ ∗
-    state_interp σ2 κs' (length t2') ∗
-    from_option Φ True (to_val e2) ∗
-    ([∗ list] v ∈ omap to_val t2', fork_post v).
-Proof.
-  iIntros (Hstep) "Hσ He Ht". rewrite Nat_iter_S_r.
-  iDestruct (wptp_steps with "Hσ He Ht") as "Hwp"; first done.
-  iMod "Hwp". iDestruct "Hwp" as (e2' t2' ?) "(Hσ & Hwp & Ht)"; simplify_eq/=.
-  iMod (fupd_plain_keep_l ⊤
-    ( ⌜s = NotStuck⌝ → [∗ list] e2 ∈ (e2' :: t2'),  ⧍ ⌜(is_Some (to_val e2) ∨ reducible e2 σ2) ⌝)%I
-    (state_interp σ2 κs' (length t2') ∗ WP e2' @ s; ⊤ {{ v, Φ v }} ∗ wptp s t2')%I
-    with "[$Hσ $Hwp $Ht]") as "(Hsafe&Hσ&Hwp&Hvs)".
-  { iIntros "(Hσ & Hwp & Ht)" (->); simpl.
-    iMod (fupd_plain_keep_l ⊤ (⧍ ⌜is_Some (to_val e2') ∨ reducible e2' σ2⌝)%I
-                            (state_interp σ2 κs' (length t2') ∗ WP e2' @ ⊤ {{ v, Φ v }})%I
-            with "[$Hσ $Hwp]") as "($ & Hσ & _)".
-    { iIntros "[H1 H2]". iApply (wp_safe with "H1 H2"). }
-    clear Hstep. generalize (length t2') as l. intros l. iInduction t2' as [| e3 t3] "IH"; simpl.
-    - by iModIntro.
-    - iDestruct "Ht" as "[Hwp Ht]".
-      iMod (fupd_plain_keep_l ⊤ (⧍ ⌜is_Some (to_val e3) ∨ reducible e3 σ2⌝)%I
-                            (state_interp σ2 κs' l ∗ WP e3 {{ v, fork_post v }})%I
-            with "[$Hσ $Hwp]") as "($ & Hσ & _)".
-      { iIntros "[H1 H2]". iApply (wp_safe with "H1 H2"). }
-      iMod ("IH" with "Ht Hσ") as "$". by iModIntro. }
-  iAssert (⧍ ⌜ ∀ e2, s = NotStuck → e2 ∈ (e2' :: t2') → (is_Some (to_val e2) ∨ reducible e2 σ2) ⌝)%I with "[Hsafe]" as "Hsafe".
-  { destruct s; last (iExists 0; iIntros (? H); discriminate). iSpecialize ("Hsafe" with "[]"); eauto.
-    iMod (list_big_later with "Hsafe") as "Hsafe". iIntros (e) "_ %".
-      by iApply (big_sepL_elem_of with "Hsafe"). }
-  iMod (fupd_intro_mask') as "Hclose". apply empty_subseteq. iModIntro.
-  iApply big_later_eventually. iMod "Hsafe". iMod "Hclose" as "_".
-  iExists _, _. iSplitL ""; first done. iFrame "Hsafe Hσ".
-  iSplitL "Hwp".
-  - destruct (to_val e2') as [v2|] eqn:He2'; last done.
-    apply of_to_val in He2' as <-. iApply (wp_value_inv' with "Hwp").
-  - clear Hstep. iInduction t2' as [|e t2'] "IH"; csimpl; first by iFrame.
-    iDestruct "Hvs" as "[Hv Hvs]". destruct (to_val e) as [v|] eqn:He.
-    + apply of_to_val in He as <-. iMod (wp_value_inv' with "Hv") as "$".
-      by iApply "IH".
-    + by iApply "IH".
-Qed.
-End adequacy.
-
-Existing Instance elim_gstep_N. 
-(** Iris's generic adequacy result *)
-Theorem wp_strong_adequacy {SI} `{TransfiniteIndex SI} (Σ: gFunctors SI) Λ `{!invPreG Σ} e1 σ1 n κs t2 σ2 φ :
-  (∀ `{Hinv : !invG Σ},
-       ⊢ (|={⊤}=> ∃
-         (s: stuckness)
-         (stateI : state Λ → list (observation Λ) → nat → iProp Σ)
-         (Φ fork_post : val Λ → iProp Σ),
-       let _ : irisG Λ Σ := IrisG _ _ _ Hinv stateI fork_post in
-       stateI σ1 κs 0 ∗
-       WP e1 @ s; ⊤ {{ Φ }} ∗
-       (∀ e2 t2',
-         (* e2 is the final state of the main thread, t2' the rest *)
-         ⌜ t2 = e2 :: t2' ⌝ -∗
-         (* If this is a stuck-free triple (i.e. [s = NotStuck]), then all
-         threads in [t2] are either done (a value) or reducible *)
-         ⌜ ∀ e2, s = NotStuck → e2 ∈ t2 → (is_Some (to_val e2) ∨ reducible e2 σ2) ⌝ -∗
-         (* The state interpretation holds for [σ2] *)
-         stateI σ2 [] (length t2') -∗
-         (* If the main thread is done, its post-condition [Φ] holds *)
-         from_option Φ True (to_val e2) -∗
-         (* For all threads that are done, their postcondition [fork_post] holds. *)
-         ([∗ list] v ∈ omap to_val t2', fork_post v) -∗
-         (* Under all these assumptions, and while opening all invariants, we
-         can conclude [φ] in the logic. After opening all required invariants,
-         one can use [fupd_intro_mask'] or [fupd_mask_weaken] to introduce the
-         fancy update. *)
-         |={⊤,∅}=> ⌜ φ ⌝))%I) →
-  nsteps n ([e1], σ1) κs (t2, σ2) →
-  (* Then we can conclude [φ] at the meta-level. *)
-  φ.
-Proof.
-  intros Hwp ?.
-  eapply (@lstep_fupd_soundness _ Σ _ _ _ (S (S n) + 1))=> Hinv.
-  rewrite Nat_iter_add Nat_iter_S.
-  iMod Hwp as (s stateI Φ fork_post) "(Hσ & Hwp & Hφ)".
-  iApply lstep_intro. iModIntro. 
-  iPoseProof (@wptp_strong_adequacy _ _ _ (IrisG _ _ _ Hinv stateI fork_post) _ []
-  with "[Hσ] Hwp") as "Hpost". 1-3:eauto. by rewrite right_id_L. iSpecialize ("Hpost" with "[$]").
-  iMod "Hpost". iDestruct "Hpost" as (e2 t2' ->) "(? & ? & ? & ?)".
-  iApply lstep_intro. 
-  iApply fupd_plain_mask_empty.
-  iMod ("Hφ" with "[% //] [$] [$] [$] [$]"). done.
-Qed.
-
-(** Since the full adequacy statement is quite a mouthful, we prove some more
-intuitive and simpler corollaries. These lemmas are moreover stated in terms of
-[rtc erased_step] so one does not have to provide the trace. *)
-Record adequate {Λ} (s : stuckness) (e1 : expr Λ) (σ1 : state Λ)
-    (φ : val Λ → state Λ → Prop) := {
-  adequate_result t2 σ2 v2 :
-   rtc erased_step ([e1], σ1) (of_val v2 :: t2, σ2) → φ v2 σ2;
-  adequate_not_stuck t2 σ2 e2 :
-   s = NotStuck →
-   rtc erased_step ([e1], σ1) (t2, σ2) →
-   e2 ∈ t2 → (is_Some (to_val e2) ∨ reducible e2 σ2)
-}.
-
-Lemma adequate_alt {Λ} s e1 σ1 (φ : val Λ → state Λ → Prop) :
-  adequate s e1 σ1 φ ↔ ∀ t2 σ2,
-    rtc erased_step ([e1], σ1) (t2, σ2) →
-      (∀ v2 t2', t2 = of_val v2 :: t2' → φ v2 σ2) ∧
-      (∀ e2, s = NotStuck → e2 ∈ t2 → (is_Some (to_val e2) ∨ reducible e2 σ2)).
-Proof. split. intros []; naive_solver. constructor; naive_solver. Qed.
-
-Theorem adequate_tp_safe {Λ} (e1 : expr Λ) t2 σ1 σ2 φ :
-  adequate NotStuck e1 σ1 φ →
-  rtc erased_step ([e1], σ1) (t2, σ2) →
-  Forall (λ e, is_Some (to_val e)) t2 ∨ ∃ t3 σ3, erased_step (t2, σ2) (t3, σ3).
-Proof.
-  intros Had ?.
-  destruct (decide (Forall (λ e, is_Some (to_val e)) t2)) as [|Ht2]; [by left|].
-  apply (not_Forall_Exists _), Exists_exists in Ht2; destruct Ht2 as (e2&?&He2).
-  destruct (adequate_not_stuck NotStuck e1 σ1 φ Had t2 σ2 e2) as [?|(κ&e3&σ3&efs&?)];
-    rewrite ?eq_None_not_Some; auto.
-  { exfalso. eauto. }
-  destruct (elem_of_list_split t2 e2) as (t2'&t2''&->); auto.
-  right; exists (t2' ++ e3 :: t2'' ++ efs), σ3, κ; econstructor; eauto.
-Qed.
-
-Corollary wp_adequacy {SI} `{TransfiniteIndex SI} {Σ: gFunctors SI} Λ `{!invPreG Σ} s e σ φ :
-  (∀ `{Hinv : !invG Σ} κs,
-     sbi_emp_valid (|={⊤}=> ∃
-         (stateI : state Λ → list (observation Λ) → iProp Σ)
-         (fork_post : val Λ → iProp Σ),
-       let _ : irisG Λ Σ := IrisG _ _ _ Hinv (λ σ κs _, stateI σ κs) fork_post in
-       stateI σ κs ∗ WP e @ s; ⊤ {{ v, ⌜φ v⌝ }})%I) →
-  adequate s e σ (λ v _, φ v).
-Proof.
-  intros Hwp. apply adequate_alt; intros t2 σ2 [n [κs ?]]%erased_steps_nsteps.
-  eapply (wp_strong_adequacy Σ _); [|done]=> ?.
-  iMod Hwp as (stateI fork_post) "[Hσ Hwp]".
-  iExists s, (λ σ κs _, stateI σ κs), (λ v, ⌜φ v⌝%I), fork_post.
-  iIntros "{$Hσ $Hwp} !>" (e2 t2' -> ?) "_ H _".
-  iApply fupd_mask_weaken; [done|]. iSplit; [|done].
-  iIntros (v2 t2'' [= -> <-]). by rewrite to_of_val.
-Qed.
-
-Corollary wp_invariance {SI} `{TransfiniteIndex SI} {Σ: gFunctors SI} Λ `{!invPreG Σ} s e1 σ1 t2 σ2 φ :
-  (∀ `{Hinv : !invG Σ} κs,
-     sbi_emp_valid (|={⊤}=> ∃
-         (stateI : state Λ → list (observation Λ) → nat → iProp Σ)
-         (fork_post : val Λ → iProp Σ),
-       let _ : irisG Λ Σ := IrisG _ _ _ Hinv stateI fork_post in
-       stateI σ1 κs 0 ∗ WP e1 @ s; ⊤ {{ _, True }} ∗
-       (stateI σ2 [] (pred (length t2)) -∗ ∃ E, |={⊤,E}=> ⌜φ⌝))%I) →
-  rtc erased_step ([e1], σ1) (t2, σ2) →
-  φ.
-Proof.
-  intros Hwp [n [κs ?]]%erased_steps_nsteps.
-  eapply (wp_strong_adequacy Σ _); [|done]=> ?.
-  iMod (Hwp _ κs) as (stateI fork_post) "(Hσ & Hwp & Hφ)".
-  iExists s, stateI, (λ _, True)%I, fork_post.
-  iIntros "{$Hσ $Hwp} !>" (e2 t2' -> _) "Hσ _ _ /=".
-  iDestruct ("Hφ" with "Hσ") as (E) ">Hφ".
-  by iApply fupd_mask_weaken; first set_solver.
-Qed.
diff --git a/theories/program_logic/ectx_language.v b/theories/program_logic/ectx_language.v
deleted file mode 100644
index f687b137dbbd2f5b29d50b03de255bcc9d958565..0000000000000000000000000000000000000000
--- a/theories/program_logic/ectx_language.v
+++ /dev/null
@@ -1,265 +0,0 @@
-(** An axiomatization of evaluation-context based languages, including a proof
-    that this gives rise to a "language" in the Iris sense. *)
-From iris.algebra Require Export base.
-From iris.program_logic Require Import language.
-Set Default Proof Using "Type".
-
-(* TAKE CARE: When you define an [ectxLanguage] canonical structure for your
-language, you need to also define a corresponding [language] canonical
-structure. Use the coercion [LanguageOfEctx] as defined in the bottom of this
-file for doing that. *)
-
-Section ectx_language_mixin.
-  Context {expr val ectx state observation : Type}.
-  Context (of_val : val → expr).
-  Context (to_val : expr → option val).
-  Context (empty_ectx : ectx).
-  Context (comp_ectx : ectx → ectx → ectx).
-  Context (fill : ectx → expr → expr).
-  Context (head_step : expr → state → list observation → expr → state → list expr → Prop).
-
-  Record EctxLanguageMixin := {
-    mixin_to_of_val v : to_val (of_val v) = Some v;
-    mixin_of_to_val e v : to_val e = Some v → of_val v = e;
-    mixin_val_head_stuck e1 σ1 κ e2 σ2 efs :
-      head_step e1 σ1 κ e2 σ2 efs → to_val e1 = None;
-
-    mixin_fill_empty e : fill empty_ectx e = e;
-    mixin_fill_comp K1 K2 e : fill K1 (fill K2 e) = fill (comp_ectx K1 K2) e;
-    mixin_fill_inj K : Inj (=) (=) (fill K);
-    mixin_fill_val K e : is_Some (to_val (fill K e)) → is_Some (to_val e);
-
-    (* There are a whole lot of sensible axioms (like associativity, and left and
-    right identity, we could demand for [comp_ectx] and [empty_ectx]. However,
-    positivity suffices. *)
-    mixin_ectx_positive K1 K2 :
-      comp_ectx K1 K2 = empty_ectx → K1 = empty_ectx ∧ K2 = empty_ectx;
-
-    mixin_step_by_val K K' e1 e1' σ1 κ e2 σ2 efs :
-      fill K e1 = fill K' e1' →
-      to_val e1 = None →
-      head_step e1' σ1 κ e2 σ2 efs →
-      ∃ K'', K' = comp_ectx K K'';
-  }.
-End ectx_language_mixin.
-
-Structure ectxLanguage := EctxLanguage {
-  expr : Type;
-  val : Type;
-  ectx : Type;
-  state : Type;
-  observation : Type;
-
-  of_val : val → expr;
-  to_val : expr → option val;
-  empty_ectx : ectx;
-  comp_ectx : ectx → ectx → ectx;
-  fill : ectx → expr → expr;
-  head_step : expr → state → list observation → expr → state → list expr → Prop;
-
-  ectx_language_mixin :
-    EctxLanguageMixin of_val to_val empty_ectx comp_ectx fill head_step
-}.
-
-Arguments EctxLanguage {_ _ _ _ _ _ _ _ _ _ _} _.
-Arguments of_val {_} _%V.
-Arguments to_val {_} _%E.
-Arguments empty_ectx {_}.
-Arguments comp_ectx {_} _ _.
-Arguments fill {_} _ _%E.
-Arguments head_step {_} _%E _ _ _%E _ _.
-
-(* From an ectx_language, we can construct a language. *)
-Section ectx_language.
-  Context {Λ : ectxLanguage}.
-  Implicit Types v : val Λ.
-  Implicit Types e : expr Λ.
-  Implicit Types K : ectx Λ.
-
-  (* Only project stuff out of the mixin that is not also in language *)
-  Lemma val_head_stuck e1 σ1 κ e2 σ2 efs : head_step e1 σ1 κ e2 σ2 efs → to_val e1 = None.
-  Proof. apply ectx_language_mixin. Qed.
-  Lemma fill_empty e : fill empty_ectx e = e.
-  Proof. apply ectx_language_mixin. Qed.
-  Lemma fill_comp K1 K2 e : fill K1 (fill K2 e) = fill (comp_ectx K1 K2) e.
-  Proof. apply ectx_language_mixin. Qed.
-  Global Instance fill_inj K : Inj (=) (=) (fill K).
-  Proof. apply ectx_language_mixin. Qed.
-  Lemma fill_val K e : is_Some (to_val (fill K e)) → is_Some (to_val e).
-  Proof. apply ectx_language_mixin. Qed.
-  Lemma ectx_positive K1 K2 :
-    comp_ectx K1 K2 = empty_ectx → K1 = empty_ectx ∧ K2 = empty_ectx.
-  Proof. apply ectx_language_mixin. Qed.
-  Lemma step_by_val K K' e1 e1' σ1 κ e2 σ2 efs :
-    fill K e1 = fill K' e1' →
-    to_val e1 = None →
-    head_step e1' σ1 κ e2 σ2 efs →
-    ∃ K'', K' = comp_ectx K K''.
-  Proof. apply ectx_language_mixin. Qed.
-
-  Definition head_reducible (e : expr Λ) (σ : state Λ) :=
-    ∃ κ e' σ' efs, head_step e σ κ e' σ' efs.
-  Definition head_reducible_no_obs (e : expr Λ) (σ : state Λ) :=
-    ∃ e' σ' efs, head_step e σ [] e' σ' efs.
-  Definition head_irreducible (e : expr Λ) (σ : state Λ) :=
-    ∀ κ e' σ' efs, ¬head_step e σ κ e' σ' efs.
-  Definition head_stuck (e : expr Λ) (σ : state Λ) :=
-    to_val e = None ∧ head_irreducible e σ.
-
-  (* All non-value redexes are at the root.  In other words, all sub-redexes are
-     values. *)
-  Definition sub_redexes_are_values (e : expr Λ) :=
-    ∀ K e', e = fill K e' → to_val e' = None → K = empty_ectx.
-
-  Inductive prim_step (e1 : expr Λ) (σ1 : state Λ) (κ : list (observation Λ))
-      (e2 : expr Λ) (σ2 : state Λ) (efs : list (expr Λ)) : Prop :=
-    Ectx_step K e1' e2' :
-      e1 = fill K e1' → e2 = fill K e2' →
-      head_step e1' σ1 κ e2' σ2 efs → prim_step e1 σ1 κ e2 σ2 efs.
-
-  Lemma Ectx_step' K e1 σ1 κ e2 σ2 efs :
-    head_step e1 σ1 κ e2 σ2 efs → prim_step (fill K e1) σ1 κ (fill K e2) σ2 efs.
-  Proof. econstructor; eauto. Qed.
-
-  Definition ectx_lang_mixin : LanguageMixin of_val to_val prim_step.
-  Proof.
-    split.
-    - apply ectx_language_mixin.
-    - apply ectx_language_mixin.
-    - intros ?????? [??? -> -> ?%val_head_stuck].
-      apply eq_None_not_Some. by intros ?%fill_val%eq_None_not_Some.
-  Qed.
-
-  Canonical Structure ectx_lang : language := Language ectx_lang_mixin.
-
-  Definition head_atomic (a : atomicity) (e : expr Λ) : Prop :=
-    ∀ σ κ e' σ' efs,
-      head_step e σ κ e' σ' efs →
-      if a is WeaklyAtomic then irreducible e' σ' else is_Some (to_val e').
-
-  (* Some lemmas about this language *)
-  Lemma fill_not_val K e : to_val e = None → to_val (fill K e) = None.
-  Proof. rewrite !eq_None_not_Some. eauto using fill_val. Qed.
-
-  Lemma head_prim_step e1 σ1 κ e2 σ2 efs :
-    head_step e1 σ1 κ e2 σ2 efs → prim_step e1 σ1 κ e2 σ2 efs.
-  Proof. apply Ectx_step with empty_ectx; by rewrite ?fill_empty. Qed.
-
-  Lemma head_reducible_no_obs_reducible e σ :
-    head_reducible_no_obs e σ → head_reducible e σ.
-  Proof. intros (?&?&?&?). eexists. eauto. Qed.
-  Lemma not_head_reducible e σ : ¬head_reducible e σ ↔ head_irreducible e σ.
-  Proof. unfold head_reducible, head_irreducible. naive_solver. Qed.
-
-
-  Lemma fill_prim_step K e1 σ1 κ e2 σ2 efs :
-    prim_step e1 σ1 κ e2 σ2 efs → prim_step (fill K e1) σ1 κ (fill K e2) σ2 efs.
-  Proof.
-    destruct 1 as [K' e1' e2' -> ->].
-    rewrite !fill_comp. by econstructor.
-  Qed.
-  Lemma fill_reducible K e σ : reducible e σ → reducible (fill K e) σ.
-  Proof.
-    intros (κ&e'&σ'&efs&?). exists κ, (fill K e'), σ', efs.
-    by apply fill_prim_step.
-  Qed.
-  Lemma head_prim_reducible e σ : head_reducible e σ → reducible e σ.
-  Proof. intros (κ&e'&σ'&efs&?). eexists κ, e', σ', efs. by apply head_prim_step. Qed.
-  Lemma head_prim_fill_reducible e K σ :
-    head_reducible e σ → reducible (fill K e) σ.
-  Proof. intro. by apply fill_reducible, head_prim_reducible. Qed.
-  Lemma head_prim_reducible_no_obs e σ : head_reducible_no_obs e σ → reducible_no_obs e σ.
-  Proof. intros (e'&σ'&efs&?). eexists e', σ', efs. by apply head_prim_step. Qed.
-  Lemma head_prim_irreducible e σ : irreducible e σ → head_irreducible e σ.
-  Proof.
-    rewrite -not_reducible -not_head_reducible. eauto using head_prim_reducible.
-  Qed.
-
-  Lemma prim_head_reducible e σ :
-    reducible e σ → sub_redexes_are_values e → head_reducible e σ.
-  Proof.
-    intros (κ&e'&σ'&efs&[K e1' e2' -> -> Hstep]) ?.
-    assert (K = empty_ectx) as -> by eauto 10 using val_head_stuck.
-    rewrite fill_empty /head_reducible; eauto.
-  Qed.
-  Lemma prim_head_irreducible e σ :
-    head_irreducible e σ → sub_redexes_are_values e → irreducible e σ.
-  Proof.
-    rewrite -not_reducible -not_head_reducible. eauto using prim_head_reducible.
-  Qed.
-
-  Lemma head_stuck_stuck e σ :
-    head_stuck e σ → sub_redexes_are_values e → stuck e σ.
-  Proof.
-    intros [] ?. split; first done.
-    by apply prim_head_irreducible.
-  Qed.
-
-  Lemma ectx_language_atomic a e :
-    head_atomic a e → sub_redexes_are_values e → Atomic a e.
-  Proof.
-    intros Hatomic_step Hatomic_fill σ κ e' σ' efs [K e1' e2' -> -> Hstep].
-    assert (K = empty_ectx) as -> by eauto 10 using val_head_stuck.
-    rewrite fill_empty. eapply Hatomic_step. by rewrite fill_empty.
-  Qed.
-
-  Lemma head_reducible_prim_step e1 σ1 κ e2 σ2 efs :
-    head_reducible e1 σ1 →
-    prim_step e1 σ1 κ e2 σ2 efs →
-    head_step e1 σ1 κ e2 σ2 efs.
-  Proof.
-    intros (κ'&e2''&σ2''&efs''&?) [K e1' e2' -> -> Hstep].
-    destruct (step_by_val K empty_ectx e1' (fill K e1') σ1 κ' e2'' σ2'' efs'')
-      as [K' [-> _]%symmetry%ectx_positive];
-      eauto using fill_empty, fill_not_val, val_head_stuck.
-    by rewrite !fill_empty.
-  Qed.
-
-  (* Every evaluation context is a context. *)
-  Global Instance ectx_lang_ctx K : LanguageCtx (fill K).
-  Proof.
-    split; simpl.
-    - eauto using fill_not_val.
-    - intros ?????? [K' e1' e2' Heq1 Heq2 Hstep].
-      by exists (comp_ectx K K') e1' e2'; rewrite ?Heq1 ?Heq2 ?fill_comp.
-    - intros e1 σ1 κ e2 σ2 ? Hnval [K'' e1'' e2'' Heq1 -> Hstep].
-      destruct (step_by_val K K'' e1 e1'' σ1 κ e2'' σ2 efs) as [K' ->]; eauto.
-      rewrite -fill_comp in Heq1; apply (inj (fill _)) in Heq1.
-      exists (fill K' e2''); rewrite -fill_comp; split; auto.
-      econstructor; eauto.
-  Qed.
-
-  Record pure_head_step (e1 e2 : expr Λ) := {
-    pure_head_step_safe σ1 : head_reducible_no_obs e1 σ1;
-    pure_head_step_det σ1 κ e2' σ2 efs :
-      head_step e1 σ1 κ e2' σ2 efs → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs = []
-  }.
-
-  Lemma pure_head_step_pure_step e1 e2 : pure_head_step e1 e2 → pure_step e1 e2.
-  Proof.
-    intros [Hp1 Hp2]. split.
-    - intros σ. destruct (Hp1 σ) as (e2' & σ2 & efs & ?).
-      eexists e2', σ2, efs. by apply head_prim_step.
-    - intros σ1 κ e2' σ2 efs ?%head_reducible_prim_step; eauto using head_reducible_no_obs_reducible.
-  Qed.
-
-  Global Instance pure_exec_fill K φ n e1 e2 :
-    PureExec φ n e1 e2 →
-    PureExec φ n (fill K e1) (fill K e2).
-  Proof. apply: pure_exec_ctx. Qed.
-End ectx_language.
-
-Arguments ectx_lang : clear implicits.
-Coercion ectx_lang : ectxLanguage >-> language.
-
-(* This definition makes sure that the fields of the [language] record do not
-refer to the projections of the [ectxLanguage] record but to the actual fields
-of the [ectxLanguage] record. This is crucial for canonical structure search to
-work.
-
-Note that this trick no longer works when we switch to canonical projections
-because then the pattern match [let '...] will be desugared into projections. *)
-Definition LanguageOfEctx (Λ : ectxLanguage) : language :=
-  let '@EctxLanguage E V C St K of_val to_val empty comp fill head mix := Λ in
-  @Language E V St K of_val to_val _
-    (@ectx_lang_mixin (@EctxLanguage E V C St K of_val to_val empty comp fill head mix)).
diff --git a/theories/program_logic/ectx_lifting.v b/theories/program_logic/ectx_lifting.v
deleted file mode 100644
index 571315485b3d93e8ea271841e65d839c6d5d4df3..0000000000000000000000000000000000000000
--- a/theories/program_logic/ectx_lifting.v
+++ /dev/null
@@ -1,178 +0,0 @@
-(** Some derived lemmas for ectx-based languages *)
-From iris.program_logic Require Export ectx_language weakestpre lifting.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-Section wp.
-Context {SI} {Σ: gFunctors SI} {Λ : ectxLanguage} `{!irisG Λ Σ} {Hinh : Inhabited (state Λ)}.
-Implicit Types s : stuckness.
-Implicit Types P : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-Hint Resolve head_prim_reducible head_reducible_prim_step : core.
-Hint Resolve (reducible_not_val _ inhabitant) : core.
-Hint Resolve head_stuck_stuck : core.
-
-Lemma wp_lift_head_step_fupd {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E,∅}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={∅,∅,E}▷=∗
-      state_interp σ2 κs (length efs + n) ∗
-      WP e2 @ s; E {{ Φ }} ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_step_fupd=>//. iIntros (σ1 κ κs Qs) "Hσ".
-  iMod ("H" with "Hσ") as "[% H]"; iModIntro.
-  iSplit; first by destruct s; eauto. iIntros (e2 σ2 efs ?).
-  iApply "H"; eauto.
-Qed.
-
-Lemma wp_lift_head_step {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E,∅}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      WP e2 @ s; E {{ Φ }} ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_head_step_fupd; [done|]. iIntros (????) "?".
-  iMod ("H" with "[$]") as "[$ H]". iIntros "!>" (e2 σ2 efs ?) "!> !>". by iApply "H".
-Qed.
-
-Lemma wp_lift_head_stuck E Φ e :
-  to_val e = None →
-  sub_redexes_are_values e →
-  (∀ σ κs n, state_interp σ κs n ={E,∅}=∗ ⌜head_stuck e σ⌝)
-  ⊢ WP e @ E ?{{ Φ }}.
-Proof.
-  iIntros (??) "H". iApply wp_lift_stuck; first done.
-  iIntros (σ κs n) "Hσ". iMod ("H" with "Hσ") as "%". by auto.
-Qed.
-
-Lemma wp_lift_pure_head_stuck E Φ e :
-  to_val e = None →
-  sub_redexes_are_values e →
-  (∀ σ, head_stuck e σ) →
-  WP e @ E ?{{ Φ }}%I.
-Proof.
-  iIntros (?? Hstuck). iApply wp_lift_head_stuck; [done|done|].
-  iIntros (σ κs n) "_". iMod (fupd_intro_mask' E ∅) as "_"; first set_solver.
-  by auto.
-Qed.
-
-Lemma wp_lift_atomic_head_step_fupd {s E1 E2 Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E1}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E1,E2}▷=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E1 {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_atomic_step_fupd; [done|].
-  iIntros (σ1 κ κs Qs) "Hσ1". iMod ("H" with "Hσ1") as "[% H]"; iModIntro.
-  iSplit; first by destruct s; auto. iIntros (e2 σ2 efs Hstep).
-  iApply "H"; eauto.
-Qed.
-
-Lemma wp_lift_atomic_head_step {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_atomic_step; eauto.
-  iIntros (σ1 κ κs Qs) "Hσ1". iMod ("H" with "Hσ1") as "[% H]"; iModIntro.
-  iSplit; first by destruct s; auto. iNext. iIntros (e2 σ2 efs Hstep).
-  iApply "H"; eauto.
-Qed.
-
-Lemma swp_lift_atomic_head_step {k s E Φ} e1 :
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros "H". iApply swp_lift_atomic_step; eauto.
-  iIntros (σ1 κ κs Qs) "Hσ1". iMod ("H" with "Hσ1") as "[% H]"; iModIntro.
-  iSplit; first by destruct s; auto. iNext. iIntros (e2 σ2 efs Hstep).
-  iApply "H"; eauto.
-Qed.
-
-Lemma wp_lift_atomic_head_step_no_fork_fupd {s E1 E2 Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E1}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E1,E2}▷=∗
-      ⌜efs = []⌝ ∗ state_interp σ2 κs n ∗ from_option Φ False (to_val e2))
-  ⊢ WP e1 @ s; E1 {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_atomic_head_step_fupd; [done|].
-  iIntros (σ1 κ κs Qs) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "[$ H]"; iModIntro.
-  iIntros (v2 σ2 efs Hstep).
-  iMod ("H" $! v2 σ2 efs with "[# //]") as "H".
-  iIntros "!> !>". iMod "H" as "(-> & ? & ?) /=". by iFrame.
-Qed.
-
-Lemma wp_lift_atomic_head_step_no_fork {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ⌜efs = []⌝ ∗ state_interp σ2 κs n ∗ from_option Φ False (to_val e2))
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_atomic_head_step; eauto.
-  iIntros (σ1 κ κs Qs) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "[$ H]"; iModIntro.
-  iNext; iIntros (v2 σ2 efs Hstep).
-  iMod ("H" $! v2 σ2 efs with "[//]") as "(-> & ? & ?) /=". by iFrame.
-Qed.
-
-Lemma swp_lift_atomic_head_step_no_fork {k s E Φ} e1 :
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E}=∗
-    ⌜head_reducible e1 σ1⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ⌜efs = []⌝ ∗ state_interp σ2 κs n ∗ from_option Φ False (to_val e2))
-  ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros "H". iApply swp_lift_atomic_head_step; eauto.
-  iIntros (σ1 κ κs Qs) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "[$ H]"; iModIntro.
-  iNext; iIntros (v2 σ2 efs Hstep).
-  iMod ("H" $! v2 σ2 efs with "[//]") as "(-> & ? & ?) /=". by iFrame.
-Qed.
-
-Lemma wp_lift_pure_det_head_step_no_fork {s E E' Φ} e1 e2 :
-  to_val e1 = None →
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs',
-    head_step e1 σ1 κ e2' σ2 efs' → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (|={E,E'}▷=> WP e2 @ s; E {{ Φ }}) ⊢ WP e1 @ s; E {{ Φ }}.
-Proof using Hinh.
-  intros. rewrite -(wp_lift_pure_det_step_no_fork e1 e2); eauto.
-  destruct s; by auto.
-Qed.
-
-Lemma wp_lift_pure_det_head_step_no_fork' {s E Φ} e1 e2 :
-  to_val e1 = None →
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs',
-    head_step e1 σ1 κ e2' σ2 efs' → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  ▷ WP e2 @ s; E {{ Φ }} ⊢ WP e1 @ s; E {{ Φ }}.
-Proof using Hinh.
-  intros. rewrite -[(WP e1 @ s; _ {{ _ }})%I]wp_lift_pure_det_head_step_no_fork //.
-  rewrite -step_fupd_intro //.
-Qed.
-End wp.
diff --git a/theories/program_logic/ectxi_language.v b/theories/program_logic/ectxi_language.v
deleted file mode 100644
index a8e3807d7c275e14b8704f0bd0c03a04f0efb1f9..0000000000000000000000000000000000000000
--- a/theories/program_logic/ectxi_language.v
+++ /dev/null
@@ -1,156 +0,0 @@
-(** An axiomatization of languages based on evaluation context items, including
-    a proof that these are instances of general ectx-based languages. *)
-From iris.algebra Require Export base.
-From iris.program_logic Require Import language ectx_language.
-Set Default Proof Using "Type".
-
-(* TAKE CARE: When you define an [ectxiLanguage] canonical structure for your
-language, you need to also define a corresponding [language] and [ectxLanguage]
-canonical structure for canonical structure inference to work properly. You
-should use the coercion [EctxLanguageOfEctxi] and [LanguageOfEctx] for that, and
-not [ectxi_lang] and [ectxi_lang_ectx], otherwise the canonical projections will
-not point to the right terms.
-
-A full concrete example of setting up your language can be found in [heap_lang].
-Below you can find the relevant parts:
-
-  Module heap_lang.
-    (* Your language definition *)
-
-    Lemma heap_lang_mixin : EctxiLanguageMixin of_val to_val fill_item head_step.
-    Proof. (* ... *) Qed.
-  End heap_lang.
-
-  Canonical Structure heap_ectxi_lang := EctxiLanguage heap_lang.heap_lang_mixin.
-  Canonical Structure heap_ectx_lang := EctxLanguageOfEctxi heap_ectxi_lang.
-  Canonical Structure heap_lang := LanguageOfEctx heap_ectx_lang.
-*)
-
-Section ectxi_language_mixin.
-  Context {expr val ectx_item state observation : Type}.
-  Context (of_val : val → expr).
-  Context (to_val : expr → option val).
-  Context (fill_item : ectx_item → expr → expr).
-  Context (head_step : expr → state → list observation → expr → state → list expr → Prop).
-
-  Record EctxiLanguageMixin := {
-    mixin_to_of_val v : to_val (of_val v) = Some v;
-    mixin_of_to_val e v : to_val e = Some v → of_val v = e;
-    mixin_val_stuck e1 σ1 κ e2 σ2 efs : head_step e1 σ1 κ e2 σ2 efs → to_val e1 = None;
-
-    mixin_fill_item_inj Ki : Inj (=) (=) (fill_item Ki);
-    mixin_fill_item_val Ki e : is_Some (to_val (fill_item Ki e)) → is_Some (to_val e);
-    mixin_fill_item_no_val_inj Ki1 Ki2 e1 e2 :
-      to_val e1 = None → to_val e2 = None →
-      fill_item Ki1 e1 = fill_item Ki2 e2 → Ki1 = Ki2;
-
-    mixin_head_ctx_step_val Ki e σ1 κ e2 σ2 efs :
-      head_step (fill_item Ki e) σ1 κ e2 σ2 efs → is_Some (to_val e);
-  }.
-End ectxi_language_mixin.
-
-Structure ectxiLanguage := EctxiLanguage {
-  expr : Type;
-  val : Type;
-  ectx_item : Type;
-  state : Type;
-  observation : Type;
-
-  of_val : val → expr;
-  to_val : expr → option val;
-  fill_item : ectx_item → expr → expr;
-  head_step : expr → state → list observation → expr → state → list expr → Prop;
-
-  ectxi_language_mixin :
-    EctxiLanguageMixin of_val to_val fill_item head_step
-}.
-
-Arguments EctxiLanguage {_ _ _ _ _ _ _ _ _} _.
-Arguments of_val {_} _%V.
-Arguments to_val {_} _%E.
-Arguments fill_item {_} _ _%E.
-Arguments head_step {_} _%E _ _ _%E _ _.
-
-Section ectxi_language.
-  Context {Λ : ectxiLanguage}.
-  Implicit Types (e : expr Λ) (Ki : ectx_item Λ).
-  Notation ectx := (list (ectx_item Λ)).
-
-  (* Only project stuff out of the mixin that is not also in ectxLanguage *)
-  Global Instance fill_item_inj Ki : Inj (=) (=) (fill_item Ki).
-  Proof. apply ectxi_language_mixin. Qed.
-  Lemma fill_item_val Ki e : is_Some (to_val (fill_item Ki e)) → is_Some (to_val e).
-  Proof. apply ectxi_language_mixin. Qed.
-  Lemma fill_item_no_val_inj Ki1 Ki2 e1 e2 :
-    to_val e1 = None → to_val e2 = None →
-    fill_item Ki1 e1 = fill_item Ki2 e2 → Ki1 = Ki2.
-  Proof. apply ectxi_language_mixin. Qed.
-  Lemma head_ctx_step_val Ki e σ1 κ e2 σ2 efs :
-    head_step (fill_item Ki e) σ1 κ e2 σ2 efs → is_Some (to_val e).
-  Proof. apply ectxi_language_mixin. Qed.
-
-  Definition fill (K : ectx) (e : expr Λ) : expr Λ := foldl (flip fill_item) e K.
-
-  Lemma fill_app (K1 K2 : ectx) e : fill (K1 ++ K2) e = fill K2 (fill K1 e).
-  Proof. apply foldl_app. Qed.
-
-  Lemma fill_cons Ki (K2 : ectx) e : fill (Ki :: K2) e = fill K2 (fill_item Ki e).
-  Proof. replace (Ki :: K2) with ([Ki] ++ K2) by auto. rewrite fill_app //. Qed.
-
-  Definition ectxi_lang_ectx_mixin :
-    EctxLanguageMixin of_val to_val [] (flip (++)) fill head_step.
-  Proof.
-    assert (fill_val : ∀ K e, is_Some (to_val (fill K e)) → is_Some (to_val e)).
-    { intros K. induction K as [|Ki K IH]=> e //=. by intros ?%IH%fill_item_val. }
-    assert (fill_not_val : ∀ K e, to_val e = None → to_val (fill K e) = None).
-    { intros K e. rewrite !eq_None_not_Some. eauto. }
-    split.
-    - apply ectxi_language_mixin.
-    - apply ectxi_language_mixin.
-    - apply ectxi_language_mixin.
-    - done.
-    - intros K1 K2 e. by rewrite /fill /= foldl_app.
-    - intros K; induction K as [|Ki K IH]; rewrite /Inj; naive_solver.
-    - done.
-    - by intros [] [].
-    - intros K K' e1 κ e1' σ1 e2 σ2 efs Hfill Hred Hstep; revert K' Hfill.
-      induction K as [|Ki K IH] using rev_ind=> /= K' Hfill; eauto using app_nil_r.
-      destruct K' as [|Ki' K' _] using @rev_ind; simplify_eq/=.
-      { rewrite fill_app in Hstep. apply head_ctx_step_val in Hstep.
-        apply fill_val in Hstep. by apply not_eq_None_Some in Hstep. }
-      rewrite !fill_app /= in Hfill.
-      assert (Ki = Ki') as ->.
-      { eapply fill_item_no_val_inj, Hfill; eauto using val_head_stuck.
-        apply fill_not_val. revert Hstep. apply ectxi_language_mixin. }
-      simplify_eq. destruct (IH K') as [K'' ->]; auto.
-      exists K''. by rewrite assoc.
-  Qed.
-
-  Canonical Structure ectxi_lang_ectx := EctxLanguage ectxi_lang_ectx_mixin.
-  Canonical Structure ectxi_lang := LanguageOfEctx ectxi_lang_ectx.
-
-  Lemma fill_not_val K e : to_val e = None → to_val (fill K e) = None.
-  Proof. rewrite !eq_None_not_Some. eauto using fill_val. Qed.
-
-  Lemma ectxi_language_sub_redexes_are_values e :
-    (∀ Ki e', e = fill_item Ki e' → is_Some (to_val e')) →
-    sub_redexes_are_values e.
-  Proof.
-    intros Hsub K e' ->. destruct K as [|Ki K _] using @rev_ind=> //=.
-    intros []%eq_None_not_Some. eapply fill_val, Hsub. by rewrite /= fill_app.
-  Qed.
-
-  Global Instance ectxi_lang_ctx_item Ki : LanguageCtx (fill_item Ki).
-  Proof. change (LanguageCtx (fill [Ki])). apply _. Qed.
-End ectxi_language.
-
-Arguments fill {_} _ _%E.
-Arguments ectxi_lang_ectx : clear implicits.
-Arguments ectxi_lang : clear implicits.
-Coercion ectxi_lang_ectx : ectxiLanguage >-> ectxLanguage.
-Coercion ectxi_lang : ectxiLanguage >-> language.
-
-Definition EctxLanguageOfEctxi (Λ : ectxiLanguage) : ectxLanguage :=
-  let '@EctxiLanguage E V C St K of_val to_val fill head mix := Λ in
-  @EctxLanguage E V (list C) St K of_val to_val _ _ _ _
-    (@ectxi_lang_ectx_mixin (@EctxiLanguage E V C St K of_val to_val fill head mix)).
diff --git a/theories/program_logic/hoare.v b/theories/program_logic/hoare.v
deleted file mode 100644
index 4e03f84bc6b70ff78f07221a402d699d796bb762..0000000000000000000000000000000000000000
--- a/theories/program_logic/hoare.v
+++ /dev/null
@@ -1,162 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.base_logic.lib Require Export viewshifts.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-Definition ht {SI} `{!@irisG Λ SI Σ} (s : stuckness) (E : coPset) (P : iProp Σ)
-    (e : expr Λ) (Φ : val Λ → iProp Σ) : iProp Σ :=
-  (□ (P -∗ WP e @ s; E {{ Φ }}))%I.
-Instance: Params (@ht) 6 := {}.
-
-Notation "{{ P } } e @ s ; E {{ Φ } }" := (ht s E P%I e%E Φ%I)
-  (at level 20, P, e, Φ at level 200,
-   format "{{  P  } }  e  @  s ;  E  {{  Φ  } }") : stdpp_scope.
-Notation "{{ P } } e @ E {{ Φ } }" := (ht NotStuck E P%I e%E Φ%I)
-  (at level 20, P, e, Φ at level 200,
-   format "{{  P  } }  e  @  E  {{  Φ  } }") : stdpp_scope.
-Notation "{{ P } } e @ E ? {{ Φ } }" := (ht MaybeStuck E P%I e%E Φ%I)
-  (at level 20, P, e, Φ at level 200,
-   format "{{  P  } }  e  @  E  ? {{  Φ  } }") : stdpp_scope.
-Notation "{{ P } } e {{ Φ } }" := (ht NotStuck ⊤ P%I e%E Φ%I)
-  (at level 20, P, e, Φ at level 200,
-   format "{{  P  } }  e  {{  Φ  } }") : stdpp_scope.
-Notation "{{ P } } e ? {{ Φ } }" := (ht MaybeStuck ⊤ P%I e%E Φ%I)
-  (at level 20, P, e, Φ at level 200,
-   format "{{  P  } }  e  ? {{  Φ  } }") : stdpp_scope.
-
-Notation "{{ P } } e @ s ; E {{ v , Q } }" := (ht s E P%I e%E (λ v, Q)%I)
-  (at level 20, P, e, Q at level 200,
-   format "{{  P  } }  e  @  s ;  E  {{  v ,  Q  } }") : stdpp_scope.
-Notation "{{ P } } e @ E {{ v , Q } }" := (ht NotStuck E P%I e%E (λ v, Q)%I)
-  (at level 20, P, e, Q at level 200,
-   format "{{  P  } }  e  @  E  {{  v ,  Q  } }") : stdpp_scope.
-Notation "{{ P } } e @ E ? {{ v , Q } }" := (ht MaybeStuck E P%I e%E (λ v, Q)%I)
-  (at level 20, P, e, Q at level 200,
-   format "{{  P  } }  e  @  E  ? {{  v ,  Q  } }") : stdpp_scope.
-Notation "{{ P } } e {{ v , Q } }" := (ht NotStuck ⊤ P%I e%E (λ v, Q)%I)
-  (at level 20, P, e, Q at level 200,
-   format "{{  P  } }  e  {{  v ,  Q  } }") : stdpp_scope.
-Notation "{{ P } } e ? {{ v , Q } }" := (ht MaybeStuck ⊤ P%I e%E (λ v, Q)%I)
-  (at level 20, P, e, Q at level 200,
-   format "{{  P  } }  e  ? {{  v ,  Q  } }") : stdpp_scope.
-
-Section hoare.
-Context {SI} `{!@irisG Λ SI Σ}.
-Implicit Types s : stuckness.
-Implicit Types P Q : iProp Σ.
-Implicit Types Φ Ψ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Import uPred.
-
-Global Instance ht_ne s E n :
-  Proper (dist n ==> eq ==> pointwise_relation _ (dist n) ==> dist n) (ht s E).
-Proof. solve_proper. Qed.
-Global Instance ht_proper s E :
-  Proper ((≡) ==> eq ==> pointwise_relation _ (≡) ==> (≡)) (ht s E).
-Proof. solve_proper. Qed.
-Lemma ht_mono s E P P' Φ Φ' e :
-  (P ⊢ P') → (∀ v, Φ' v ⊢ Φ v) → {{ P' }} e @ s; E {{ Φ' }} ⊢ {{ P }} e @ s; E {{ Φ }}.
-Proof. by intros; apply affinely_mono, persistently_mono, wand_mono, wp_mono. Qed.
-Lemma ht_stuck_mono s1 s2 E P Φ e :
-  s1 ⊑ s2 → {{ P }} e @ s1; E {{ Φ }} ⊢ {{ P }} e @ s2; E {{ Φ }}.
-Proof. by intros; apply affinely_mono, persistently_mono, wand_mono, wp_stuck_mono. Qed.
-Global Instance ht_mono' s E :
-  Proper (flip (⊢) ==> eq ==> pointwise_relation _ (⊢) ==> (⊢)) (ht s E).
-Proof. solve_proper. Qed.
-
-Lemma ht_alt s E P Φ e : (P ⊢ WP e @ s; E {{ Φ }}) → {{ P }} e @ s; E {{ Φ }}.
-Proof. iIntros (Hwp) "!# HP". by iApply Hwp. Qed.
-
-Lemma ht_val s E v : {{ True }} of_val v @ s; E {{ v', ⌜v = v'⌝ }}.
-Proof. iIntros "!# _". by iApply wp_value'. Qed.
-
-Lemma ht_vs s E P P' Φ Φ' e :
-  (P ={E}=> P') ∧ {{ P' }} e @ s; E {{ Φ' }} ∧ (∀ v, Φ' v ={E}=> Φ v)
-  ⊢ {{ P }} e @ s; E {{ Φ }}.
-Proof.
-  iIntros "(#Hvs & #Hwp & #HΦ) !# HP". iMod ("Hvs" with "HP") as "HP".
-  iApply wp_fupd. iApply (wp_wand with "(Hwp HP)").
-  iIntros (v) "Hv". by iApply "HΦ".
-Qed.
-
-Lemma ht_atomic s E1 E2 P P' Φ Φ' e `{!Atomic StronglyAtomic e} :
-  (P ={E1,E2}=> P') ∧ {{ P' }} e @ s; E2 {{ Φ' }} ∧ (∀ v, Φ' v ={E2,E1}=> Φ v)
-  ⊢ {{ P }} e @ s; E1 {{ Φ }}.
-Proof.
-  iIntros "(#Hvs & #Hwp & #HΦ) !# HP". iApply (wp_atomic  _ E2); auto.
-  iMod ("Hvs" with "HP") as "HP". iModIntro.
-  iApply (wp_wand with "(Hwp HP)").
-  iIntros (v) "Hv". by iApply "HΦ".
-Qed.
-
-Lemma ht_bind `{!LanguageCtx K} s E P Φ Φ' e :
-  {{ P }} e @ s; E {{ Φ }} ∧ (∀ v, {{ Φ v }} K (of_val v) @ s; E {{ Φ' }})
-  ⊢ {{ P }} K e @ s; E {{ Φ' }}.
-Proof.
-  iIntros "[#Hwpe #HwpK] !# HP". iApply wp_bind.
-  iApply (wp_wand with "(Hwpe HP)").
-  iIntros (v) "Hv". by iApply "HwpK".
-Qed.
-
-Lemma ht_stuck_weaken s E P Φ e :
-  {{ P }} e @ s; E {{ Φ }} ⊢ {{ P }} e @ E ?{{ Φ }}.
-Proof.
-  by iIntros "#Hwp !# ?"; iApply wp_stuck_weaken; iApply "Hwp".
-Qed.
-
-Lemma ht_mask_weaken s E1 E2 P Φ e :
-  E1 ⊆ E2 → {{ P }} e @ s; E1 {{ Φ }} ⊢ {{ P }} e @ s; E2 {{ Φ }}.
-Proof.
-  iIntros (?) "#Hwp !# HP". iApply (wp_mask_mono _ E1 E2); try done.
-  by iApply "Hwp".
-Qed.
-
-Lemma ht_frame_l s E P Φ R e :
-  {{ P }} e @ s; E {{ Φ }} ⊢ {{ R ∗ P }} e @ s; E {{ v, R ∗ Φ v }}.
-Proof. iIntros "#Hwp !# [$ HP]". by iApply "Hwp". Qed.
-
-Lemma ht_frame_r s E P Φ R e :
-  {{ P }} e @ s; E {{ Φ }} ⊢ {{ P ∗ R }} e @ s; E {{ v, Φ v ∗ R }}.
-Proof. iIntros "#Hwp !# [HP $]". by iApply "Hwp". Qed.
-
-Lemma ht_frame_step_l s E1 E2 P R1 R2 e Φ :
-  to_val e = None → E2 ⊆ E1 →
-  (R1 ={E1,E2}=> ▷ |={E2,E1}=> R2) ∧ {{ P }} e @ s; E2 {{ Φ }}
-  ⊢ {{ R1 ∗ P }} e @ s; E1 {{ λ v, R2 ∗ Φ v }}.
-Proof.
-  iIntros (??) "[#Hvs #Hwp] !# [HR HP]".
-  iApply (wp_frame_step_l _ E1 E2); try done.
-  iSplitL "HR"; [by iApply "Hvs"|by iApply "Hwp"].
-Qed.
-
-Lemma ht_frame_step_r s E1 E2 P R1 R2 e Φ :
-  to_val e = None → E2 ⊆ E1 →
-  (R1 ={E1,E2}=> ▷ |={E2,E1}=> R2) ∧ {{ P }} e @ s; E2 {{ Φ }}
-  ⊢ {{ P ∗ R1 }} e @ s; E1 {{ λ v, Φ v ∗ R2 }}.
-Proof.
-  iIntros (??) "[#Hvs #Hwp] !# [HP HR]".
-  iApply (wp_frame_step_r _ E1 E2); try done.
-  iSplitR "HR"; [by iApply "Hwp"|by iApply "Hvs"].
-Qed.
-
-Lemma ht_frame_step_l' s E P R e Φ :
-  to_val e = None →
-  {{ P }} e @ s; E {{ Φ }} ⊢ {{ ▷ R ∗ P }} e @ s; E {{ v, R ∗ Φ v }}.
-Proof.
-  iIntros (?) "#Hwp !# [HR HP]".
-  iApply wp_frame_step_l'; try done. iFrame "HR". by iApply "Hwp".
-Qed.
-
-Lemma ht_frame_step_r' s E P Φ R e :
-  to_val e = None →
-  {{ P }} e @ s; E {{ Φ }} ⊢ {{ P ∗ ▷ R }} e @ s; E {{ v, Φ v ∗ R }}.
-Proof.
-  iIntros (?) "#Hwp !# [HP HR]".
-  iApply wp_frame_step_r'; try done. iFrame "HR". by iApply "Hwp".
-Qed.
-
-Lemma ht_exists (T : Type) s E (P : T → iProp Σ) Φ e :
-  (∀ x, {{ P x }} e @ s; E {{ Φ }}) ⊢ {{ ∃ x, P x }} e @ s; E {{ Φ }}.
-Proof. iIntros "#HT !# HP". iDestruct "HP" as (x) "HP". by iApply "HT". Qed.
-
-End hoare.
diff --git a/theories/program_logic/language.v b/theories/program_logic/language.v
deleted file mode 100644
index e8862d4915a17e2911931f1f53774aabcfc0a12f..0000000000000000000000000000000000000000
--- a/theories/program_logic/language.v
+++ /dev/null
@@ -1,234 +0,0 @@
-From iris.algebra Require Export ofe.
-Set Default Proof Using "Type".
-
-Section language_mixin.
-  Context {expr val state observation : Type}.
-  Context (of_val : val → expr).
-  Context (to_val : expr → option val).
-  (** We annotate the reduction relation with observations [κ], which we will
-     use in the definition of weakest preconditions to predict future
-     observations and assert correctness of the predictions. *)
-  Context (prim_step : expr → state → list observation → expr → state → list expr → Prop).
-
-  Record LanguageMixin := {
-    mixin_to_of_val v : to_val (of_val v) = Some v;
-    mixin_of_to_val e v : to_val e = Some v → of_val v = e;
-    mixin_val_stuck e σ κ e' σ' efs : prim_step e σ κ e' σ' efs → to_val e = None
-  }.
-End language_mixin.
-
-Structure language := Language {
-  expr : Type;
-  val : Type;
-  state : Type;
-  observation : Type;
-  of_val : val → expr;
-  to_val : expr → option val;
-  prim_step : expr → state → list observation → expr → state → list expr → Prop;
-  language_mixin : LanguageMixin of_val to_val prim_step
-}.
-Delimit Scope expr_scope with E.
-Delimit Scope val_scope with V.
-Bind Scope expr_scope with expr.
-Bind Scope val_scope with val.
-
-Arguments Language {_ _ _ _ _ _ _} _.
-Arguments of_val {_} _.
-Arguments to_val {_} _.
-Arguments prim_step {_} _ _ _ _ _ _.
-
-Canonical Structure stateO (SI: indexT) Λ  : ofeT SI := leibnizO SI (state Λ).
-Canonical Structure valO (SI: indexT) Λ  : ofeT SI := leibnizO SI (val Λ).
-Canonical Structure exprO (SI: indexT) Λ : ofeT SI := leibnizO SI (expr Λ).
-
-Definition cfg (Λ : language) := (list (expr Λ) * state Λ)%type.
-
-Class LanguageCtx {Λ : language} (K : expr Λ → expr Λ) := {
-  fill_not_val e :
-    to_val e = None → to_val (K e) = None;
-  fill_step e1 σ1 κ e2 σ2 efs :
-    prim_step e1 σ1 κ e2 σ2 efs →
-    prim_step (K e1) σ1 κ (K e2) σ2 efs;
-  fill_step_inv e1' σ1 κ e2 σ2 efs :
-    to_val e1' = None → prim_step (K e1') σ1 κ e2 σ2 efs →
-    ∃ e2', e2 = K e2' ∧ prim_step e1' σ1 κ e2' σ2 efs
-}.
-
-Instance language_ctx_id Λ : LanguageCtx (@id (expr Λ)).
-Proof. constructor; naive_solver. Qed.
-
-Inductive atomicity := StronglyAtomic | WeaklyAtomic.
-
-Section language.
-  Context {Λ : language}.
-  Implicit Types v : val Λ.
-  Implicit Types e : expr Λ.
-
-  Lemma to_of_val v : to_val (of_val v) = Some v.
-  Proof. apply language_mixin. Qed.
-  Lemma of_to_val e v : to_val e = Some v → of_val v = e.
-  Proof. apply language_mixin. Qed.
-  Lemma val_stuck e σ κ e' σ' efs : prim_step e σ κ e' σ' efs → to_val e = None.
-  Proof. apply language_mixin. Qed.
-
-  Definition reducible (e : expr Λ) (σ : state Λ) :=
-    ∃ κ e' σ' efs, prim_step e σ κ e' σ' efs.
-  (* Total WP only permits reductions without observations *)
-  Definition reducible_no_obs (e : expr Λ) (σ : state Λ) :=
-    ∃ e' σ' efs, prim_step e σ [] e' σ' efs.
-  Definition irreducible (e : expr Λ) (σ : state Λ) :=
-    ∀ κ e' σ' efs, ¬prim_step e σ κ e' σ' efs.
-  Definition stuck (e : expr Λ) (σ : state Λ) :=
-    to_val e = None ∧ irreducible e σ.
-
-  (* [Atomic WeaklyAtomic]: This (weak) form of atomicity is enough to open
-     invariants when WP ensures safety, i.e., programs never can get stuck.  We
-     have an example in lambdaRust of an expression that is atomic in this
-     sense, but not in the stronger sense defined below, and we have to be able
-     to open invariants around that expression.  See `CasStuckS` in
-     [lambdaRust](https://gitlab.mpi-sws.org/FP/LambdaRust-coq/blob/master/theories/lang/lang.v).
-
-     [Atomic StronglyAtomic]: To open invariants with a WP that does not ensure
-     safety, we need a stronger form of atomicity.  With the above definition,
-     in case `e` reduces to a stuck non-value, there is no proof that the
-     invariants have been established again. *)
-  Class Atomic (a : atomicity) (e : expr Λ) : Prop :=
-    atomic σ e' κ σ' efs :
-      prim_step e σ κ e' σ' efs →
-      if a is WeaklyAtomic then irreducible e' σ' else is_Some (to_val e').
-
-  Inductive step (ρ1 : cfg Λ) (κ : list (observation Λ)) (ρ2 : cfg Λ) : Prop :=
-    | step_atomic e1 σ1 e2 σ2 efs t1 t2 :
-       ρ1 = (t1 ++ e1 :: t2, σ1) →
-       ρ2 = (t1 ++ e2 :: t2 ++ efs, σ2) →
-       prim_step e1 σ1 κ e2 σ2 efs →
-       step ρ1 κ ρ2.
-  Hint Constructors step : core.
-
-  Inductive nsteps : nat → cfg Λ → list (observation Λ) → cfg Λ → Prop :=
-    | nsteps_refl ρ :
-       nsteps 0 ρ [] ρ
-    | nsteps_l n ρ1 ρ2 ρ3 κ κs :
-       step ρ1 κ ρ2 →
-       nsteps n ρ2 κs ρ3 →
-       nsteps (S n) ρ1 (κ ++ κs) ρ3.
-  Hint Constructors nsteps : core.
-
-  Definition erased_step (ρ1 ρ2 : cfg Λ) := ∃ κ, step ρ1 κ ρ2.
-
-  (** [rtc erased_step] and [nsteps] encode the same thing, just packaged
-      in a different way. *)
-  Lemma erased_steps_nsteps ρ1 ρ2 :
-    rtc erased_step ρ1 ρ2 ↔ ∃ n κs, nsteps n ρ1 κs ρ2.
-  Proof.
-    split.
-    - induction 1; firstorder eauto. (* FIXME: [naive_solver eauto] should be able to handle this *)
-    - intros (n & κs & Hsteps). unfold erased_step.
-      induction Hsteps; eauto using rtc_refl, rtc_l.
-  Qed.
-
-  Lemma of_to_val_flip v e : of_val v = e → to_val e = Some v.
-  Proof. intros <-. by rewrite to_of_val. Qed.
-
-  Lemma not_reducible e σ : ¬reducible e σ ↔ irreducible e σ.
-  Proof. unfold reducible, irreducible. naive_solver. Qed.
-  Lemma reducible_not_val e σ : reducible e σ → to_val e = None.
-  Proof. intros (?&?&?&?&?); eauto using val_stuck. Qed.
-  Lemma reducible_no_obs_reducible e σ : reducible_no_obs e σ → reducible e σ.
-  Proof. intros (?&?&?&?); eexists; eauto. Qed.
-  Lemma val_irreducible e σ : is_Some (to_val e) → irreducible e σ.
-  Proof. intros [??] ???? ?%val_stuck. by destruct (to_val e). Qed.
-  Global Instance of_val_inj : Inj (=) (=) (@of_val Λ).
-  Proof. by intros v v' Hv; apply (inj Some); rewrite -!to_of_val Hv. Qed.
-
-  Lemma strongly_atomic_atomic e a :
-    Atomic StronglyAtomic e → Atomic a e.
-  Proof. unfold Atomic. destruct a; eauto using val_irreducible. Qed.
-
-  Lemma reducible_fill `{!@LanguageCtx Λ K} e σ :
-    to_val e = None → reducible (K e) σ → reducible e σ.
-  Proof.
-    intros ? (e'&σ'&k&efs&Hstep); unfold reducible.
-    apply fill_step_inv in Hstep as (e2' & _ & Hstep); eauto.
-  Qed.
-  Lemma reducible_no_obs_fill `{!@LanguageCtx Λ K} e σ :
-    to_val e = None → reducible_no_obs (K e) σ → reducible_no_obs e σ.
-  Proof.
-    intros ? (e'&σ'&efs&Hstep); unfold reducible_no_obs.
-    apply fill_step_inv in Hstep as (e2' & _ & Hstep); eauto.
-  Qed.
-  Lemma irreducible_fill `{!@LanguageCtx Λ K} e σ :
-    to_val e = None → irreducible e σ → irreducible (K e) σ.
-  Proof. rewrite -!not_reducible. naive_solver eauto using reducible_fill. Qed.
-
-  Lemma stuck_fill `{!@LanguageCtx Λ K} e σ :
-    stuck e σ → stuck (K e) σ.
-  Proof. intros [??]. split. by apply fill_not_val. by apply irreducible_fill. Qed.
-
-  Lemma step_Permutation (t1 t1' t2 : list (expr Λ)) κ σ1 σ2 :
-    t1 ≡ₚ t1' → step (t1,σ1) κ (t2,σ2) → ∃ t2', t2 ≡ₚ t2' ∧ step (t1',σ1) κ (t2',σ2).
-  Proof.
-    intros Ht [e1 σ1' e2 σ2' efs tl tr ?? Hstep]; simplify_eq/=.
-    move: Ht; rewrite -Permutation_middle (symmetry_iff (≡ₚ)).
-    intros (tl'&tr'&->&Ht)%Permutation_cons_inv.
-    exists (tl' ++ e2 :: tr' ++ efs); split; [|by econstructor].
-    by rewrite -!Permutation_middle !assoc_L Ht.
-  Qed.
-
-  Lemma erased_step_Permutation (t1 t1' t2 : list (expr Λ)) σ1 σ2 :
-    t1 ≡ₚ t1' → erased_step (t1,σ1) (t2,σ2) → ∃ t2', t2 ≡ₚ t2' ∧ erased_step (t1',σ1) (t2',σ2).
-  Proof.
-    intros Heq [? Hs]. pose proof (step_Permutation _ _ _ _ _ _ Heq Hs). firstorder.
-     (* FIXME: [naive_solver] should be able to handle this *)
-  Qed.
-
-  Record pure_step (e1 e2 : expr Λ) := {
-    pure_step_safe σ1 : reducible_no_obs e1 σ1;
-    pure_step_det σ1 κ e2' σ2 efs :
-      prim_step e1 σ1 κ e2' σ2 efs → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs = []
-  }.
-
-  (* TODO: Exclude the case of [n=0], either here, or in [wp_pure] to avoid it
-  succeeding when it did not actually do anything. *)
-  Class PureExec (φ : Prop) (n : nat) (e1 e2 : expr Λ) :=
-    pure_exec : φ → relations.nsteps pure_step n e1 e2.
-
-  Lemma pure_step_ctx K `{!@LanguageCtx Λ K} e1 e2 :
-    pure_step e1 e2 →
-    pure_step (K e1) (K e2).
-  Proof.
-    intros [Hred Hstep]. split.
-    - unfold reducible_no_obs in *. naive_solver eauto using fill_step.
-    - intros σ1 κ e2' σ2 efs Hpstep.
-      destruct (fill_step_inv e1 σ1 κ e2' σ2 efs) as (e2'' & -> & ?); [|exact Hpstep|].
-      + destruct (Hred σ1) as (? & ? & ? & ?); eauto using val_stuck.
-      + edestruct (Hstep σ1 κ e2'' σ2 efs) as (? & -> & -> & ->); auto.
-  Qed.
-
-  Lemma pure_step_nsteps_ctx K `{!@LanguageCtx Λ K} n e1 e2 :
-    relations.nsteps pure_step n e1 e2 →
-    relations.nsteps pure_step n (K e1) (K e2).
-  Proof. induction 1; econstructor; eauto using pure_step_ctx. Qed.
-
-  (* We do not make this an instance because it is awfully general. *)
-  Lemma pure_exec_ctx K `{!@LanguageCtx Λ K} φ n e1 e2 :
-    PureExec φ n e1 e2 →
-    PureExec φ n (K e1) (K e2).
-  Proof. rewrite /PureExec; eauto using pure_step_nsteps_ctx. Qed.
-
-  (* This is a family of frequent assumptions for PureExec *)
-  Class IntoVal (e : expr Λ) (v : val Λ) :=
-    into_val : of_val v = e.
-
-  Class AsVal (e : expr Λ) := as_val : ∃ v, of_val v = e.
-  (* There is no instance [IntoVal → AsVal] as often one can solve [AsVal] more
-  efficiently since no witness has to be computed. *)
-  Global Instance as_vals_of_val vs : TCForall AsVal (of_val <$> vs).
-  Proof.
-    apply TCForall_Forall, Forall_fmap, Forall_true=> v.
-    rewrite /AsVal /=; eauto.
-  Qed.
-  Lemma as_val_is_Some e :
-    (∃ v, of_val v = e) → is_Some (to_val e).
-  Proof. intros [v <-]. rewrite to_of_val. eauto. Qed.
-End language.
diff --git a/theories/program_logic/lifting.v b/theories/program_logic/lifting.v
deleted file mode 100644
index 36ceb429b01db9beb1d50b06de52ac60a39dd7c8..0000000000000000000000000000000000000000
--- a/theories/program_logic/lifting.v
+++ /dev/null
@@ -1,281 +0,0 @@
-From iris.program_logic Require Export weakestpre.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-Section lifting.
-Context {SI} {Σ: gFunctors SI} `{!irisG Λ Σ}.
-Implicit Types s : stuckness.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-Implicit Types σ : state Λ.
-Implicit Types P Q : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-
-Hint Resolve reducible_no_obs_reducible : core.
-
-Lemma wp_lift_step_fupd s E Φ e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E,∅}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={∅,∅,E}▷=∗
-      state_interp σ2 κs (length efs + n) ∗
-      WP e2 @ s; E {{ Φ }} ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  rewrite wp_unfold /wp_pre=>->. iIntros "H" (σ1 κ κs n) "Hσ".
-  iMod ("H" with "Hσ") as "(%&H)". iApply lstep_intro. iModIntro. iSplit.
-    by destruct s.
-  iIntros (????). iApply "H". eauto.
-Qed.
-
-Lemma swp_lift_step_fupd k s E Φ e1 :
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E,∅}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={∅,∅,E}▷=∗
-      state_interp σ2 κs (length efs + n) ∗
-      WP e2 @ s; E {{ Φ }} ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  rewrite swp_unfold /swp_def. iIntros "H" (σ1 κ κs n) "Hσ".
-  iMod ("H" with "Hσ") as "(%&H)". iApply lstepN_intro. iModIntro.
-  iSplit; eauto.
-Qed.
-
-Lemma wp_lift_stuck E Φ e :
-  to_val e = None →
-  (∀ σ κs n, state_interp σ κs n ={E,∅}=∗ ⌜stuck e σ⌝)
-  ⊢ WP e @ E ?{{ Φ }}.
-Proof.
-  rewrite wp_unfold /wp_pre=>->. iIntros "H" (σ1 κ κs n) "Hσ".
-  iMod ("H" with "Hσ") as %[? Hirr]. iApply lstep_intro. iModIntro. 
-  iSplit; first done.
-  iIntros (e2 σ2 efs ?). by case: (Hirr κ e2 σ2 efs).
-Qed.
-
-(** Derived lifting lemmas. *)
-Lemma wp_lift_step s E Φ e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E,∅}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      WP e2 @ s; E {{ Φ }} ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_step_fupd; [done|]. iIntros (????) "Hσ".
-  iMod ("H" with "Hσ") as "[$ H]". iIntros "!> * % !> !>". by iApply "H".
-Qed.
-
-Lemma swp_lift_step k s E Φ e1 :
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E,∅}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      WP e2 @ s; E {{ Φ }} ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros "H". iApply swp_lift_step_fupd. iIntros (????) "Hσ".
-  iMod ("H" with "Hσ") as "[$ H]". iIntros "!> * % !> !>". by iApply "H".
-Qed.
-
-Lemma wp_lift_pure_step_no_fork `{!Inhabited (state Λ)} s E E' Φ e1 :
-  (∀ σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) →
-  (∀ κ σ1 e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (|={E,E'}▷=> ∀ κ e2 efs σ, ⌜prim_step e1 σ κ e2 σ efs⌝ → WP e2 @ s; E {{ Φ }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (Hsafe Hstep) "H". iApply wp_lift_step.
-  { specialize (Hsafe inhabitant). destruct s; eauto using reducible_not_val. }
-  iIntros (σ1 κ κs n) "Hσ". iMod "H".
-  iMod fupd_intro_mask' as "Hclose"; last iModIntro; first by set_solver. iSplit.
-  { iPureIntro. destruct s; done. }
-  iNext. iIntros (e2 σ2 efs ?).
-  destruct (Hstep κ σ1 e2 σ2 efs) as (-> & <- & ->); auto.
-  iMod "Hclose" as "_". iMod "H". iModIntro.
-  iDestruct ("H" with "[//]") as "H". simpl. iFrame.
-Qed.
-
-
-Lemma swp_lift_pure_step_no_fork k s E E' Φ e1 :
-  (∀ σ1, s = NotStuck → reducible e1 σ1) →
-  (∀ κ σ1 e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (|={E,E'}▷=> ∀ κ e2 efs σ, ⌜prim_step e1 σ κ e2 σ efs⌝ → WP e2 @ s; E {{ Φ }})
-  ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros (Hsafe Hstep) "H". iApply swp_lift_step.
-  iIntros (σ1 κ κs n) "Hσ". iMod "H".
-  iMod fupd_intro_mask' as "Hclose"; last iModIntro; first by set_solver. iSplit.
-  { iPureIntro. destruct s; eauto. }
-  iNext. iIntros (e2 σ2 efs ?).
-  destruct (Hstep κ σ1 e2 σ2 efs) as (-> & <- & ->); auto.
-  iMod "Hclose" as "_". iMod "H". iModIntro.
-  iDestruct ("H" with "[//]") as "H". simpl. iFrame.
-Qed.
-
-Lemma wp_lift_pure_stuck `{!Inhabited (state Λ)} E Φ e :
-  (∀ σ, stuck e σ) →
-  True ⊢ WP e @ E ?{{ Φ }}.
-Proof.
-  iIntros (Hstuck) "_". iApply wp_lift_stuck.
-  - destruct(to_val e) as [v|] eqn:He; last done.
-    rewrite -He. by case: (Hstuck inhabitant).
-  - iIntros (σ κs n) "_". by iMod (fupd_intro_mask' E ∅) as "_"; first set_solver.
-Qed.
-
-(* Atomic steps don't need any mask-changing business here, one can
-   use the generic lemmas here. *)
-Lemma wp_lift_atomic_step_fupd {s E1 E2 Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E1}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E1,E2}▷=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E1 {{ Φ }}.
-Proof.
-  iIntros (?) "H".
-  iApply (wp_lift_step_fupd s E1 _ e1)=>//; iIntros (σ1 κ κs n) "Hσ1".
-  iMod ("H" $! σ1 with "Hσ1") as "[$ H]".
-  iMod (fupd_intro_mask' E1 ∅) as "Hclose"; first set_solver.
-  iIntros "!>" (e2 σ2 efs ?). iMod "Hclose" as "_".
-  iMod ("H" $! e2 σ2 efs with "[#]") as "H"; [done|].
-  iMod (fupd_intro_mask' E2 ∅) as "Hclose"; [set_solver|]. iIntros "!> !>".
-  iMod "Hclose" as "_". iMod "H" as "($ & HQ & $)".
-  destruct (to_val e2) eqn:?; last by iExFalso.
-  iApply wp_value; last done. by apply of_to_val.
-Qed.
-
-Lemma swp_lift_atomic_step_fupd {k s E1 E2 Φ} e1 :
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E1}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E1,E2}▷=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ SWP e1 at k @ s; E1 {{ Φ }}.
-Proof.
-  iIntros "H".
-  iApply (swp_lift_step_fupd k s E1 _ e1)=>//; iIntros (σ1 κ κs n) "Hσ1".
-  iMod ("H" $! σ1 with "Hσ1") as "[$ H]".
-  iMod (fupd_intro_mask' E1 ∅) as "Hclose"; first set_solver.
-  iIntros "!>" (e2 σ2 efs ?). iMod "Hclose" as "_".
-  iMod ("H" $! e2 σ2 efs with "[#]") as "H"; [done|].
-  iMod (fupd_intro_mask' E2 ∅) as "Hclose"; [set_solver|]. iIntros "!> !>".
-  iMod "Hclose" as "_". iMod "H" as "($ & HQ & $)".
-  destruct (to_val e2) eqn:?; last by iExFalso.
-  iApply wp_value; last done. by apply of_to_val.
-Qed.
-
-Lemma wp_lift_atomic_step {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (?) "H". iApply wp_lift_atomic_step_fupd; [done|].
-  iIntros (????) "?". iMod ("H" with "[$]") as "[$ H]".
-  iIntros "!> *". iIntros (Hstep) "!> !>".
-  by iApply "H".
-Qed.
-
-Lemma swp_lift_atomic_step {k s E Φ} e1 :
-  (∀ σ1 κ κs n, state_interp σ1 (κ ++ κs) n ={E}=∗
-    ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ▷ ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      state_interp σ2 κs (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, WP ef @ s; ⊤ {{ fork_post }})
-  ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros "H". iApply swp_lift_atomic_step_fupd.
-  iIntros (????) "?". iMod ("H" with "[$]") as "[$ H]".
-  iIntros "!> *". iIntros (Hstep) "!> !>".
-  by iApply "H".
-Qed.
-
-
-Lemma wp_lift_pure_det_step_no_fork `{!Inhabited (state Λ)} {s E E' Φ} e1 e2 :
-  (∀ σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) →
-  (∀ σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs' →
-    κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (|={E,E'}▷=> WP e2 @ s; E {{ Φ }}) ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (? Hpuredet) "H". iApply (wp_lift_pure_step_no_fork s E E'); try done.
-  { naive_solver. }
-  iApply (step_fupd_wand with "H"); iIntros "H".
-  iIntros (κ e' efs' σ (_&?&->&?)%Hpuredet); auto.
-Qed.
-
-Lemma swp_lift_pure_det_step_no_fork {k s E E' Φ} e1 e2 :
-  (∀ σ1, s = NotStuck → reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs' →
-    κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (|={E,E'}▷=> WP e2 @ s; E {{ Φ }}) ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros (? Hpuredet) "H". iApply (swp_lift_pure_step_no_fork k s E E'); try done.
-  { naive_solver. }
-  iApply (step_fupd_wand with "H"); iIntros "H".
-  iIntros (κ e' efs' σ (_&?&->&?)%Hpuredet); auto.
-Qed.
-
-Lemma wp_pure_step_fupd `{!Inhabited (state Λ)} s E E' e1 e2 φ n Φ :
-  PureExec φ n e1 e2 →
-  φ →
-  (|={E,E'}▷=>^n WP e2 @ s; E {{ Φ }}) ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  iIntros (Hexec Hφ) "Hwp". specialize (Hexec Hφ).
-  iInduction Hexec as [e|n e1 e2 e3 [Hsafe ?]] "IH"; simpl; first done.
-  iApply wp_lift_pure_det_step_no_fork.
-  - intros σ. specialize (Hsafe σ). destruct s; eauto using reducible_not_val.
-  - done.
-  - by iApply (step_fupd_wand with "Hwp").
-Qed.
-
-Lemma swp_pure_step_fupd k s E E' e1 e2 φ n Φ `{!Inhabited (state Λ)} :
-  PureExec φ (S n) e1 e2 →
-  φ →
-  (|={E,E'}▷=>^(S n) WP e2 @ s; E {{ Φ }}) ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  iIntros (Hexec Hφ) "Hwp". specialize (Hexec Hφ).
-  iInduction n as [|n] "IH" forall (e1 Hexec); simpl;
-  inversion Hexec as [|n' ? e1' ? Hstep Hrest]; subst.
-  all: iApply swp_lift_pure_det_step_no_fork.
-  1, 4: intros σ; intros H; subst; eauto using pure_step_safe, reducible_no_obs_reducible, reducible_not_val.
-  1, 3: eauto using pure_step_det.
-  - inversion Hrest; subst; eauto.
-  - iSpecialize ("IH" with "[//] Hwp").
-    iMod "IH". iModIntro. iNext. iMod "IH". iModIntro.
-    iPoseProof (swp_wp with "IH") as "IH"; eauto.
-    inversion Hrest; subst.
-    unshelve eauto using pure_step_safe, reducible_no_obs_reducible, reducible_not_val.
-    exact inhabitant.
-Qed.
-
-Lemma wp_pure_step_later `{!Inhabited (state Λ)} s E e1 e2 φ n Φ :
-  PureExec φ n e1 e2 →
-  φ →
-  ▷^n WP e2 @ s; E {{ Φ }} ⊢ WP e1 @ s; E {{ Φ }}.
-Proof.
-  intros Hexec ?. rewrite -wp_pure_step_fupd //. clear Hexec.
-  induction n as [|n IH]; by rewrite //= -step_fupd_intro // IH.
-Qed.
-
-
-Lemma swp_pure_step_later `{!Inhabited (state Λ)} k s E e1 e2 φ n Φ :
-  PureExec φ (S n) e1 e2 →
-  φ →
-  ▷^(S n) WP e2 @ s; E {{ Φ }} ⊢ SWP e1 at k @ s; E {{ Φ }}.
-Proof.
-  intros Hexec ?. rewrite -swp_pure_step_fupd //. iIntros "H".
-  iApply step_fupdN_intro; eauto.
-Qed.
-End lifting.
diff --git a/theories/program_logic/refinement/ref_adequacy.v b/theories/program_logic/refinement/ref_adequacy.v
deleted file mode 100644
index 0a9b9d39175f03e9084bf72dba1ef169c066e5cf..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/ref_adequacy.v
+++ /dev/null
@@ -1,354 +0,0 @@
-From iris.program_logic Require Export language.
-From iris.bi Require Export weakestpre fixpoint.
-From iris.proofmode Require Import base tactics classes.
-From iris.algebra Require Import auth list.
-From iris.base_logic Require Export satisfiable gen_heap.
-From iris.base_logic.lib Require Export fancy_updates logical_step.
-From iris.program_logic.refinement Require Export ref_source ref_weakestpre.
-Set Default Proof Using "Type".
-
-
-
-Lemma sn_not_ex_loop {A} `{Classical} (R : relation A) x :
-  ¬ex_loop R x → sn R x.
-Proof.
-  intros Hex. destruct (excluded_middle (sn R x)) as [|Hsn]; [done|].
-  destruct Hex. revert x Hsn. cofix IH; intros x Hsn.
-  destruct (excluded_middle (∃ y, R x y ∧ ¬sn R y)) as [(y&?&?)|Hnot].
-  - exists y; auto.
-  - destruct Hsn. constructor. intros y Hxy.
-    destruct (excluded_middle (sn R y)); naive_solver.
-Qed.
-
-
-Section refinements.
-Context {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ}.
-Implicit Types s : stuckness.
-Implicit Types P : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-Implicit Types a : A.
-Implicit Types b : bool.
-
-(** We first prove that termination is preserverd: if the source is strongly normalising, then also the target is strongly normalising *)
-
-(* With rwp_tp, we lift the essential parts for termination preserving refinement of rwp to thread pools. *)
-Definition rwp_tp_pre (rwp_tp: list (expr Λ) → iProp Σ) (t1: list (expr Λ)) : iProp Σ :=
-  (∀ t2 σ σ' κ a n,
-    ⌜step (t1, σ) κ (t2, σ')⌝
-      -∗ source_interp a ∗ ref_state_interp σ n
-          ={⊤, ∅}=∗ ∃ b,
-            ▷?b |={∅, ⊤}=> ∃ m,
-              ref_state_interp σ' m
-              ∗ if b then ∃ a', ⌜a ↪⁺ a'⌝ ∗ rwp_tp t2 ∗ source_interp a'
-                     else rwp_tp t2 ∗ source_interp a)%I.
-
-(* Not every recursive occurrence is guarded by a later. We obtain a fixpoint of the defintion using a least fixpoint operator.*)
-Definition rwp_tp (t : list (expr Λ)) : iProp Σ := bi_least_fixpoint rwp_tp_pre t.
-
-Lemma rwp_tp_pre_mono (rwp_tp1 rwp_tp2 : list (expr Λ) → iProp Σ) :
-  ⊢ (<pers> (∀ t, rwp_tp1 t -∗ rwp_tp2 t) →
-    ∀ t, rwp_tp_pre rwp_tp1 t -∗ rwp_tp_pre rwp_tp2 t)%I.
-Proof.
-  iIntros "#H"; iIntros (t) "Hwp". rewrite /rwp_tp_pre.
-  iIntros (t2 σ1 σ2 κ a n1) "Hstep Hσ".
-  iMod ("Hwp" with "[$] [$]") as (b) "Hwp".
-  iModIntro. iExists b. iNext. iMod "Hwp". iModIntro.
-  iDestruct "Hwp" as (m) "(Hσ & Hwp)". iExists m. iFrame "Hσ".
-  destruct b; eauto.
-  - iDestruct "Hwp" as (a') "(Hstep & Hgn & Hsrc)".
-    iExists a'. iFrame. by iApply "H".
-  - iDestruct "Hwp" as "(Hgn & $)". by iApply "H".
-Qed.
-
-Local Instance rwp_tp_pre_mono' : BiMonoPred rwp_tp_pre.
-Proof.
-  constructor; first apply rwp_tp_pre_mono.
-  intros wp Hwp n t1 t2 ?%(discrete_iff _ _)%leibniz_equiv; solve_proper.
-Qed.
-
-
-Lemma rwp_tp_unfold t : rwp_tp t ⊣⊢ rwp_tp_pre rwp_tp t.
-Proof. by rewrite /rwp_tp least_fixpoint_unfold. Qed.
-
-Lemma rwp_tp_ind Ψ :
-  ⊢ ((□ ∀ t, rwp_tp_pre (λ t, Ψ t ∧ rwp_tp t) t -∗ Ψ t) → ∀ t, rwp_tp t -∗ Ψ t)%I.
-Proof.
-  iIntros "#IH" (t) "H".
-  assert (NonExpansive Ψ).
-  { by intros n ?? ->%(discrete_iff _ _)%leibniz_equiv. }
-  iApply (least_fixpoint_strong_ind _ Ψ with "[] H").
-  iIntros "!#" (t') "H". by iApply "IH".
-Qed.
-
-Instance rwp_tp_Permutation : Proper ((≡ₚ) ==> (⊢)) rwp_tp.
-Proof.
-  iIntros (t1 t1' Ht) "Ht1". iRevert (t1' Ht); iRevert (t1) "Ht1".
-  iApply rwp_tp_ind; iIntros "!#" (t1) "IH"; iIntros (t1' Ht).
-  rewrite rwp_tp_unfold /rwp_tp_pre. iIntros (t2 σ1 σ2 κ a n Hstep) "Hσ".
-  destruct (step_Permutation t1' t1 t2 κ σ1 σ2) as (t2'&?&?); try done.
-  iMod ("IH" with "[% //] Hσ") as (b) "IH". iModIntro. iExists b. iNext.
-  iMod "IH" as (n2) "(Hσ & IH)".
-  iModIntro. iExists n2. iFrame "Hσ".
-  destruct b.
-  - iDestruct "IH" as (a') "(Hstep & [IH _] & Hsrc)".
-    iExists a'. iFrame. by iApply "IH".
-  - iDestruct "IH" as "([IH _] & $)".
-    by iApply "IH".
-Qed.
-
-Lemma rwp_tp_app t1 t2: rwp_tp t1 -∗ rwp_tp t2 -∗ rwp_tp (t1 ++ t2).
-Proof.
-  iIntros "H1". iRevert (t2). iRevert (t1) "H1".
-  iApply rwp_tp_ind; iIntros "!#" (t1) "IH1". iIntros (t2) "H2".
-  iRevert (t1) "IH1"; iRevert (t2) "H2".
-  iApply rwp_tp_ind; iIntros "!#" (t2) "IH2". iIntros (t1) "IH1".
-  rewrite rwp_tp_unfold {4}/rwp_tp_pre. iIntros (t1'' σ1 σ2 κ a n Hstep) "Hσ1".
-  destruct Hstep as [e1 σ1' e2 σ2' efs' t1' t2' [=Ht ?] ? Hstep]; simplify_eq/=.
-  apply app_eq_inv in Ht as [(t&?&?)|(t&?&?)]; subst.
-  - destruct t as [|e1' ?]; simplify_eq/=.
-    + iMod ("IH2" with "[%] Hσ1") as (b) "IH2".
-      { by eapply step_atomic with (t1:=[]). }
-      iModIntro. iExists b. iNext. iMod "IH2" as (n2) "[Hσ IH2]". iModIntro. iExists n2. iFrame "Hσ".
-      rewrite -{2}(left_id_L [] (++) (e2 :: _)). destruct b.
-      * iDestruct "IH2" as (a' Hsrc) "[[IH2 _] Hsrc]". iExists a'. iFrame "Hsrc".
-        iSplit; first by iPureIntro. iApply "IH2".
-        by rewrite (right_id_L [] (++)).
-      * iDestruct "IH2" as "[[IH2 _] Hsrc]". iFrame "Hsrc". iApply "IH2".
-        by rewrite (right_id_L [] (++)).
-    +  iMod ("IH1" with "[%] Hσ1") as (b) "IH1".
-      { by econstructor. }
-      iModIntro. iExists b. iApply (bi.laterN_wand with "[IH2] IH1"). iNext.
-      iIntros "IH1". iMod "IH1" as (n2) "(Hσ & IH1)". iModIntro.
-      iExists n2. iFrame "Hσ".
-      iAssert (rwp_tp t2) with "[IH2]" as "Ht2".
-        { rewrite rwp_tp_unfold. iApply (rwp_tp_pre_mono with "[] IH2").
-          iIntros "!# * [_ ?] //". }
-      destruct b.
-      * iDestruct "IH1" as (a' Hsrc) "[[IH1 _] Hsrc]".
-        iExists a'. iFrame "Hsrc". iSplit; first by iPureIntro.
-        rewrite -assoc_L (comm _ t2) !cons_middle !assoc_L. by iApply "IH1".
-      * iDestruct "IH1" as  "[[IH1 _] Hsrc]".
-        iFrame "Hsrc". rewrite -assoc_L (comm _ t2) !cons_middle !assoc_L. by iApply "IH1".
-  - iMod ("IH2" with "[%] Hσ1") as (b) "IH2"; first by econstructor.
-    iModIntro. iExists b. iApply (bi.laterN_wand with "[IH1] IH2"). iNext.
-    iIntros "IH2". iMod "IH2" as (n2) "[Hσ IH2]". iModIntro. iExists n2.
-    iFrame "Hσ". rewrite -assoc_L. destruct b.
-    + iDestruct "IH2" as (a' Hsrc) "[[IH2 _] Hsrc]". iExists a'. iFrame "Hsrc".
-      iSplit; first by iPureIntro. by iApply "IH2".
-    + iDestruct "IH2" as "[[IH2 _] Hsrc]". iFrame "Hsrc". by iApply "IH2".
-Qed.
-
-(* rwp_tp subsumes rwp *)
-Lemma rwp_rwp_tp s Φ e : RWP e @ s; ⊤ ⟨⟨ Φ ⟩⟩ -∗ rwp_tp [e].
-Proof.
-  iIntros "He". remember (⊤ : coPset) as E eqn:HE.
-  iRevert (HE). iRevert (e E Φ) "He". iApply rwp_ind.
-  iIntros "!#" (e E Φ). iIntros "IH" (->).
-  rewrite /rwp_pre /rwp_step rwp_tp_unfold /rwp_tp_pre.
-  iIntros (t' σ σ' κ a n Hstep).
-  destruct Hstep as [e1 σ1 e2 σ2 efs [|? t1] t2 ?? Hstep];
-    simplify_eq/=; try discriminate_list.
-  destruct (to_val e1) as [v|] eqn:He1.
-  { apply val_stuck in Hstep; naive_solver. }
-  iIntros "[Ha Hσ]".
-  iMod ("IH" with "[$Ha $Hσ]") as (b) "IH". iModIntro.
-  iExists b. iApply (bi.laterN_wand with "[] IH"). iNext.
-  iIntros "H". iMod "H" as "[_ IH]".
-  iMod ("IH" with "[% //]") as "(Hsrc & Hσ & IH & IHs)".
-  iModIntro. iExists (length efs + n). iFrame "Hσ".
-  iAssert (rwp_tp (e2 :: efs))%I with "[IH IHs]" as "Hrwp_tp".
-  { iApply (rwp_tp_app [_] with "(IH [//])").
-    clear. iInduction efs as [|e efs] "IH"; simpl.
-    { rewrite rwp_tp_unfold /rwp_tp_pre. iIntros (t2 σ1 κ σ2 a n1 Hstep).
-      destruct Hstep; simplify_eq/=; discriminate_list. }
-    iDestruct "IHs" as "[IH' IHfork]".
-    iApply (rwp_tp_app [_] with "(IH' [//])"). by iApply "IH".
-  }
-  destruct b; iFrame.
-Qed.
-
-
-(* We unfold the refinement to a sequence of later operations interleaved with fancy updates. *)
-Definition guarded_pre (grd: (A -d> iProp Σ -d> iProp Σ)) : A -d> iProp Σ -d> iProp Σ :=
-  λ (a: A) (P: iProp Σ),
-    (|={⊤,∅}=> (|={∅,⊤}=> P) ∨ (▷ |={∅,⊤}=> ∃ a', ⌜a ↪⁺ a'⌝ ∗ grd a' P))%I.
-
-Global Instance guarded_pre_contractive: Contractive (guarded_pre).
-Proof.
-  intros α ev1 ev2 Heq. rewrite /guarded_pre; simpl.
-  intros e_S P. do 2 f_equiv. f_contractive. intros ??.
-  do 2 f_equiv. intros e_s'. f_equiv. by apply Heq.
-Qed.
-
-Definition guarded := fixpoint guarded_pre.
-
-Lemma guarded_unfold a P: guarded a P ≡ (|={⊤,∅}=> (|={∅,⊤}=> P) ∨ (▷ |={∅,⊤}=> ∃ a', ⌜a ↪⁺a'⌝ ∗ guarded a' P))%I.
-Proof. unfold guarded. apply (@fixpoint_unfold SI (A -d> iProp Σ -d> iProp Σ) _ guarded_pre _). Qed.
-
-(* Guarded propositions eventually become true, if the source does not allow infinite loops. *)
-Lemma guarded_satisfiable `{LargeIndex SI} a P:
-  sn source_rel a
-  → satisfiable_at ⊤ (guarded a P)
-  → satisfiable_at ⊤ P.
-Proof.
-  intros Hsn % sn_tc. induction Hsn as [a Ha IH]. rewrite guarded_unfold.
-  intros Hsat. apply satisfiable_at_fupd in Hsat.
-  apply satisfiable_at_or in Hsat as [Hsat|Hsat].
-  { by apply satisfiable_at_fupd in Hsat. }
-  apply satisfiable_at_later in Hsat.
-  apply satisfiable_at_fupd in Hsat.
-  apply satisfiable_at_exists in Hsat as [b Hsat]; last apply _.
-  apply satisfiable_at_sep in Hsat as [Hsat1 % satisfiable_at_pure Hsat2].
-  by eapply IH.
-Qed.
-
-
-
-Lemma rwp_tp_guarded_false t:
-  rwp_tp t ⊢ ∀ σ a n, ⌜ex_loop erased_step (t, σ)⌝
-                      -∗ source_interp a
-                      -∗ ref_state_interp σ n
-                      -∗ guarded a False.
-Proof.
-  iApply (rwp_tp_ind (λ t, ∀ σ a n, ⌜ex_loop erased_step (t, σ)⌝ -∗ source_interp a -∗ ref_state_interp σ n -∗ guarded a False)%I with "[]"). clear t.
-  iModIntro. iIntros (t). rewrite /rwp_tp_pre. iIntros "Hrwp_tp". iIntros (σ a n Hloop) "Hsrc Hσ".
-  inversion Hloop as [x [t' σ'] [κ Hstep] Hloop']; subst x; clear Hloop.
-  iSpecialize ("Hrwp_tp"  $! t' σ σ' κ a n with "[]"); eauto.
-  iSpecialize ("Hrwp_tp" with "[$Hsrc $Hσ]"). iApply guarded_unfold.
-  iMod "Hrwp_tp" as (b) "Hrwp_tp". destruct b.
-  + iModIntro. iRight. iNext. iMod "Hrwp_tp" as (m) "(Hσ & Hev)".
-    iModIntro. iDestruct "Hev" as (a' Hsrc) "[[Hev _] Hsrc]".
-    iExists a'. iSplit; first by iPureIntro.
-    iApply ("Hev" with "[] Hsrc Hσ"); eauto.
-  + iMod "Hrwp_tp" as (m) "(Hσ & [Hev _] & Ha)".
-    iSpecialize ("Hev" with "[//] Ha Hσ").
-    by rewrite guarded_unfold.
-Qed.
-
-Lemma rwp_adequacy `{LargeIndex SI} Φ a e σ n s:
-  sn source_rel a
-  → ex_loop erased_step ([e], σ)
-  → satisfiable_at ⊤ (source_interp a ∗ ref_state_interp σ n ∗ RWP e @ s; ⊤ ⟨⟨ Φ ⟩⟩)%I
-  → False.
-Proof.
-  intros Hsn Hloop Hsat. eapply (satisfiable_at_mono _ _ (guarded a False)%I) in Hsat.
-  - apply guarded_satisfiable in Hsat; eauto. by eapply satisfiable_at_pure.
-  - iIntros "(Hsrc & Hσ & Hwp)".
-    iApply (rwp_tp_guarded_false with "[Hwp] [//] Hsrc Hσ").
-    by iApply rwp_rwp_tp.
-Qed.
-
-Lemma rwp_sn_preservation `{Classical} `{LargeIndex SI} Φ a e σ n s:
-  sn source_rel a
-  → satisfiable_at ⊤ (source_interp a ∗ ref_state_interp σ n ∗ RWP e @ s; ⊤ ⟨⟨ Φ ⟩⟩)%I
-  → sn erased_step ([e], σ).
-Proof.
-    intros Hsn Hsat. eapply sn_not_ex_loop. intros Hloop.
-    eapply rwp_adequacy; eauto.
-Qed.
-
-
-(** the following lemmas are completely independent from the preceding lemmas*)
-(** they provide a general result which can be used to prove that the result of a computation refines a source computation
-  -- however, the concrete shape of this strongly depends on the chosen source and state interpretations *)
-
-(* we are ignoring any threads that are forked off *)
-Lemma rwp_prim_step `{LargeIndex SI} F s κ a n e e' σ σ' Φ efs:
-  prim_step e σ κ e' σ' efs →
-  satisfiable_at ⊤ (source_interp a ∗ ref_state_interp σ n ∗ RWP e @ s; ⊤ ⟨⟨ Φ ⟩⟩ ∗ F)%I
-  → ∃ a' m, rtc source_rel a a'
-            ∧ satisfiable_at ⊤ (source_interp a' ∗ ref_state_interp σ' m ∗ RWP e' @ s; ⊤ ⟨⟨ Φ ⟩⟩
-                                  ∗ ([∗ list] e ∈ efs, RWP e @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩) ∗ F)%I.
-Proof.
-  intros Hstep Hsat.
-  eapply satisfiable_at_mono with (Q := (|={⊤, ∅}=> ▷ |={∅, ⊤}=> ∃ a' m, ⌜rtc source_rel a a'⌝ ∗ source_interp a' ∗ ref_state_interp σ' m ∗ RWP e' @ s; ⊤ ⟨⟨ Φ ⟩⟩ ∗ ([∗ list] e ∈ efs, RWP e @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩) ∗ F)%I)  in Hsat; last first.
-  - rewrite rwp_unfold /rwp_pre /rwp_step.
-    iIntros "(Hsrc & SI & Hwp & F)".
-    erewrite val_stuck; eauto.
-    iMod ("Hwp" $! σ n a with "[$Hsrc $SI]") as ([]) "Hwp"; simpl; iModIntro; iNext; iMod "Hwp" as "[_ Hwp]".
-    + iMod ("Hwp" $! _ _ _ _ Hstep) as "(Hsrc & SI & RWP & Hfork)".
-      iDestruct "Hsrc" as (a' Hsteps) "Hsrc".
-      iModIntro. iExists a', _. iFrame. iPureIntro.
-      by apply tc_rtc.
-    + iMod ("Hwp" $! _ _ _ _ Hstep) as "(Hsrc & SI & RWP & Hfork)".
-      iModIntro. iExists a, _. iFrame. by iPureIntro.
-  - apply satisfiable_at_fupd in Hsat.
-    apply satisfiable_at_later in Hsat.
-    apply satisfiable_at_fupd in Hsat.
-    apply satisfiable_at_exists in Hsat as [a' Hsat]; auto.
-    apply satisfiable_at_exists in Hsat as [m Hsat]; auto.
-    apply satisfiable_at_sep in Hsat as [Hsteps Hsat].
-    apply satisfiable_at_pure in Hsteps.
-    exists a', m. eauto.
-Qed.
-
-
-Definition thread_wps s Φ (es: list (expr Λ)) : iProp Σ :=
-  ([∗ list] i ↦ e ∈ es, if i is 0 then RWP e @ s; ⊤ ⟨⟨ Φ ⟩⟩ else RWP e @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)%I.
-
-(* thread lifting *)
-Lemma rwp_erased_step `{LargeIndex SI} s Φ a n ts ts' σ σ':
-  erased_step (ts, σ) (ts', σ')
-  → satisfiable_at ⊤ (source_interp a ∗ ref_state_interp σ n ∗ thread_wps s Φ ts)%I
-  → ∃ a' m, rtc source_rel a a'
-            ∧ satisfiable_at ⊤ (source_interp a' ∗ ref_state_interp σ' m ∗ thread_wps s Φ ts')%I.
-Proof.
-  intros [κ Hstep] Hsat. inversion Hstep as [e1 σ1 e2 σ2 efs t1 t2 Heq1 Heq2 Hstep'].
-  injection Heq1 as -> ->. injection Heq2 as -> ->. revert Hsat.
-  destruct t1; simpl in *; rewrite /thread_wps //=.
-  -  intros Hsat. eapply rwp_prim_step in Hsat; eauto. rewrite /thread_wps //=.
-    destruct Hsat as (a' & m & Hrtc & Hsat).
-    exists a', m. split; auto.
-    by rewrite big_sepL_app [(([∗ list] y ∈ t2, _) ∗ _)%I]bi.sep_comm.
-  - rewrite big_sepL_app //=.
-    intros Hsat; eapply satisfiable_at_mono with (Q := (_ ∗ _ ∗ _ ∗ _)%I)in Hsat; last first.
-    { iIntros "(Hsrc & SI & Hrwp & Ht1 & He & Ht2)".
-      iSplitL "Hsrc"; first iAssumption.
-      iSplitL "SI"; first iAssumption.
-      iSplitL "He"; first iAssumption.
-      iCombine "Hrwp Ht1 Ht2" as "H"; iAssumption. }
-    eapply rwp_prim_step in Hsat; eauto.
-    destruct Hsat as (a' & m & Hrtc & Hsat).
-    exists a', m. split; auto.
-    eapply satisfiable_at_mono; first apply Hsat.
-    iIntros "($ & $ & He2 & Hefs & $ & Ht1 & Ht2)".
-    rewrite big_sepL_app //= big_sepL_app; iFrame.
-Qed.
-
-
-Lemma rwp_erased_steps `{LargeIndex SI} s Φ a n ts ts' σ σ':
-  rtc erased_step (ts, σ) (ts', σ')
-  → satisfiable_at ⊤ (source_interp a ∗ ref_state_interp σ n ∗ thread_wps s Φ ts)%I
-  → ∃ a' m, rtc source_rel a a'
-            ∧ satisfiable_at ⊤ (source_interp a' ∗ ref_state_interp σ' m ∗ thread_wps s Φ ts')%I.
-Proof.
-  intros Hsteps. remember (ts, σ) as c. remember (ts', σ') as c'.
-  revert ts σ Heqc ts' σ' Heqc' n a.
-  induction Hsteps as [|x [ts'' σ''] z Hstep]; intros ts σ Heqc ts' σ' Heqc' n a; subst.
-  - injection Heqc' as -> ->. intros Hsteps. exists a, n; by split.
-  - intros Hsat. eapply rwp_erased_step in Hsat as (a' & m & Hsteps' & Hsat); last eauto.
-    edestruct IHHsteps as (a'' & m' & Hsteps'' & Hsat'); [done|done| |].
-    + apply Hsat.
-    + exists a'', m'; split; eauto. transitivity a'; eauto.
-Qed.
-
-Lemma rwp_result `{LargeIndex SI} Φ ts a n e v σ σ' s:
-  rtc erased_step ([e], σ) (of_val v :: ts, σ')
-  → satisfiable_at ⊤ (source_interp a ∗ ref_state_interp σ n ∗ RWP e @ s; ⊤ ⟨⟨ Φ ⟩⟩)%I
-  → ∃ a' m, rtc source_rel a a'
-            ∧ satisfiable_at ⊤ (source_interp a' ∗ ref_state_interp σ' m ∗ Φ v)%I.
-Proof.
-  intros Hsteps Hsat. eapply rwp_erased_steps in Hsteps; last first.
-  { rewrite /thread_wps //=. eapply satisfiable_at_mono; first apply Hsat.
-    by iIntros "($ & $ & $)". }
-  destruct Hsteps as (a' & m & Hrtc & Hsat'). exists a', m; split; auto.
-  eapply satisfiable_at_fupd, satisfiable_at_mono; first apply Hsat'.
-  iIntros "(Hsrc & Href & Hthread)".
-  rewrite /thread_wps. iDestruct "Hthread" as "[Hthread _]".
-  rewrite rwp_unfold /rwp_pre to_of_val.
-  by iMod ("Hthread" with "[$]") as "($&$&$)".
-Qed.
-
-End refinements.
diff --git a/theories/program_logic/refinement/ref_ectx_lifting.v b/theories/program_logic/refinement/ref_ectx_lifting.v
deleted file mode 100644
index d6614261192f68e9d87e8ce990cc4792f63a0289..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/ref_ectx_lifting.v
+++ /dev/null
@@ -1,201 +0,0 @@
-(** Some derived lemmas for ectx-based languages *)
-From iris.program_logic Require Export ectx_language.
-
-From iris.program_logic.refinement Require Export ref_weakestpre ref_lifting.
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-Section rwp.
-Context {SI} {Σ: gFunctors SI} {A} {Λ: ectxLanguage} `{Hsrc: !source Σ A} `{Hiris: !ref_irisG Λ Σ}  `{Hexp: Inhabited (expr Λ)} `{Hstate: Inhabited (state Λ)}.
-Implicit Types s : stuckness.
-Implicit Types P Q : iProp Σ.
-Implicit Types a : A.
-Implicit Types b : bool.
-Implicit Types Φ : val Λ → iProp Σ.
-Hint Resolve head_prim_reducible head_reducible_prim_step : core.
-Hint Resolve (reducible_not_val _ inhabitant) : core.
-Hint Resolve head_stuck_stuck : core.
-
-
-(* refinement weakest precondition *)
-Lemma rwp_lift_head_step_fupd {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 n (a: A), source_interp a ∗ ref_state_interp σ1 n ={E,∅}=∗
-    ∃ b, ▷? b |={∅}=> ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      (if b then ∃ a' : A, ⌜a ↪⁺ a'⌝ ∗ source_interp a' else source_interp a) ∗
-      ref_state_interp σ2 (length efs + n) ∗
-      RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (?) "H". iApply rwp_lift_step_fupd=>//. iIntros (σ1 n a) "Hσ".
-  iMod ("H" with "Hσ") as (b) "H"; iExists b. iModIntro. iNext. iMod "H" as "[% H]". iModIntro.
-  iSplit; first by destruct s; eauto. iIntros (e2 σ2 efs κ ?).
-  iApply "H"; eauto.
-Qed.
-
-Lemma rwp_lift_atomic_head_step_fupd {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 n a, source_interp a ∗ ref_state_interp σ1 n ={E}=∗
-    ∃ b, ▷? b |={E}=> ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      (if b then ∃ (a': A), ⌜a ↪⁺ a'⌝ ∗ source_interp a' else source_interp a) ∗
-      ref_state_interp σ2 (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (?) "H". iApply rwp_lift_atomic_step_fupd; [done|].
-  iIntros (σ1 Qs a) "H'". iMod ("H" with "H'") as (b) "H'".
-  iModIntro. iExists b. iNext. iMod "H'" as "[% H']". iModIntro.
-  iSplit; first by destruct s; auto. iIntros (e2 σ2 efs κ Hstep).
-  iMod ("H'" with "[]"); eauto.
-Qed.
-
-Lemma rwp_lift_pure_head_step_no_fork s E Φ e1 :
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ κ σ1 e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (∀ κ e2 efs σ, ⌜head_step e1 σ κ e2 σ efs⌝ → RWP e2 @ s; E ⟨⟨ Φ ⟩⟩)%I
-  ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof using A Hexp Hiris Hsrc Hstate SI Λ Σ.
-  intros Hsafe Hstep.
-  iIntros "H". iApply rwp_lift_head_step_fupd; auto.
-  iIntros (σ1 n a) "[Ha Hσ]". iMod (fupd_intro_mask' E ∅) as "Hclose"; first set_solver.
-  iModIntro. iExists false. iModIntro; iSplit; auto.
-  iIntros (e2 σ2 efs κ H'). destruct (Hstep κ σ1 e2 σ2 efs) as (-> & <- & ->); auto.
-  iMod "Hclose" as "_". iModIntro.
-  iDestruct ("H" with "[//]") as "H". simpl. iFrame.
-Qed.
-
-Lemma rwp_lift_pure_det_head_step_no_fork {s E Φ} e1 e2 :
-  to_val e1 = None →
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs',
-    head_step e1 σ1 κ e2' σ2 efs' → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof using A Hexp Hiris Hsrc Hstate SI Λ Σ.
-  intros H2 Hstep Hpuredet.
-  iIntros "H". iApply rwp_lift_pure_head_step_no_fork; auto.
-  { naive_solver. }
-  iIntros (κ e' efs' σ (_&?&->&?)%Hpuredet); auto.
-Qed.
-
-
-(* lemmas for the indexed version *)
-Lemma rswp_lift_head_step_fupd {k s E Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E,∅}=∗
-    |={∅, ∅}▷=>^k ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_step_fupd=>//. iIntros (σ1 n) "Hσ".
-  iMod ("H" with "Hσ") as "H". iModIntro. iApply (step_fupdN_wand with "H").
-  iIntros "[% H]".
-  iSplit; first by destruct s; eauto.
-  iIntros (e2 σ2 efs κ ?).
-  iApply "H"; eauto.
-Qed.
-
-Lemma rswp_lift_atomic_head_step_fupd {k s E Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E}=∗
-    |={E,E}▷=>^k ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_atomic_step_fupd; eauto.
-  iIntros (σ1 Qs) "Hσ1". iMod ("H" with "Hσ1") as "H"; iModIntro.
-  iApply (step_fupdN_wand with "H"); iIntros "[% H]".
-  iSplit; first by destruct s; auto. iIntros (e2 σ2 efs κ Hstep).
-  iApply "H"; eauto.
-Qed.
-
-Lemma rswp_lift_atomic_head_step {k s E Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E}=∗
-    ▷^k (⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩))
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_atomic_head_step_fupd; eauto.
-  iIntros (σ1 Qs) "Hσ1". iMod ("H" with "Hσ1") as "H"; iModIntro.
-  by iApply step_fupdN_intro.
-Qed.
-
-Lemma rswp_lift_atomic_head_step_no_fork_fupd {k s E Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E}=∗
-    |={E,E}▷=>^k ⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ⌜efs = []⌝ ∗ ref_state_interp σ2 n ∗ from_option Φ False (to_val e2))
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_atomic_head_step_fupd; eauto.
-  iIntros (σ1 Qs) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "H"; iModIntro.
-  iApply (step_fupdN_wand with "H"); iIntros "[$ H]" (v2 σ2 efs κ Hstep).
-  iMod ("H" $! v2 σ2 efs with "[//]") as "(-> & ? & ?) /=". by iFrame.
-Qed.
-
-Lemma rswp_lift_atomic_head_step_no_fork {k s E Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E}=∗
-    ▷^k (⌜head_reducible e1 σ1⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜head_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ⌜efs = []⌝ ∗ ref_state_interp σ2 n ∗ from_option Φ False (to_val e2)))
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_atomic_head_step_no_fork_fupd.
-  iIntros (σ1 Qs) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "H"; iModIntro.
-  by iApply step_fupdN_intro.
-Qed.
-
-
-Lemma rswp_lift_pure_head_step_no_fork_fupd k s E Φ e1 :
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ κ σ1 e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (|={E,E}▷=>^k ∀ κ e2 efs σ, ⌜head_step e1 σ κ e2 σ efs⌝ → RWP e2 @ s; E ⟨⟨ Φ ⟩⟩)%I
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof using A Hexp Hiris Hsrc Hstate SI Λ Σ.
-  intros Hsafe Hstep.
-  iIntros "H". iApply rswp_lift_pure_step_no_fork; eauto.
-  iModIntro. iApply (step_fupdN_wand with "H"); iIntros "H" (κ e2 efs σ Hs).
-  iApply "H"; eauto.
-Qed.
-
-Lemma rswp_lift_pure_head_step_no_fork k s E Φ e1 :
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ κ σ1 e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (▷^k ∀ κ e2 efs σ, ⌜head_step e1 σ κ e2 σ efs⌝ → RWP e2 @ s; E ⟨⟨ Φ ⟩⟩)%I
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof using A Hexp Hiris Hsrc Hstate SI Λ Σ.
-  iIntros (Hsafe Hstep) "H". iApply rswp_lift_pure_head_step_no_fork_fupd; eauto.
-  by iApply step_fupdN_intro.
-Qed.
-
-Lemma rswp_lift_pure_det_head_step_no_fork_fupd {k s E Φ} e1 e2 :
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs',
-    head_step e1 σ1 κ e2' σ2 efs' → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (|={E,E}▷=>^k RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof using A Hexp Hiris Hsrc Hstate SI Λ Σ.
-  iIntros (Hstep Hdet) "H". iApply rswp_lift_pure_head_step_no_fork_fupd; eauto.
-  { naive_solver. }
-  iApply (step_fupdN_wand with "H"); by iIntros "H" (κ e2' efs σ (_&_&->&->)%Hdet).
-Qed.
-
-Lemma rswp_lift_pure_det_head_step_no_fork {k s E Φ} e1 e2 :
-  (∀ σ1, head_reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs',
-    head_step e1 σ1 κ e2' σ2 efs' → κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (▷^k RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof using A Hexp Hiris Hsrc Hstate SI Λ Σ.
-  iIntros (Hsafe Hstep) "H". iApply rswp_lift_pure_det_head_step_no_fork_fupd; eauto.
-  by iApply step_fupdN_intro.
-Qed.
-End rwp.
diff --git a/theories/program_logic/refinement/ref_lifting.v b/theories/program_logic/refinement/ref_lifting.v
deleted file mode 100644
index a1b1c4c6ba7012578ab46973b9cfc80b5116ce19..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/ref_lifting.v
+++ /dev/null
@@ -1,244 +0,0 @@
-From iris.proofmode Require Import tactics.
-Set Default Proof Using "Type".
-
-From iris.program_logic.refinement Require Export ref_weakestpre.
-(* TODO: move to the right place *)
-Section step_fupdN.
-
-  Context {SI} {PROP: sbi SI} `{FU: BiFUpd SI PROP}.
-
-  Lemma step_fupdN_mask_comm n E1 E2 E3 E4 (P: PROP):
-    E1 ⊆ E2 → E4 ⊆ E3 →
-    ((|={E1, E2}=>|={E2, E3}▷=>^n P) ⊢ |={E1, E4}▷=>^n |={E1, E2}=> P)%I.
-  Proof.
-    iIntros (Hsub1 Hsub2) "H". iInduction n as [|n] "IH"; auto; simpl.
-    iMod "H". iMod "H". iMod (fupd_intro_mask' E3 E4) as "Hclose"; auto.
-    iModIntro. iNext. iMod "Hclose". iMod "H".
-    iMod (fupd_intro_mask' E2 E1) as "Hclose'"; auto.
-    iModIntro. iApply "IH". iMod "Hclose'". by iModIntro.
-  Qed.
-
-  Lemma step_fupdN_mask_comm' n E1 E2 (P: PROP):
-    E2 ⊆ E1 →
-    ((|={E1, E1}▷=>^n |={E1, E2}=> P) ⊢ |={E1, E2}=> |={E2, E2}▷=>^n P)%I.
-  Proof.
-    iIntros (Hsub) "H". iInduction n as [|n] "IH"; auto; simpl.
-    iMod "H". iMod (fupd_intro_mask' E1 E2) as "Hclose"; auto.
-    do 2 iModIntro. iNext. iMod "Hclose". iMod "H". by iApply "IH".
-  Qed.
-
-
-End step_fupdN.
-
-
-Section lifting.
-Context {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} `{Inhabited (expr Λ)}.
-Implicit Types s : stuckness.
-Implicit Types P Q : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-Implicit Types a : A.
-Implicit Types b : bool.
-
-(* refinement weakest precondition *)
-Hint Resolve reducible_no_obs_reducible : core.
-
-Lemma rwp_lift_step_fupd s E Φ e1 :
-  to_val e1 = None →
-  (∀ σ1 n a, source_interp a ∗ ref_state_interp σ1 n ={E,∅}=∗
-  ∃ b, ▷? b |={∅}=> (⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-  ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ -∗ |={∅,E}=>
-    (if b then ∃ (a': A), ⌜a ↪⁺ a'⌝ ∗ source_interp a' else source_interp a) ∗
-    ref_state_interp σ2 (length efs + n) ∗ RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ∗ [∗ list] i ↦ ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩))
-  ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  by rewrite rwp_unfold /rwp_pre /rwp_step=> ->.
-Qed.
-
-Lemma rwp_lift_atomic_step_fupd {s E Φ} e1 :
-  to_val e1 = None →
-  (∀ σ1 n a, source_interp a ∗ ref_state_interp σ1 n ={E}=∗
-    ∃ b, ▷? b |={E}=> ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      (if b then ∃ (a': A), ⌜a ↪⁺ a'⌝ ∗ source_interp a' else source_interp a) ∗
-      ref_state_interp σ2 (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (?) "H".
-  iApply (rwp_lift_step_fupd s E _ e1)=>//; iIntros (σ1 n a) "H'".
-  iMod ("H" $! σ1 with "H'") as (b) "H". iExists b.
-  iMod (fupd_intro_mask' E ∅) as "Hclose"; first set_solver.
-  iModIntro. iNext. iMod "Hclose" as "_". iMod "H" as "[$ H]".
-  iMod (fupd_intro_mask' E ∅) as "Hclose"; first set_solver.
-  iIntros "!>" (e2 σ2 efs κ ?). iMod "Hclose" as "_".
-  iMod ("H" $! e2 σ2 efs with "[#]") as "($ & $ & H & $)"; [done|].
-  iModIntro.
-  destruct (to_val e2) eqn:?; last by iExFalso.
-  iApply rwp_value; last done. by apply of_to_val.
-Qed.
-
-Lemma rwp_lift_pure_step_no_fork `{!Inhabited (state Λ)} s E Φ e1 :
-  (∀ σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) →
-  (∀ κ σ1 e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (∀ κ e2 efs σ, ⌜prim_step e1 σ κ e2 σ efs⌝ → RWP e2 @ s; E ⟨⟨ Φ ⟩⟩)
-  ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (Hsafe Hstep) "H". iApply rwp_lift_step_fupd.
-  { specialize (Hsafe inhabitant). destruct s; eauto using reducible_not_val. }
-  iIntros (σ1 n e_s) "Hσ".
-  iMod fupd_intro_mask' as "Hclose"; last iModIntro; first by set_solver.
-  iExists false. iModIntro. iSplit.
-  { iPureIntro. destruct s; done. }
-  iIntros (e2 σ2 efs κ ?).
-  destruct (Hstep κ σ1 e2 σ2 efs) as (-> & <- & ->); auto.
-  iMod "Hclose" as "_". iModIntro.
-  iDestruct ("H" with "[//]") as "H". simpl. iFrame.
-Qed.
-
-Lemma rwp_lift_pure_det_step_no_fork `{!Inhabited (state Λ)} {s E Φ} e1 e2 :
-  (∀ σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) →
-  (∀ σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs' →
-    κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (? Hpuredet) "H". iApply (rwp_lift_pure_step_no_fork s E); try done.
-  { naive_solver. }
-  iIntros (κ e' efs' σ (_&?&->&?)%Hpuredet); auto.
-Qed.
-
-Lemma rwp_pure_step `{!Inhabited (state Λ)} s E e1 e2 φ n Φ :
-  PureExec φ n e1 e2 →
-  φ →
-  RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e1 @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (Hexec Hφ) "Hwp". specialize (Hexec Hφ).
-  iInduction Hexec as [e|n e1 e2 e3 [Hsafe ?]] "IH"; simpl; first done.
-  iApply rwp_lift_pure_det_step_no_fork.
-  - intros σ. specialize (Hsafe σ). destruct s; eauto using reducible_not_val.
-  - done.
-  - by iApply "IH".
-Qed.
-
-
-(* step refinement weakest lemmas *)
-Lemma rswp_lift_step_fupd k s E Φ e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E,∅}=∗
-    |={∅,∅}▷=>^k ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-     ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  rewrite rswp_unfold /rswp_def /rswp_step. iIntros "H" (σ1 n ?) "(?&Hσ)".
-  iMod ("H" with "Hσ") as "H". iModIntro. iApply (step_fupdN_wand with "H").
-  iIntros "($&H)". iFrame. eauto.
-Qed.
-
-Lemma rswp_lift_step k s E Φ e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E,∅}=∗
-    ▷^k (⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={∅,E}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩))
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_step_fupd. iIntros (??) "Hσ".
-  iMod ("H" with "Hσ") as "H". iIntros "!>". by iApply step_fupdN_intro.
-Qed.
-
-Lemma rswp_lift_pure_step_no_fork k s E E' Φ e1 :
-  (∀ σ1, s = NotStuck → reducible e1 σ1) →
-  (∀ κ σ1 e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs → κ = [] ∧ σ2 = σ1 ∧ efs = []) →
-  (|={E}=>|={E,E'}▷=>^k ∀ κ e2 efs σ, ⌜prim_step e1 σ κ e2 σ efs⌝ → RWP e2 @ s; E ⟨⟨ Φ ⟩⟩)
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (Hsafe Hstep) "H". iApply rswp_lift_step_fupd.
-  iIntros (σ1 n) "Hσ". iMod "H".
-  iMod fupd_intro_mask' as "Hclose"; last iModIntro; first by set_solver.
-  iApply (step_fupdN_wand with "[Hclose H]").
-  { iApply (step_fupdN_mask_comm _ _ E E'); first set_solver; first set_solver.
-  iMod "Hclose". by iModIntro. }
-  iIntros "H". iSplit.
-  { iPureIntro. destruct s; eauto. }
-  iIntros (e2 σ2 efs κ Hstep'). iMod "H"; iModIntro.
-  destruct (Hstep κ σ1 e2 σ2 efs) as (-> & <- & ->); auto.
-  iDestruct ("H" with "[//]") as "H". simpl. iFrame.
-Qed.
-
-Lemma rswp_lift_atomic_step_fupd {k s E1 Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E1}=∗
-  |={E1,E1}▷=>^k ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E1}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩)
-  ⊢ RSWP e1 at k @ s; E1 ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H".
-  iApply (rswp_lift_step_fupd k s E1 _ e1)=>//; iIntros (σ1 n) "Hσ1".
-  iMod ("H" $! σ1 with "Hσ1") as "H". iApply step_fupdN_mask_comm'; first set_solver.
-  iApply (step_fupdN_wand with "H"); iIntros "[% H]".
-  iMod (fupd_intro_mask' E1 ∅) as "Hclose"; first set_solver.
-  iModIntro; iSplit; auto.
-  iIntros (e2 σ2 efs κ Hstep). iMod "Hclose".
-  iMod ("H" with "[//]") as "($ & H & $)".
-  destruct (to_val e2) eqn:?; last by iExFalso.
-  iApply rwp_value; last done. by apply of_to_val.
-Qed.
-
-Lemma rswp_lift_atomic_step {k s E Φ} e1 :
-  (∀ σ1 n, ref_state_interp σ1 n ={E}=∗
-    ▷^k (⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-    ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ ={E}=∗
-      ref_state_interp σ2 (length efs + n) ∗
-      from_option Φ False (to_val e2) ∗
-      [∗ list] ef ∈ efs, RWP ef @ s; ⊤ ⟨⟨ ref_fork_post ⟩⟩))
-  ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply rswp_lift_atomic_step_fupd.
-  iIntros (??) "?". iMod ("H" with "[$]") as "H".
-  iIntros "!>". by iApply step_fupdN_intro; first done.
-Qed.
-
-Lemma rswp_lift_pure_det_step_no_fork {k s E E' Φ} e1 e2 :
-  (∀ σ1, s = NotStuck → reducible e1 σ1) →
-  (∀ σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs' →
-    κ = [] ∧ σ2 = σ1 ∧ e2' = e2 ∧ efs' = []) →
-  (|={E,E'}▷=>^k RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (? Hpuredet) "H". iApply (rswp_lift_pure_step_no_fork k s E); try done.
-  { naive_solver. }
-  iModIntro. iApply (step_fupdN_wand with "H"); iIntros "H".
-  iIntros (κ e' efs' σ (_&?&->&?)%Hpuredet); auto.
-Qed.
-
-
-(* RSWP lemmas are designed to be used with a single step only. The RSWP returns to RWP after a single step.*)
-Lemma rswp_pure_step_fupd k s E E' e1 e2 φ Φ `{!Inhabited (state Λ)} :
-  PureExec φ 1 e1 e2 →
-  φ →
-  (|={E,E'}▷=>^k RWP e2 @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (Hexec Hφ) "Hwp". specialize (Hexec Hφ).
-  inversion Hexec as [|n' ? e1' ? Hstep Hrest]; subst.
-  iApply rswp_lift_pure_det_step_no_fork.
-  - intros σ; intros ->; eauto using pure_step_safe, reducible_no_obs_reducible, reducible_not_val.
-  - eauto using pure_step_det.
-  - inversion Hrest; subst; eauto.
-Qed.
-
-Lemma rswp_pure_step_later `{!Inhabited (state Λ)} k s E e1 e2 φ Φ :
-  PureExec φ 1 e1 e2 →
-  φ →
-  ▷^k RWP e2 @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e1 at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  intros Hexec ?. rewrite -rswp_pure_step_fupd //. iIntros "H".
-  iApply step_fupdN_intro; eauto.
-Qed.
-
-End lifting.
diff --git a/theories/program_logic/refinement/ref_source.v b/theories/program_logic/refinement/ref_source.v
deleted file mode 100644
index e269ea4370de3765ea8e37e728fa008e9ddf9c92..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/ref_source.v
+++ /dev/null
@@ -1,372 +0,0 @@
-From iris.base_logic.lib Require Export fancy_updates.
-From iris.proofmode Require Import base tactics classes.
-From iris.algebra Require Import excl auth ord_stepindex arithmetic.
-Set Default Proof Using "Type".
-
-Class source {SI: indexT} (Σ: gFunctors SI) (A: Type) := mkSource {
-  source_rel : relation A;
-  source_interp : A → iProp Σ
-}.
-
-Infix "↪" := (source_rel) (at level 60).
-
-(* We use the transitive closure.
-   It's normalization is equivalent to normalization of source_rel. *)
-Infix "↪⁺" := (tc source_rel) (at level 60).
-
-Infix "↪⋆" := (rtc source_rel) (at level 60).
-
-Lemma sn_tc {X} (R: X → X → Prop) (x: X): sn R x ↔ sn (tc R) x.
-Proof.
-  split.
-  - induction 1 as [x _ IH]; constructor; simpl; intros y Hy; revert IH; simpl.
-    destruct Hy as [x y Honce|x y z Honce Hsteps]; intros IH; eauto.
-    destruct (IH _ Honce) as [Hy]; eauto.
-  - induction 1 as [z _ IH]; constructor; intros ??; apply IH; simpl in *; eauto using tc_once.
-Qed.
-
-
-
-Section src_update.
-  Context {SI A} {Σ: gFunctors SI} `{!source Σ A} `{!invG Σ}.
-
-  Definition src_update E (P: iProp Σ) : iProp Σ :=
-    (∀ a: A, source_interp a -∗ |={E}=> ∃ b: A, ⌜a ↪⁺ b⌝ ∗ source_interp b ∗ P)%I.
-
-  Definition weak_src_update E (P: iProp Σ) : iProp Σ :=
-    (∀ a: A, source_interp a -∗ |={E}=> ∃ b: A, ⌜a ↪⋆ b⌝ ∗ source_interp b ∗ P)%I.
-
-  Lemma src_update_bind E P Q: src_update E P ∗ (P -∗ src_update E Q) ⊢ src_update E Q.
-  Proof.
-    rewrite /src_update. iIntros "[P PQ]" (a) "Ha".
-    iMod ("P" $! a with "Ha") as (b Hab) "[Hb P]".
-    iSpecialize ("PQ" with "P").
-    iMod ("PQ" $! b with "Hb") as (c Hbc) "[Hc Q]".
-    iModIntro. iExists c. iFrame. iPureIntro.
-    by trans b.
-  Qed.
-
-  Lemma src_update_mono_fupd E P Q: src_update E P ∗ (P ={E}=∗ Q) ⊢ src_update E Q.
-  Proof.
-    iIntros "[HP PQ]". iIntros (a) "Hsrc".
-    iMod ("HP" with "Hsrc") as (b Hstep) "[Hsrc P]".
-    iMod ("PQ" with "P"). iFrame. iModIntro.
-    iExists b; by iFrame.
-  Qed.
-
-  Lemma src_update_mono E P Q: src_update E P ∗ (P -∗ Q) ⊢ src_update E Q.
-  Proof.
-    iIntros "[Hupd HPQ]". iApply (src_update_mono_fupd with "[$Hupd HPQ]").
-    iIntros "P". iModIntro. by iApply "HPQ".
-  Qed.
-
-  Lemma fupd_src_update E P : (|={E}=> src_update E P) ⊢ src_update E P.
-  Proof.
-    iIntros "H". rewrite /src_update. iIntros (e) "Hsrc".
-    iMod "H". by iApply "H".
-  Qed.
-
-  Lemma src_update_weak_src_update E P: src_update E P ⊢ weak_src_update E P.
-  Proof.
-    rewrite /src_update /weak_src_update. iIntros "P" (a) "Ha".
-    iMod ("P" $! a with "Ha") as (b Hab) "[Hb P]".
-    iModIntro. iExists b. iFrame. iPureIntro.
-    by apply tc_rtc.
-  Qed.
-
-  Lemma weak_src_update_return E P: P ⊢ weak_src_update E P.
-  Proof.
-    rewrite /src_update. iIntros "P" (a) "Ha".
-    iModIntro. iExists (a). iFrame. iPureIntro.
-    reflexivity.
-  Qed.
-
-  Lemma weak_src_update_bind_l E P Q: weak_src_update E P ∗ (P -∗ src_update E Q) ⊢ src_update E Q.
-  Proof.
-    rewrite /src_update. iIntros "[P PQ]" (a) "Ha".
-    iMod ("P" $! a with "Ha") as (b Hab) "[Hb P]".
-    iSpecialize ("PQ" with "P").
-    iMod ("PQ" $! b with "Hb") as (c Hbc) "[Hc Q]".
-    iModIntro. iExists c. iFrame. iPureIntro.
-    by eapply tc_rtc_l.
-  Qed.
-
-  Lemma weak_src_update_bind_r E P Q: src_update E P ∗ (P -∗ weak_src_update E Q) ⊢ src_update E Q.
-  Proof.
-    rewrite /src_update. iIntros "[P PQ]" (a) "Ha".
-    iMod ("P" $! a with "Ha") as (b Hab) "[Hb P]".
-    iSpecialize ("PQ" with "P").
-    iMod ("PQ" $! b with "Hb") as (c Hbc) "[Hc Q]".
-    iModIntro. iExists c. iFrame. iPureIntro.
-    by eapply tc_rtc_r.
-  Qed.
-
-  Lemma weak_src_update_mono_fupd E P Q: weak_src_update E P ∗ (P ={E}=∗ Q) ⊢ weak_src_update E Q.
-  Proof.
-    iIntros "[HP PQ]". iIntros (a) "Hsrc".
-    iMod ("HP" with "Hsrc") as (b Hstep) "[Hsrc P]".
-    iMod ("PQ" with "P"). iFrame. iModIntro.
-    iExists b; by iFrame.
-  Qed.
-
-  Lemma weak_src_update_mono E P Q: weak_src_update E P ∗ (P -∗ Q) ⊢ weak_src_update E Q.
-  Proof.
-    iIntros "[Hupd HPQ]". iApply (weak_src_update_mono_fupd with "[$Hupd HPQ]").
-    iIntros "P". iModIntro. by iApply "HPQ".
-  Qed.
-
-  Lemma fupd_weak_src_update E P : (|={E}=> weak_src_update E P) ⊢ weak_src_update E P.
-  Proof.
-    iIntros "H". rewrite /weak_src_update. iIntros (e) "Hsrc".
-    iMod "H". by iApply "H".
-  Qed.
-
-End src_update.
-
-
-Section auth_source.
-
-  Structure auth_source SI := {
-    auth_sourceUR :> ucmraT SI;
-    auth_source_discrete : CmraDiscrete auth_sourceUR;
-    auth_source_trans : relation auth_sourceUR;
-    auth_source_trans_proper: Proper (equiv ==> equiv ==> iff) auth_source_trans;
-    auth_source_step_frame (a a' f: auth_sourceUR):
-      auth_source_trans a a' → ✓ (a ⋅ f) → ✓ (a' ⋅ f) ∧ auth_source_trans (a ⋅ f) (a' ⋅ f);
-    auth_source_op_cancel (a f f': auth_sourceUR):
-      ✓ (a ⋅ f) → a ⋅ f ≡ a ⋅ f' → f ≡ f'
-  }.
-  Existing Instance auth_source_trans_proper.
-  Existing Instance auth_source_discrete.
-
-  Class auth_sourceG {SI} (Σ: gFunctors SI) (S: auth_source SI) := {
-    sourceG_inG :> inG Σ (authR S);
-    sourceG_name : gname;
-  }.
-
-  Global Instance source_auth_source {SI} (Σ: gFunctors SI) (S: auth_source SI) `{!auth_sourceG Σ S} : source Σ S  :=
-  {|
-    source_rel := auth_source_trans _ S;
-    source_interp a := own sourceG_name (● a)
-  |}.
-
-  Definition srcA {SI} {Σ: gFunctors SI} (S: auth_source SI) `{!auth_sourceG Σ S} (s: S) : iProp Σ := own sourceG_name (● s).
-  Definition srcF {SI} {Σ: gFunctors SI} (S: auth_source SI) `{!auth_sourceG Σ S} (s: S) : iProp Σ := own sourceG_name (◯ s).
-
-
-  Section auth_updates.
-    Context {SI} {Σ: gFunctors SI} (S: auth_source SI) `{!auth_sourceG Σ S}.
-
-    Lemma source_step_update (E_s e_s e_s': S):
-      ✓ E_s → e_s ≼ E_s → e_s ↪ e_s' → ∃ E_s', (E_s, e_s) ~l~> (E_s', e_s') ∧ E_s ↪ E_s'.
-    Proof.
-      intros Hv Hincl Hstep.
-      destruct Hincl as [e_f Heq]. erewrite Heq in Hv.
-      specialize (auth_source_step_frame _ S _ _ _ Hstep Hv) as [Hv' Hstep'].
-      exists (e_s' ⋅ e_f). split; rewrite Heq.
-      - intros α [e_f'|]; simpl; intros ? Heq'; split.
-        + by apply cmra_valid_validN.
-        + f_equiv. eapply discrete_iff; first apply _.
-          eapply discrete_iff in Heq'; last apply _.
-          eapply auth_source_op_cancel; last eauto; eauto.
-        + by apply cmra_valid_validN.
-        + specialize (ucmra_unit_right_id  e_s') as H'. rewrite -{2}H'. f_equiv.
-          eapply discrete_iff; first apply _.
-          eapply discrete_iff in Heq'; last apply _.
-          eapply auth_source_op_cancel; first apply Hv.
-          by rewrite ucmra_unit_right_id.
-      - eapply Hstep'.
-    Qed.
-
-    Lemma auth_src_update `{!invG Σ} E s s':
-      s ↪ s' → srcF S s ⊢ src_update E (srcF S s').
-    Proof.
-      intros Hstep. unfold src_update. iIntros "SF" (E_s). iIntros "SA".
-      iCombine "SA SF" as "S".
-      iPoseProof (own_valid_l with "S") as (Hv) "S".
-      apply auth_both_valid in Hv as [Hincl Hv].
-      eapply source_step_update in Hv as [E_s' [Hl Hstep']]; eauto.
-      iMod (own_update _ _ (● E_s' ⋅ ◯ s') with "S") as "S".
-      - by apply auth_update.
-      - iModIntro. iExists (E_s'); iDestruct "S" as "($ & $)".
-        iPureIntro; eauto using tc_once.
-    Qed.
-
-
-    Lemma srcF_split s t:
-      srcF S (s ⋅ t) ⊣⊢ srcF S s ∗ srcF S t.
-    Proof.
-      rewrite /srcF -own_op auth_frag_op //=.
-    Qed.
-  End auth_updates.
-
-End auth_source.
-
-Class Credit (SI: indexT) := credit_source: auth_source SI.
-Notation "$ a" := (srcF credit_source a) (at level 60).
-Notation "●$ a" := (srcA credit_source a) (at level 60).
-
-
-(* nat auth source *)
-Section nat_auth_source.
-
-  Context (SI: indexT).
-
-  Lemma nat_source_step_frame (a a' f : natR SI):
-    a' < a → ✓ (a ⋅ f) → ✓ (a' ⋅ f) ∧ (a' ⋅ f) < (a ⋅ f).
-  Proof.
-    intros Hαβ _; split; first done.
-    rewrite !nat_op_plus. lia.
-  Qed.
-
-  Lemma nat_source_op_cancel (a f f' : natR SI):
-      ✓ (a ⋅ f) → a ⋅ f = a ⋅ f' → f = f'.
-  Proof using SI.
-    intros _; rewrite !nat_op_plus. by intros H% Nat.add_cancel_l.
-  Qed.
-
-
-  (* we define an auth structure for ordinals *)
-  Program Canonical Structure natA : auth_source SI := {|
-    auth_sourceUR := natUR SI;
-    auth_source_trans := flip lt;
-    auth_source_discrete := _;
-    auth_source_trans_proper := _;
-    auth_source_step_frame := nat_source_step_frame;
-    auth_source_op_cancel := nat_source_op_cancel
-  |}.
-
-  Lemma nat_srcF_split `{!auth_sourceG Σ natA} (n m: nat):
-    srcF natA (n + m) ⊣⊢ srcF natA n ∗ srcF natA m.
-  Proof. apply srcF_split. Qed.
-
-  Lemma nat_srcF_succ `{!auth_sourceG Σ natA} (n: nat):
-    srcF natA (S n) ⊣⊢ srcF natA 1 ∗ srcF natA n.
-  Proof. rewrite -srcF_split //=. Qed.
-
-  Global Instance nat_credit `{!auth_sourceG Σ natA}: Credit SI := natA.
-
-End nat_auth_source.
-
-(* ord auth source *)
-Section ord_auth_source.
-
-  Context (SI: indexT).
-  Lemma ord_source_step_frame (a a' f : OrdR SI):
-    a' ≺ a → ✓ (a ⋅ f) → ✓ (a' ⋅ f) ∧ (a' ⋅ f) ≺ (a ⋅ f).
-  Proof.
-    intros Hαβ _; split; first done.
-    by eapply natural_addition_strict_compat.
-  Qed.
-
-  Lemma ord_source_op_cancel (a f f' : OrdR SI):
-      ✓ (a ⋅ f) → a ⋅ f = a ⋅ f' → f = f'.
-  Proof using SI.
-    intros _; rewrite comm_L [a ⋅ f']comm_L.
-    by apply natural_addition_cancel.
-  Qed.
-
-  (* we define an auth structure for ordinals *)
-  Program Canonical Structure ordA : auth_source SI := {|
-    auth_sourceUR := OrdUR SI;
-    auth_source_trans := flip (index_lt ordI);
-    auth_source_discrete := _;
-    auth_source_trans_proper := _;
-    auth_source_step_frame := ord_source_step_frame;
-    auth_source_op_cancel := ord_source_op_cancel
-  |}.
-
-  Lemma ord_srcF_split `{!auth_sourceG Σ ordA} (n m: Ord):
-    srcF ordA (n ⊕ m) ⊣⊢ srcF ordA n ∗ srcF ordA m.
-  Proof. apply srcF_split. Qed.
-
-  Definition one := succ zero.
-  Lemma ord_srcF_succ `{!auth_sourceG Σ ordA} (n: Ord):
-    srcF ordA (succ n) ⊣⊢ srcF ordA one ∗ srcF ordA n.
-  Proof.
-    rewrite -ord_srcF_split //= natural_addition_succ natural_addition_zero_left_id //=.
-  Qed.
-
-  Global Instance ord_credit `{!auth_sourceG Σ ordA}: Credit SI := ordA.
-
-End ord_auth_source.
-
-Inductive lex {X Y} (R: X → X → Prop) (S: Y → Y → Prop) : (X * Y) → (X * Y) -> Prop :=
-| lex_left x x' y y': R x x' → lex R S (x, y) (x', y')
-| lex_right x y y': S y y' → lex R S (x, y) (x, y').
-
-Lemma sn_lex {X Y} (R: X → X → Prop) (S: Y → Y → Prop) x y: sn R x -> (forall y, sn S y) → sn (lex R S) (x, y).
-Proof.
-  intros Sx Sy. revert y; induction Sx as [x _ IHx]; intros y.
-  induction (Sy y) as [y _ IHy].
-  constructor. intros [x' y']; simpl; inversion 1; subst.
-  - apply IHx; auto.
-  - apply IHy; auto.
-Qed.
-
-Lemma tc_lex_left {X Y} (R: X → X → Prop) (S: Y → Y → Prop) x x' y y': tc R x x' → tc (lex R S) (x, y) (x', y').
-Proof.
-  induction 1 as [x x' Hstep| x x' x'' Hstep Hsteps] in y, y'.
-  - constructor 1. by constructor.
-  - econstructor 2; eauto. by eapply (lex_left _ _ _ _ y y).
-Qed.
-
-Lemma tc_lex_right {X Y} (R: X → X → Prop) (S: Y → Y → Prop) x y y': tc S y y' → tc (lex R S) (x, y) (x, y').
-Proof.
-  induction 1 as [y y' Hstep|y y' y'' Hstep Hsteps].
-  - constructor 1. by constructor.
-  - econstructor 2; eauto. by constructor 2.
-Qed.
-
-Lemma lex_rtc {X Y} (R: X → X → Prop) (S: Y → Y → Prop) x x' y y': rtc (lex R S) (x, y) (x', y') → rtc R x x'.
-Proof.
-  remember (x, y) as p1. remember (x', y') as p2. intros Hrtc.
-  revert x x' y y' Heqp1 Heqp2. induction Hrtc as [p|p1 p2 p3 Hstep Hsteps IH]; intros x x' y y' -> Heq.
-  - injection Heq. by intros -> ->.
-  - subst p3. inversion Hstep; subst.
-    + etransitivity; last by eapply IH.
-      eapply rtc_l; by eauto.
-    + by eapply IH.
-Qed.
-
-
-(* stuttering: we can stutter with any auth source *)
-Section lexicographic.
-
-  Context {SI A B} {Σ: gFunctors SI} `{src1: !source Σ A} `{src2: !source Σ B}.
-
-  Global Instance lex_source : source Σ (A * B) := {|
-    source_rel := lex source_rel source_rel;
-    source_interp := (λ '(a, b), source_interp a ∗ source_interp b)%I;
-  |}.
-
-  Lemma source_update_embed_l_strong `{!invG Σ} E P Q:
-  @src_update _ _ Σ src1 _ E P ∗
-  (∀ b: B, source_interp b ={E}=∗ ∃ b': B, source_interp b' ∗ Q)
-  ⊢ @src_update _ _ Σ lex_source _ E (P ∗ Q).
-  Proof.
-    rewrite /src_update; simpl. iIntros "[H Hupd]".
-    iIntros ([a b]) "[Hs Hsrc]". iMod ("H" with "Hs") as (a' Hstep) "[SI P]".
-    iFrame. iMod ("Hupd" with "Hsrc") as (b') "[Hsrc $]". iModIntro. iExists (a', b'); iFrame.
-    iPureIntro. by apply tc_lex_left.
-  Qed.
-
-  Lemma source_update_embed_l `{!invG Σ} E P:
-    @src_update _ _ Σ src1 _ E P ⊢ @src_update _ _ Σ lex_source _ E P.
-  Proof.
-    iIntros "H". iPoseProof (source_update_embed_l_strong _ _ True%I with "[$H]") as "H".
-    - iIntros (b) "Hsrc". iModIntro. iExists b. iFrame.
-    - iApply src_update_mono; iFrame; iIntros "[$ _]".
-  Qed.
-
-  Lemma source_update_embed_r `{!invG Σ} E P:
-    @src_update _ _ Σ src2 _ E P ⊢ @src_update _ _ Σ lex_source _ E P.
-  Proof.
-    rewrite /src_update; simpl. iIntros "H".
-    iIntros ([a b]) "[Ha Hb]". iMod ("H" with "Hb") as (b' Hstep) "[SI P]".
-    iFrame. iModIntro. iExists (a, b'); iFrame.
-    iPureIntro. by apply tc_lex_right.
-  Qed.
-
-
-End lexicographic.
diff --git a/theories/program_logic/refinement/ref_weakestpre.v b/theories/program_logic/refinement/ref_weakestpre.v
deleted file mode 100644
index a04bc2706ecb9efb131748bc189f33e9e6709897..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/ref_weakestpre.v
+++ /dev/null
@@ -1,691 +0,0 @@
-From iris.program_logic Require Export language.
-From iris.bi Require Export fixpoint weakestpre.
-From iris.proofmode Require Import base tactics classes.
-From iris.algebra Require Import auth list.
-From iris.base_logic Require Export gen_heap.
-From iris.base_logic.lib Require Export fancy_updates logical_step.
-From iris.program_logic.refinement Require Export ref_source.
-Set Default Proof Using "Type".
-
-From iris.program_logic Require Import weakestpre.
-
-Class ref_irisG (Λ : language) {SI} (Σ : gFunctors SI) := IrisG {
-  ref_iris_invG :> invG Σ;
-  (** The state interpretation is an invariant that should hold in between each
-  step of reduction. Here [Λstate] is the global state and [nat] is the number of forked-off threads
-  (not the total number of threads, which is one higher because there is always
-  a main thread). *)
-  ref_state_interp : state Λ → nat → iProp Σ;
-
-  (** A fixed postcondition for any forked-off thread. For most languages, e.g.
-  heap_lang, this will simply be [True]. However, it is useful if one wants to
-  keep track of resources precisely, as in e.g. Iron. *)
-  ref_fork_post : val Λ → iProp Σ;
-}.
-
-(* we first define the core of the WP for the case that e1 is not a value.
-  Φ is the prop that needs to hold for the expression (and forked-off threads) that we step to. *)
-Definition rwp_step {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} E s (e1: expr Λ) (φ: expr Λ → list (expr Λ) → iProp Σ) : iProp Σ :=
-  (∀ σ1 n (a: A), source_interp a ∗ ref_state_interp σ1 n ={E,∅}=∗
-  ∃ b, ▷? b |={∅}=> (⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-  ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ -∗ |={∅,E}=> (
-    (if b then ∃ (a': A), ⌜a ↪⁺ a'⌝ ∗ source_interp a' else source_interp a) ∗
-    ref_state_interp σ2 (length efs + n) ∗ φ e2 efs)))%I.
-
-(* a "stronger" version: we cannot take a source step, but have to prove that the target
-  can take a step under k laters *)
-Definition rswp_step {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} (k: nat) E s (e1: expr Λ) (φ: expr Λ → list (expr Λ) → iProp Σ) : iProp Σ :=
-  (∀ σ1 n a, source_interp a ∗ ref_state_interp σ1 n ={E,∅}=∗
-  |={∅, ∅}▷=>^k (⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-  ∀ e2 σ2 efs κ, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ -∗ |={∅,E}=> (
-      source_interp a ∗
-      ref_state_interp σ2 (length efs + n) ∗ φ e2 efs)))%I.
-
-(* pre-definition of rwp of which we will take a fixpoint. *)
-Definition rwp_pre {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} (s: stuckness)
-    (rwp : coPset → expr Λ → (val Λ → iProp Σ) → iProp Σ) :
-    coPset → expr Λ → (val Λ → iProp Σ) → iProp Σ := λ E e1 Φ,
-  match to_val e1 with
-  | Some v => ∀ σ n a, source_interp a ∗ ref_state_interp σ n ={E}=∗ source_interp a ∗ ref_state_interp σ n ∗ Φ v
-  | None => rwp_step E s e1 (λ e2 efs, (rwp E e2 Φ) ∗ [∗ list] i ↦ ef ∈ efs, rwp ⊤ ef ref_fork_post)
-  end%I.
-
-Lemma rwp_pre_mono {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ}  s (wp1 wp2 : coPset → expr Λ → (val Λ → iProp Σ) → iProp Σ) :
-  ⊢ ((□ ∀ E e Φ, wp1 E e Φ -∗ wp2 E e Φ) →
-      ∀ E e Φ, rwp_pre s wp1 E e Φ -∗ rwp_pre s wp2 E e Φ)%I.
-Proof.
-iIntros "#H"; iIntros (E e1 Φ) "Hwp". rewrite /rwp_pre /rwp_step.
-destruct (to_val e1) as [v|]; first done.
-iIntros (σ1 n e_s) "Hσ". iMod ("Hwp" with "Hσ") as (b) "Hwp"; iModIntro.
-iExists b. iApply (bi.laterN_wand with "[] Hwp"). iNext. iIntros "Hwp". iMod "Hwp" as "($ & Hwp)". iModIntro.
-iIntros (e2 σ2 efs κ) "Hstep"; iMod ("Hwp" with "Hstep") as "(Hsrc & Hσ & Hwp & Hfork)".
-iModIntro; iFrame "Hsrc Hσ". iSplitL "Hwp"; first by iApply "H".
-iApply (@big_sepL_impl with "Hfork"); iIntros "!#" (k e _) "Hwp".
-  by iApply "H".
-Qed.
-
-(* Uncurry [rwp_pre] and equip its type with an OFE structure *)
-Definition rwp_pre' {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} (s : stuckness) :
-(prodO (prodO (leibnizO SI coPset) (exprO SI Λ)) (val Λ -d> iProp Σ) → iProp Σ) →
-prodO (prodO (leibnizO SI coPset) (exprO SI Λ)) (val Λ -d> iProp Σ) → iProp Σ
-:= curry3 ∘ rwp_pre s ∘ uncurry3.
-
-Local Instance rwp_pre_mono' {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} s :
-  BiMonoPred (rwp_pre' s).
-Proof.
-constructor.
-- iIntros (wp1 wp2) "#H"; iIntros ([[E e1] Φ]); iRevert (E e1 Φ).
-  iApply rwp_pre_mono. iIntros "!#" (E e Φ). iApply ("H" $! (E,e,Φ)).
-- intros wp Hwp n [[E1 e1] Φ1] [[E2 e2] Φ2]
-    [[?%leibniz_equiv ?%leibniz_equiv] ?]; simplify_eq/=.
-  rewrite /uncurry3 /rwp_pre /rwp_step. do 28 (f_equiv || done).
-  by apply pair_ne.
-Qed.
-
-(* take the least fixpoint of the above definition *)
-Definition rwp_def {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} (s : stuckness) (E : coPset)
-  (e : expr Λ) (Φ : val Λ → iProp Σ) : iProp Σ
-  := bi_least_fixpoint (rwp_pre' s) (E,e,Φ).
-Definition rwp_aux {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} : seal (@rwp_def SI Σ A Λ _ _). by eexists. Qed.
-Instance rwp' {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} : Rwp Λ (iProp Σ) stuckness := rwp_aux.(unseal).
-Definition rwp_eq {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} : rwp = @rwp_def SI Σ A Λ _ _ := rwp_aux.(seal_eq).
-
-(* take a rswp_step and afterwards, we prove an rwp *)
-Definition rswp_def {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} (k: nat) (s : stuckness) (E : coPset) (e : expr Λ) (Φ : val Λ → iProp Σ) : iProp Σ
-  := rswp_step k E s e (λ e2 efs, (rwp s E e2 Φ)
-                        ∗ [∗ list] i ↦ ef ∈ efs, rwp s ⊤ ef ref_fork_post)%I.
-Definition rswp_aux {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} : seal (@rswp_def SI Σ A Λ _ _). by eexists. Qed.
-Instance rswp' {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} : Rswp Λ (iProp Σ) stuckness := rswp_aux.(unseal).
-Definition rswp_eq {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ} : rswp = @rswp_def SI Σ A Λ _ _ := rswp_aux.(seal_eq).
-
-
-
-Section rwp.
-Context {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ}.
-Implicit Types s : stuckness.
-Implicit Types P : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-Implicit Types a : A.
-Implicit Types b : bool.
-
-(* Weakest pre *)
-Lemma rwp_unfold s E e Φ :
-  RWP e @ s; E ⟨⟨ Φ ⟩⟩ ⊣⊢ rwp_pre s (rwp (PROP:=iProp Σ) s) E e Φ.
-Proof. by rewrite rwp_eq /rwp_def least_fixpoint_unfold. Qed.
-
-
-Lemma rwp_strong_ind s Ψ :
-  (∀ n E e, Proper (pointwise_relation _ (dist n) ==> dist n) (Ψ E e))
-  → ⊢ (□ (∀ e E Φ, rwp_pre s (λ E e Φ, Ψ E e Φ ∧ RWP e @ s; E ⟨⟨ Φ ⟩⟩) E e Φ -∗ Ψ E e Φ)
-       → ∀ e E Φ, RWP e @ s; E ⟨⟨ Φ ⟩⟩ -∗ Ψ E e Φ)%I.
-Proof.
-  iIntros (HΨ). iIntros "#IH" (e E Φ) "H". rewrite rwp_eq.
-  set (Ψ' := curry3 Ψ :
-    prodO (prodO (leibnizO SI coPset) (exprO SI Λ)) (val Λ -d> iProp Σ) → iProp Σ).
-  assert (NonExpansive Ψ').
-  { intros n [[E1 e1] Φ1] [[E2 e2] Φ2]
-      [[?%leibniz_equiv ?%leibniz_equiv] ?]; simplify_eq/=. by apply HΨ. }
-  iApply (least_fixpoint_strong_ind _ Ψ' with "[] H").
-  iIntros "!#" ([[??] ?]) "H". by iApply "IH".
-Qed.
-
-Lemma rwp_ind s Ψ :
-  (∀ n E e, Proper (pointwise_relation _ (dist n) ==> dist n) (Ψ E e))
-  → ⊢ (□ (∀ e E Φ, rwp_pre s (λ E e Φ, Ψ E e Φ) E e Φ -∗ Ψ E e Φ)
-       → ∀ e E Φ, RWP e @ s; E ⟨⟨ Φ ⟩⟩ -∗ Ψ E e Φ)%I.
-Proof.
-  iIntros (HΨ) "#H". iApply rwp_strong_ind. iIntros "!>" (e E Φ) "Hrwp".
-  iApply "H". iApply (rwp_pre_mono with "[] Hrwp"). clear.
-  iIntros "!>" (E e Φ) "[$ _]".
-Qed.
-
-Global Instance rwp_ne s E e n :
-  Proper (pointwise_relation _ (dist n) ==> dist n) (rwp (PROP:=iProp Σ) s E e).
-Proof.
-  intros Φ1 Φ2 HΦ. rewrite !rwp_eq. by apply (least_fixpoint_ne _), pair_ne, HΦ.
-Qed.
-
-Global Instance rwp_proper s E e :
-  Proper (pointwise_relation _ (≡) ==> (≡)) (rwp (PROP:=iProp Σ) s E e).
-Proof.
-  by intros Φ Φ' ?; apply equiv_dist=>n; apply rwp_ne=>v; apply equiv_dist.
-Qed.
-
-Lemma rwp_value' s E Φ v : Φ v ⊢ RWP of_val v @ s; E ⟨⟨ Φ ⟩⟩.
-Proof. iIntros "HΦ". rewrite rwp_unfold /rwp_pre to_of_val. iIntros (???) "($&$)". auto. Qed.
-(*
-Lemma rwp_value_inv' s E Φ v : RWP of_val v @ s; E ⟨⟨ Φ ⟩⟩ ={E}=∗ Φ v.
-Proof. by rewrite rwp_unfold /rwp_pre to_of_val. Qed.
-*)
-
-
-Lemma rwp_strong_mono' s1 s2 E1 E2 e Φ Ψ :
-  s1 ⊑ s2 → E1 ⊆ E2 →
-  RWP e @ s1; E1 ⟨⟨ Φ ⟩⟩ -∗
-  (∀ σ n a v, source_interp a ∗ ref_state_interp σ n ∗ Φ v ={E2}=∗
-              source_interp a ∗ ref_state_interp σ n ∗ Ψ v) -∗
-  RWP e @ s2; E2 ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros (? HE) "H HΦ". iRevert (E2 Ψ HE) "HΦ"; iRevert (e E1 Φ) "H".
-  iApply rwp_ind; first solve_proper.
-  iIntros "!#" (e E1 Φ) "IH"; iIntros (E2 Ψ HE) "HΦ".
-  rewrite !rwp_unfold /rwp_pre /rwp_step.
-  destruct (to_val e) as [v|] eqn:?.
-  { iIntros (???) "H".
-    iSpecialize ("IH" with "[$]").
-    iMod (fupd_mask_mono with "IH") as "(H1&H2&H)"; auto.
-    by iApply ("HΦ" with "[$]"). }
-  iIntros (σ1 n e_s) "Hσ". iMod (fupd_intro_mask' E2 E1) as "Hclose"; first done.
-  iMod ("IH" with "[$]") as "IH". iModIntro. iDestruct "IH" as (b) "IH". iExists b.
-  iNext. iMod "IH" as "[? IH]"; iModIntro.
-  iSplit; [by destruct s1, s2|]. iIntros (e2 σ2 efs κ Hstep).
-  iSpecialize ("IH" with "[//]"). iMod "IH". iMod "Hclose" as "_". iModIntro.
-  iDestruct "IH" as "($ & $ & IH & Hefs)". iSplitR "Hefs".
-  - iApply ("IH" with "[//] HΦ").
-  - iApply (big_sepL_impl with "Hefs"); iIntros "!#" (k ef _).
-    iIntros "IH". iApply ("IH" with "[]"); auto.
-Qed.
-
-Lemma rwp_strong_mono s1 s2 E1 E2 e Φ Ψ :
-  s1 ⊑ s2 → E1 ⊆ E2 →
-  RWP e @ s1; E1 ⟨⟨ Φ ⟩⟩ -∗ (∀ v, Φ v ={E2}=∗ Ψ v) -∗ RWP e @ s2; E2 ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros (??) "Hrwp H". iApply (rwp_strong_mono' with "[$]"); auto.
-  iIntros (????) "($&$&HΦ)". by iApply "H".
-Qed.
-
-Lemma fupd_rwp s E e Φ : (|={E}=> RWP e @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  rewrite rwp_unfold /rwp_pre. iIntros "H". destruct (to_val e) as [v|] eqn:?.
-  { by iMod "H". }
-  iIntros (σ1 n e_s) "HS". iMod "H". by iApply "H".
-Qed.
-Lemma fupd_rwp' s E e Φ : (∀ σ1 n a, source_interp a ∗ ref_state_interp σ1 n ={E}=∗
-                                     source_interp a ∗ ref_state_interp σ1 n ∗
-                                     RWP e @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H".
-  iEval (rewrite rwp_unfold /rwp_pre). destruct (to_val e) as [v|] eqn:Heq.
-  { iIntros. iSpecialize ("H" with "[$]"). rewrite rwp_unfold /rwp_pre Heq.
-    iMod "H" as "(H1&H2&Hwand)". by iMod ("Hwand" with "[$]") as "$". }
-  iIntros (σ1 n e_s) "HS".
-  iSpecialize ("H" with "[$]"). rewrite rwp_unfold /rwp_pre Heq.
-  iMod "H" as "(H1&H2&Hwand)". by iMod ("Hwand" with "[$]") as "$".
-Qed.
-Lemma rwp_fupd s E e Φ : RWP e @ s; E ⟨⟨ v, |={E}=> Φ v ⟩⟩ ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof. iIntros "H". iApply (rwp_strong_mono s s E with "H"); auto. Qed.
-
-Lemma rwp_fupd' s E e Φ : RWP e @ s; E ⟨⟨ v, ∀ σ1 n a, source_interp a ∗ ref_state_interp σ1 n ={E}=∗
-                                                        source_interp a ∗ ref_state_interp σ1 n ∗ Φ v⟩⟩
-                          ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". iApply (rwp_strong_mono' s s E with "H"); auto. iIntros (????) "(?&?&H)".
-  by iMod ("H" with "[$]").
-Qed.
-
-
-(* TODO: We do not need StronglyAtomic for the definition with a single later but for the definition with a logical step. *)
-Lemma rwp_atomic E1 E2 e s Φ `{!Atomic StronglyAtomic e} :
-  (|={E1,E2}=> RWP e @ s; E2 ⟨⟨ v, |={E2,E1}=> Φ v ⟩⟩) ⊢ RWP e @ s; E1 ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". rewrite !rwp_unfold /rwp_pre.
-  destruct (to_val e) as [v|] eqn:He.
-  { iIntros. iMod ("H"). iMod ("H" with "[$]") as "($&$&$)". }
-  iIntros (σ1 n e_s) "Hσ". iMod "H".
-  iMod ("H" $! σ1 with "Hσ") as "H". iModIntro.
-  iDestruct "H" as (b) "H". iExists b. iNext. iMod "H" as "[$ H]"; iModIntro.
-  iIntros (e2 σ2 efs κ Hstep). iSpecialize ("H" with "[//]"). iMod "H".
-  iDestruct "H" as "(Hsrc & Hσ & H & Hefs)".
-  rewrite rwp_unfold /rwp_pre. destruct (to_val e2) as [v2|] eqn:He2.
-  - rewrite rwp_unfold /rwp_pre He2.
-    destruct b.
-    * iDestruct "Hsrc" as (??) "H'". iMod ("H" with "[$]") as "(Hsrc&$&H)".
-      iFrame. iMod "H". iIntros "!>".
-      iSplitL "Hsrc"; first eauto.
-      iIntros (???) "(?&?) !>". iFrame.
-    * iMod ("H" with "[$]") as "(Hsrc&$&H)".
-      iFrame. iMod "H". iIntros "!>".
-      iIntros (???) "(?&?) !>". iFrame.
-  - specialize (atomic _ _ _ _ _ Hstep) as []; congruence.
-Qed.
-
-Lemma rwp_bind K `{!LanguageCtx K} s E e Φ :
-  RWP e @ s; E ⟨⟨ v, RWP K (of_val v) @ s; E ⟨⟨ Φ ⟩⟩ ⟩⟩ ⊢ RWP K e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  revert Φ. cut (∀ Φ', RWP e @ s; E ⟨⟨ Φ' ⟩⟩ -∗ ∀ Φ,
-  (∀ v, Φ' v -∗ RWP K (of_val v) @ s; E ⟨⟨ Φ ⟩⟩) -∗ RWP K e @ s; E ⟨⟨ Φ ⟩⟩).
-  { iIntros (help Φ) "H". iApply (help with "H"); auto. }
-  iIntros (Φ') "H". iRevert (e E Φ') "H". iApply rwp_strong_ind; first solve_proper.
-  iIntros "!#" (e E1 Φ') "IH". iIntros (Φ) "HΦ".
-  rewrite /rwp_pre /rwp_step.
-  destruct (to_val e) as [v|] eqn:He.
-  { apply of_to_val in He as <-. iApply fupd_rwp'.
-    iIntros. iMod ("IH" with "[$]") as "($&$&H)".
-      by iApply "HΦ". }
-  rewrite rwp_unfold /rwp_pre /rwp_step fill_not_val //.
-  iIntros (σ1 n a) "H". iMod ("IH" with "H") as "IH". iModIntro.
-  iDestruct "IH" as (b) "IH". iExists b. iNext.
-  iMod "IH" as "[% IH]"; iModIntro. iSplit.
-  { iPureIntro. destruct s; last done.
-    unfold reducible in *. naive_solver eauto using fill_step. }
-  iIntros (e2 σ2 efs κ Hstep).
-  destruct (fill_step_inv e σ1 κ e2 σ2 efs) as (e2'&->&?); auto.
-  iMod ("IH" $! e2' σ2 efs with "[//]") as "($ & $ & IH & IHfork)". iIntros "!>".
-  iSplitL "IH HΦ".
-  - iDestruct "IH" as "[IH _]". by iApply "IH".
-  - by setoid_rewrite bi.and_elim_r.
-Qed.
-
-
-Lemma rwp_bind_inv K `{!LanguageCtx K} s E e Φ :
-  RWP K e @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s; E ⟨⟨ v, RWP K (of_val v) @ s; E ⟨⟨ Φ ⟩⟩ ⟩⟩.
-Proof.
-  iIntros "H". remember (K e) as e' eqn:He'.
-  iRevert (e He'). iRevert (e' E Φ) "H". iApply rwp_strong_ind; first solve_proper.
-  iIntros "!#" (e' E1 Φ) "IH". iIntros (e ->).
-  rewrite !rwp_unfold {2}/rwp_pre.
-  destruct (to_val e) as [v|] eqn:He.
-  { iIntros (???) "($&$)". iModIntro. apply of_to_val in He as <-. rewrite !rwp_unfold.
-    iApply (rwp_pre_mono with "[] IH"). by iIntros "!#" (E e Φ') "[_ ?]". }
-  rewrite /rwp_pre fill_not_val //.
-  iIntros (σ1 κs n) "Hσ". iMod ("IH" with "[$]") as (b) "IH". iModIntro.
-  iExists b. iNext. iMod "IH" as "[% IH]"; iModIntro. iSplit.
-  { destruct s; eauto using reducible_fill. }
-  iIntros (e2 σ2 efs κ Hstep).
-  iMod ("IH" $! (K e2) σ2 efs κ with "[]") as "(Hsrc & Hσ & IH & IHefs)"; eauto using fill_step.
-  iModIntro. iFrame "Hsrc Hσ". iSplitR "IHefs".
-  - iDestruct "IH" as "[IH _]". by iApply "IH".
-  - by setoid_rewrite bi.and_elim_r.
-Qed.
-
-(** * Derived rules *)
-Lemma rwp_mono s E e Φ Ψ : (∀ v, Φ v ⊢ Ψ v) → RWP e @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros (HΦ) "H"; iApply (rwp_strong_mono with "H"); auto.
-  iIntros (v) "?". by iApply HΦ.
-Qed.
-Lemma rwp_stuck_mono s1 s2 E e Φ :
-  s1 ⊑ s2 → RWP e @ s1; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s2; E ⟨⟨ Φ ⟩⟩.
-Proof. iIntros (?) "H". iApply (rwp_strong_mono with "H"); auto. Qed.
-Lemma rwp_stuck_weaken s E e Φ :
-  RWP e @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ E ?⟨⟨ Φ ⟩⟩.
-Proof. apply rwp_stuck_mono. by destruct s. Qed.
-Lemma rwp_mask_mono s E1 E2 e Φ : E1 ⊆ E2 → RWP e @ s; E1 ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s; E2 ⟨⟨ Φ ⟩⟩.
-Proof. iIntros (?) "H"; iApply (rwp_strong_mono with "H"); auto. Qed.
-Global Instance rwp_mono' s E e :
-  Proper (pointwise_relation _ (⊢) ==> (⊢)) (rwp (PROP:=iProp Σ) s E e).
-Proof. by intros Φ Φ' ?; apply rwp_mono. Qed.
-
-Lemma rwp_value s E Φ e v : IntoVal e v → Φ v ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof. intros <-. by apply rwp_value'. Qed.
-Lemma rwp_value_fupd' s E Φ v : (|={E}=> Φ v) ⊢ RWP of_val v @ s; E ⟨⟨ Φ ⟩⟩.
-Proof. intros. by rewrite -rwp_fupd -rwp_value'. Qed.
-Lemma rwp_value_fupd s E Φ e v `{!IntoVal e v} :
-  (|={E}=> Φ v) ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof. intros. rewrite -rwp_fupd -rwp_value //. Qed.
-(*
-Lemma rwp_value_inv s E Φ e v : IntoVal e v → RWP e @ s; E ⟨⟨ Φ ⟩⟩ ={E}=∗ Φ v.
-Proof. intros <-. by apply rwp_value_inv'. Qed.
-*)
-
-Lemma rwp_frame_l s E e Φ R : R ∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s; E ⟨⟨ v, R ∗ Φ v ⟩⟩.
-Proof. iIntros "[? H]". iApply (rwp_strong_mono with "H"); auto with iFrame. Qed.
-Lemma rwp_frame_r s E e Φ R : RWP e @ s; E ⟨⟨ Φ ⟩⟩ ∗ R ⊢ RWP e @ s; E ⟨⟨ v, Φ v ∗ R ⟩⟩.
-Proof. iIntros "[H ?]". iApply (rwp_strong_mono with "H"); auto with iFrame. Qed.
-
-Lemma rwp_wand s E e Φ Ψ :
-  RWP e @ s; E ⟨⟨ Φ ⟩⟩ -∗ (∀ v, Φ v -∗ Ψ v) -∗ RWP e @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros "Hwp H". iApply (rwp_strong_mono with "Hwp"); auto.
-  iIntros (?) "?". by iApply "H".
-Qed.
-Lemma rwp_wand_l s E e Φ Ψ :
-  (∀ v, Φ v -∗ Ψ v) ∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof. iIntros "[H Hwp]". iApply (rwp_wand with "Hwp H"). Qed.
-Lemma rwp_wand_r s E e Φ Ψ :
-  RWP e @ s; E ⟨⟨ Φ ⟩⟩ ∗ (∀ v, Φ v -∗ Ψ v) ⊢ RWP e @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof. iIntros "[Hwp H]". iApply (rwp_wand with "Hwp H"). Qed.
-Lemma rwp_frame_wand_l s E e Q Φ :
-  Q ∗ RWP e @ s; E ⟨⟨ v, Q -∗ Φ v ⟩⟩ -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "[HQ HRWP]". iApply (rwp_wand with "HRWP").
-  iIntros (v) "HΦ". by iApply "HΦ".
-Qed.
-
-End rwp.
-
-
-Section rswp.
-Context {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ}.
-Implicit Types s : stuckness.
-Implicit Types P : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-Implicit Types a : A.
-Implicit Types b : bool.
-Implicit Types k : nat.
-
-(* Weakest pre *)
-Lemma rswp_unfold k s E e Φ :
-  RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊣⊢ rswp_def k s E e Φ.
-Proof. by rewrite rswp_eq. Qed.
-
-
-Global Instance rswp_ne k s E e n :
-  Proper (pointwise_relation _ (dist n) ==> dist n) (rswp (PROP:=iProp Σ) k s E e).
-Proof.
-  intros Φ1 Φ2 HΦ. rewrite !rswp_eq /rswp_def /rswp_step.
-  do 20 f_equiv. by rewrite HΦ.
-Qed.
-
-Global Instance rswp_proper s E e :
-  Proper (pointwise_relation _ (≡) ==> (≡)) (rwp (PROP:=iProp Σ) s E e).
-Proof.
-  apply _.
-Qed.
-
-Lemma rswp_strong_mono k s1 s2 E1 E2 e Φ Ψ :
-  s1 ⊑ s2 → E1 ⊆ E2 →
-  RSWP e at k @ s1; E1 ⟨⟨ Φ ⟩⟩ -∗ (∀ v, Φ v ={E2}=∗ Ψ v) -∗ RSWP e at k @ s2; E2 ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros (? HE); rewrite !rswp_eq /rswp_def /rswp_step.
-  iIntros "H HΦ" (σ1 n a) "Hσ". iMod (fupd_intro_mask' E2 E1) as "Hclose"; first done.
-  iMod ("H" with "[$]") as "H". iModIntro. iApply (step_fupdN_wand with "H").
-  iIntros "[H' H]". iSplit; [by destruct s1, s2|]. iIntros (e2 σ2 efs κ Hstep).
-  iSpecialize ("H" with "[//]"). iMod "H". iMod "Hclose" as "_". iModIntro.
-  iDestruct "H" as "($ & $ & H & Hefs)". iSplitR "Hefs".
-  - iApply (rwp_strong_mono with "H"); auto.
-  - iApply (big_sepL_impl with "Hefs"); iIntros "!#" (k' ef _).
-    iIntros "H"; iApply (rwp_strong_mono with "H"); auto.
-Qed.
-
-
-Lemma fupd_rswp k s E e Φ : (|={E}=> RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩) ⊢ RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  rewrite rswp_eq /rswp_def /rswp_step. iIntros "H".
-  iIntros (σ1 n a) "HS". iMod "H". by iApply "H".
-Qed.
-Lemma rswp_fupd k s E e Φ : RSWP e at k @ s; E ⟨⟨ v, |={E}=> Φ v ⟩⟩ ⊢ RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof. iIntros "H". iApply (rswp_strong_mono k s s E with "H"); auto. Qed.
-
-
-(* do not take a source step, end up with an rswp with no later budget *)
-Lemma rwp_no_step E e s Φ:
-  to_val e = None →
-  (RSWP e at 0 @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RWP e @ s; E ⟨⟨ Φ ⟩⟩)%I.
-Proof.
-  rewrite rswp_eq rwp_unfold /rswp_def /rwp_pre /rswp_step /rwp_step.
-  iIntros (He) "Hswp". rewrite He. iIntros (σ1 n a) "[Ha Hσ]".
-  iMod ("Hswp" with "[$]") as "[$ Hswp]". iModIntro.
-  iExists false. iModIntro. iIntros (e2 σ2 efs κ Hstep).
-  by iMod ("Hswp" with "[//]") as "($ & $ & $)".
-Qed.
-
-(* take a source step, end up with an rswp with a budget of one later *)
-Lemma rwp_take_step P E e s Φ:
-  to_val e = None
-  → ⊢ ((P -∗ RSWP e at 1 @ s; E ⟨⟨ Φ ⟩⟩) -∗ src_update E P -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩)%I.
-Proof.
-  rewrite rswp_eq rwp_unfold /rswp_def /rwp_pre /rswp_step /rwp_step.
-  iIntros (He) "Hswp Hsrc". rewrite He. iIntros (σ1 n a) "[Ha Hσ]". rewrite /src_update.
-  iMod ("Hsrc" with "Ha") as (a' Ha) "(Hsource_interp & P)". iMod ("Hswp" with "P [$]") as "Hswp".
-  iMod "Hswp". iModIntro. iExists true. iNext. iMod "Hswp" as "[$ Hswp]"; iModIntro.
-  iIntros (e2 σ2 efs κ Hstep'). iMod ("Hswp" with "[//]") as "(Hsrc & $ & Hrwp & $)".
-  iModIntro; iFrame. iExists a'; iSplit; eauto.
-Qed.
-
-Lemma rwp_weaken' P E e s Φ:
-  to_val e = None
-  → ⊢ ((P -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩) -∗ weak_src_update E P -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩)%I.
-Proof.
-  rewrite rwp_unfold /rwp_pre /rwp_step.
-  iIntros (He) "Hwp Hsrc". rewrite He. iIntros (σ1 n a) "[Ha Hσ]". rewrite /src_update.
-  iMod ("Hsrc" with "Ha") as (a' Ha) "(Hsource_interp & P)". iMod ("Hwp" with "P [$Hsource_interp $Hσ]") as (b) "Hwp".
-  iModIntro. destruct Ha as [a|].
-  { iExists b. iFrame. }
-  iExists true. destruct b; iNext.
-  - iMod "Hwp" as "[$ Hwp]"; iModIntro.
-    iIntros (e2 σ2 efs κ Hstep'); iMod ("Hwp" with "[//]") as "(Hstep & $ & $)"; iModIntro.
-    iDestruct "Hstep" as (a' Hsteps) "S". iExists a'. iFrame. iPureIntro.
-    eapply tc_l, tc_rtc_l; eauto.
-  - iMod "Hwp" as "[$ Hwp]"; iModIntro.
-    iIntros (e2 σ2 efs κ Hstep'); iMod ("Hwp" with "[//]") as "(Hstep & $ & $)"; iModIntro.
-    iExists z. iFrame. iPureIntro.
-    eapply tc_rtc_r; eauto. by apply tc_once.
-Qed.
-
-Lemma rwp_weaken P E e s Φ:
-  to_val e = None
-  → ⊢ ((P -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩) -∗ src_update E P -∗ RWP e @ s; E ⟨⟨ Φ ⟩⟩)%I.
-Proof.
-  intros H. rewrite src_update_weak_src_update. by apply rwp_weaken'.
-Qed.
-
-Lemma rswp_do_step k E e s Φ:
-  ▷ RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at (S k) @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  rewrite rswp_eq /rswp_def /rswp_step.
-  iIntros "H". iIntros (σ1 n a) "Hσ". iMod (fupd_intro_mask' _ ∅) as "Hclose"; first set_solver.
-  simpl; do 2 iModIntro. iNext. iSpecialize ("H" with "Hσ"). by iMod "Hclose".
-Qed.
-
-(* TODO: We do not need StronglyAtomic for the definition with a single later but for the definition with a logical step. *)
-Lemma rswp_atomic k E1 E2 e s Φ `{!Atomic StronglyAtomic e} :
-  (|={E1,E2}=> RSWP e at k @ s; E2 ⟨⟨ v, |={E2,E1}=> Φ v ⟩⟩) ⊢ RSWP e at k @ s; E1 ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "H". rewrite !rswp_eq /rswp_def /rswp_step.
-  iIntros (σ1 n a) "Hσ". iMod "H".
-  iMod ("H" $! σ1 with "Hσ") as "H". iModIntro.
-  iApply (step_fupdN_wand with "H"); iIntros "[$ H]".
-  iIntros (e2 σ2 efs κ Hstep). iSpecialize ("H" with "[//]"). iMod "H".
-  iDestruct "H" as "(? & Hσ & H & Hefs)".
-  rewrite rwp_unfold /rwp_pre. destruct (to_val e2) as [v2|] eqn:He2.
-  - rewrite rwp_unfold /rwp_pre He2. iDestruct ("H" with "[$]") as ">($&$&>$)". iFrame. eauto.
-  - specialize (atomic _ _ _ _ _ Hstep) as []; congruence.
-Qed.
-
-Lemma rswp_bind K `{!LanguageCtx K} k s E e Φ :
-  to_val e = None →
-  RSWP e at k @ s; E ⟨⟨ v, RWP K (of_val v) @ s; E ⟨⟨ Φ ⟩⟩ ⟩⟩ ⊢ RSWP K e at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros (He) "H". rewrite !rswp_eq /rswp_def /rswp_step.
-  iIntros (σ1 n a) "Hσ". iMod ("H" with "Hσ") as "H".
-  iModIntro. iApply (step_fupdN_wand with "H").
-  iIntros "[% H]". iSplit.
-  { iPureIntro. destruct s; last done.
-    unfold reducible in *. naive_solver eauto using fill_step. }
-  iIntros (e2 σ2 efs κ Hstep).
-  destruct (fill_step_inv e σ1 κ e2 σ2 efs) as (e2'&->&?); auto.
-  iMod ("H" $! e2' σ2 efs with "[//]") as "($ & $ & H & $)". iIntros "!>".
-  by iApply rwp_bind.
-Qed.
-
-
-Lemma rswp_bind_inv K `{!LanguageCtx K} k s E e Φ :
-  to_val e = None →
-  RSWP K e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ s; E ⟨⟨ v, RWP K (of_val v) @ s; E ⟨⟨ Φ ⟩⟩ ⟩⟩.
-Proof.
-  iIntros (He) "H". rewrite !rswp_eq /rswp_def /rswp_step.
-  iIntros (σ1 n a) "Hσ". iMod ("H" with "Hσ") as "H".
-  iModIntro. iApply (step_fupdN_wand with "H").
-  iIntros "[% H]". iSplit.
-  { destruct s; eauto using reducible_fill. }
-  iIntros (e2 σ2 efs κ Hstep).
-  iMod ("H" $! (K e2) σ2 efs κ with "[]") as "($ & $ & H & $)"; eauto using fill_step.
-  iModIntro. by iApply rwp_bind_inv.
-Qed.
-
-(** * Derived rules *)
-Lemma rswp_mono k s E e Φ Ψ : (∀ v, Φ v ⊢ Ψ v) → RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros (HΦ) "H". iApply (rswp_strong_mono with "[H] []"); auto.
-  iIntros (v) "?". by iApply HΦ.
-Qed.
-Lemma rswp_stuck_mono k s1 s2 E e Φ :
-  s1 ⊑ s2 → RSWP e at k @ s1; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ s2; E ⟨⟨ Φ ⟩⟩.
-Proof. iIntros (?) "H". iApply (rswp_strong_mono with "H"); auto. Qed.
-Lemma rswp_stuck_weaken k s E e Φ :
-  RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ E ?⟨⟨ Φ ⟩⟩.
-Proof. apply rswp_stuck_mono. by destruct s. Qed.
-Lemma rswp_mask_mono k s E1 E2 e Φ : E1 ⊆ E2 → RSWP e at k @ s; E1 ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ s; E2 ⟨⟨ Φ ⟩⟩.
-Proof. iIntros (?) "H"; iApply (rswp_strong_mono with "H"); auto. Qed.
-Global Instance rswp_mono' k s E e :
-  Proper (pointwise_relation _ (⊢) ==> (⊢)) (rswp (PROP:=iProp Σ) k s E e).
-Proof. by intros Φ Φ' ?; apply rswp_mono. Qed.
-
-Lemma rswp_frame_l k s E e Φ R : R ∗ RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ s; E ⟨⟨ v, R ∗ Φ v ⟩⟩.
-Proof. iIntros "[? H]". iApply (rswp_strong_mono with "H"); auto with iFrame. Qed.
-Lemma rswp_frame_r k s E e Φ R : RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ∗ R ⊢ RSWP e at k @ s; E ⟨⟨ v, Φ v ∗ R ⟩⟩.
-Proof. iIntros "[H ?]". iApply (rswp_strong_mono with "H"); auto with iFrame. Qed.
-
-Lemma rswp_wand k s E e Φ Ψ :
-  RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ -∗ (∀ v, Φ v -∗ Ψ v) -∗ RSWP e at k @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof.
-  iIntros "Hwp H". iApply (rswp_strong_mono with "Hwp"); auto.
-  iIntros (?) "?". by iApply "H".
-Qed.
-Lemma rswp_wand_l k s E e Φ Ψ :
-  (∀ v, Φ v -∗ Ψ v) ∗ RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ⊢ RSWP e at k @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof. iIntros "[H Hwp]". iApply (rswp_wand with "Hwp H"). Qed.
-Lemma rswp_wand_r k s E e Φ Ψ :
-  RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩ ∗ (∀ v, Φ v -∗ Ψ v) ⊢ RSWP e at k @ s; E ⟨⟨ Ψ ⟩⟩.
-Proof. iIntros "[Hwp H]". iApply (rswp_wand with "Hwp H"). Qed.
-Lemma rswp_frame_wand_l k s E e Q Φ :
-  Q ∗ RSWP e at k @ s; E ⟨⟨ v, Q -∗ Φ v ⟩⟩ -∗ RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩.
-Proof.
-  iIntros "[HQ HWP]". iApply (rswp_wand with "HWP").
-  iIntros (v) "HΦ". by iApply "HΦ".
-Qed.
-
-End rswp.
-
-
-(** Proofmode class instances *)
-Section proofmode_classes.
-  Context {SI} {Σ: gFunctors SI} {A Λ} `{!source Σ A} `{!ref_irisG Λ Σ}.
-  Implicit Types P Q : iProp Σ.
-  Implicit Types Φ : val Λ → iProp Σ.
-
-  Global Instance frame_rwp p s E e R Φ Ψ :
-    (∀ v, Frame p R (Φ v) (Ψ v)) →
-    Frame p R (RWP e @ s; E ⟨⟨ Φ ⟩⟩) (RWP e @ s; E ⟨⟨ Ψ ⟩⟩).
-  Proof. rewrite /Frame=> HR. rewrite rwp_frame_l. apply rwp_mono, HR. Qed.
-
-  Global Instance frame_rswp k p s E e R Φ Ψ :
-    (∀ v, Frame p R (Φ v) (Ψ v)) →
-    Frame p R (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩) (RSWP e at k @ s; E ⟨⟨ Ψ ⟩⟩).
-  Proof. rewrite /Frame=> HR. rewrite rswp_frame_l. apply rswp_mono, HR. Qed.
-
-  Global Instance is_except_0_rwp s E e Φ : IsExcept0 (RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof. by rewrite /IsExcept0 -{2}fupd_rwp -except_0_fupd -fupd_intro. Qed.
-
-  Global Instance is_except_0_rswp k s E e Φ : IsExcept0 (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof. by rewrite /IsExcept0 -{2}fupd_rswp -except_0_fupd -fupd_intro. Qed.
-
-  Global Instance elim_modal_bupd_rwp p s E e P Φ :
-    ElimModal True p false (|==> P) P (RWP e @ s; E ⟨⟨ Φ ⟩⟩) (RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof.
-    by rewrite /ElimModal bi.intuitionistically_if_elim
-      (bupd_fupd E) fupd_frame_r bi.wand_elim_r fupd_rwp.
-  Qed.
-
-   Global Instance elim_modal_bupd_rswp k p s E e P Φ :
-    ElimModal True p false (|==> P) P (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩) (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof.
-    by rewrite /ElimModal bi.intuitionistically_if_elim
-      (bupd_fupd E) fupd_frame_r bi.wand_elim_r fupd_rswp.
-  Qed.
-
-  Global Instance elim_modal_fupd_rwp p s E e P Φ :
-    ElimModal True p false (|={E}=> P) P (RWP e @ s; E ⟨⟨ Φ ⟩⟩) (RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof.
-    by rewrite /ElimModal bi.intuitionistically_if_elim
-      fupd_frame_r bi.wand_elim_r fupd_rwp.
-  Qed.
-
-  Global Instance elim_modal_fupd_rswp k p s E e P Φ :
-    ElimModal True p false (|={E}=> P) P (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩) (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof.
-    by rewrite /ElimModal bi.intuitionistically_if_elim
-      fupd_frame_r bi.wand_elim_r fupd_rswp.
-  Qed.
-
-  Global Instance elim_modal_fupd_rwp_atomic s p E1 E2 e P Φ :
-    Atomic StronglyAtomic e →
-    ElimModal True p false (|={E1,E2}=> P) P
-            (RWP e @ s; E1 ⟨⟨ Φ ⟩⟩) (RWP e @ s; E2 ⟨⟨ v, |={E2,E1}=> Φ v ⟩⟩)%I.
-  Proof.
-    intros. by rewrite /ElimModal bi.intuitionistically_if_elim
-      fupd_frame_r bi.wand_elim_r rwp_atomic.
-  Qed.
-
-  Global Instance elim_modal_fupd_rswp_atomic k s p E1 E2 e P Φ :
-    Atomic StronglyAtomic e →
-    ElimModal True p false (|={E1,E2}=> P) P
-            (RSWP e at k @ s; E1 ⟨⟨ Φ ⟩⟩) (RSWP e at k @ s; E2 ⟨⟨ v, |={E2,E1}=> Φ v ⟩⟩)%I.
-  Proof.
-    intros. by rewrite /ElimModal bi.intuitionistically_if_elim
-      fupd_frame_r bi.wand_elim_r rswp_atomic.
-  Qed.
-
-
-  Global Instance add_modal_fupd_rwp s E e P Φ :
-    AddModal (|={E}=> P) P (RWP e @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof. by rewrite /AddModal fupd_frame_r bi.wand_elim_r fupd_rwp. Qed.
-
-  Global Instance add_modal_fupd_rswp k s E e P Φ :
-    AddModal (|={E}=> P) P (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩).
-  Proof. by rewrite /AddModal fupd_frame_r bi.wand_elim_r fupd_rswp. Qed.
-
-
-  Global Instance elim_acc_wp {X} s E1 E2 α β γ e Φ :
-    Atomic StronglyAtomic e →
-    ElimAcc (X:=X) (fupd E1 E2) (fupd E2 E1)
-            α β γ (RWP e @ s; E1 ⟨⟨ Φ ⟩⟩)
-            (λ x, RWP e @ s; E2 ⟨⟨ v, |={E2}=> β x ∗ (γ x -∗? Φ v) ⟩⟩)%I.
-  Proof.
-    intros ?. rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply (rwp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-
-  Global Instance elim_acc_rswp {X} k s E1 E2 α β γ e Φ :
-    Atomic StronglyAtomic e →
-    ElimAcc (X:=X) (fupd E1 E2) (fupd E2 E1)
-            α β γ (RSWP e at k @ s; E1 ⟨⟨ Φ ⟩⟩)
-            (λ x, RSWP e at k @ s; E2 ⟨⟨ v, |={E2}=> β x ∗ (γ x -∗? Φ v) ⟩⟩)%I.
-  Proof.
-    intros ?. rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply (rswp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-
-  Global Instance elim_acc_wp_nonatomic {X} E α β γ e s Φ :
-    ElimAcc (X:=X) (fupd E E) (fupd E E)
-            α β γ (RWP e @ s; E ⟨⟨ Φ ⟩⟩)
-            (λ x, RWP e @ s; E ⟨⟨ v, |={E}=> β x ∗ (γ x -∗? Φ v) ⟩⟩)%I.
-  Proof.
-    rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply rwp_fupd.
-    iApply (rwp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-
-  Global Instance elim_acc_swp_nonatomic {X} k E α β γ e s Φ :
-    ElimAcc (X:=X) (fupd E E) (fupd E E)
-            α β γ (RSWP e at k @ s; E ⟨⟨ Φ ⟩⟩)
-            (λ x, RSWP e at k @ s; E ⟨⟨ v, |={E}=> β x ∗ (γ x -∗? Φ v) ⟩⟩)%I.
-  Proof.
-    rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply rswp_fupd.
-    iApply (rswp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-End proofmode_classes.
diff --git a/theories/program_logic/refinement/seq_weakestpre.v b/theories/program_logic/refinement/seq_weakestpre.v
deleted file mode 100644
index 0b647dea54385f36d56bc15518b411f33a70e03e..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/seq_weakestpre.v
+++ /dev/null
@@ -1,32 +0,0 @@
-From iris.proofmode Require Import tactics.
-From iris.base_logic.lib Require Import na_invariants.
-From iris.program_logic.refinement Require Import ref_weakestpre tc_weakestpre.
-Set Default Proof Using "Type".
-
-
-(* sequential reasoning *)
-Class seqG {SI} (Σ: gFunctors SI) := {
-  seqG_na_invG :> na_invG Σ;
-  seqG_name: gname;
-}.
-
-Definition seq {SI A Λ} {Σ: gFunctors SI} `{!source Σ A} `{!ref_irisG Λ Σ} `{!seqG Σ} E (e: expr Λ) Φ : iProp Σ :=
-  (na_own seqG_name E -∗ RWP e ⟨⟨ v, na_own seqG_name E ∗ Φ v ⟩⟩)%I.
-
-Definition se_inv {SI} {Σ: gFunctors SI} `{!invG Σ} `{!seqG Σ} (N: namespace) (P: iProp Σ) := na_inv seqG_name N P.
-
-Notation "'SEQ' e @ E ⟨⟨ v , Q ⟩ ⟩" := (seq E e%E (λ v, Q)) (at level 20, e, Q at level 200,
-format "'[' 'SEQ'  e  '/' '[          ' @  E  ⟨⟨  v ,  Q  ⟩ ⟩ ']' ']'") : bi_scope.
-Notation "'SEQ' e ⟨⟨ v , Q ⟩ ⟩" := (seq ⊤ e%E (λ v, Q)) (at level 20, e, Q at level 200,
-format "'[' 'SEQ'  e  '/' '[          ' ⟨⟨  v ,  Q  ⟩ ⟩ ']' ']'") : bi_scope.
-
-Lemma seq_value {SI A Λ} {Σ: gFunctors SI} `{!source Σ A} `{!ref_irisG Λ Σ} `{!seqG Σ} Φ E (v: val Λ) e `{!IntoVal e v}: Φ v ⊢ SEQ e @ E ⟨⟨ v, Φ v⟩⟩.
-Proof.
-  iIntros "Hv Hna". iApply rwp_value. iFrame.
-Qed.
-
-
-Notation "'SEQ' e @ E [{ v , Q } ]" := (@seq _ (ordA _) _ _ _ _ _ E e%E (λ v, Q)) (at level 20, e, Q at level 200,
-format "'[' 'SEQ'  e  '/' '[          ' @  E  [{  v ,  Q  } ] ']' ']'") : bi_scope.
-Notation "'SEQ' e [{ v , Q } ]" := (@seq _ (ordA _) _ _ _ _ _ ⊤ e%E (λ v, Q)) (at level 20, e, Q at level 200,
-format "'[' 'SEQ'  e  '/' '[          ' [{  v ,  Q  } ] ']' ']'") : bi_scope.
diff --git a/theories/program_logic/refinement/tc_weakestpre.v b/theories/program_logic/refinement/tc_weakestpre.v
deleted file mode 100644
index a5f00b1a4b2b9a3ef940c65a866bc4f507e12926..0000000000000000000000000000000000000000
--- a/theories/program_logic/refinement/tc_weakestpre.v
+++ /dev/null
@@ -1,103 +0,0 @@
-From iris.program_logic Require Export language.
-From iris.proofmode Require Import base tactics classes.
-From iris.algebra Require Import auth.
-From iris.algebra.ordinals Require Export ord_stepindex arithmetic.
-From iris.program_logic.refinement Require Import ref_adequacy ref_source ref_weakestpre.
-Set Default Proof Using "Type".
-
-
-(* time credits weakest precondition, using notation of total weakest-pre  *)
-Notation tcG Σ := (auth_sourceG Σ (ordA _)).
-
-Global Program Instance tcwp {SI} {Σ: gFunctors SI} `{!tcG Σ} `{!ref_irisG Λ Σ} : Twp Λ (iProp Σ) stuckness := rwp.
-
-Section lemmas.
-  Context {SI} {Σ: gFunctors SI} {Λ} `{!ref_irisG Λ Σ} `{!tcG Σ}.
-
-  Definition one := (succ zero).
-
-  Lemma tc_split α β: $ (α ⊕ β) ≡ ($α ∗ $β)%I.
-  Proof.
-    by rewrite -ord_op_plus /srcF auth_frag_op own_op.
-  Qed.
-
-  Lemma tc_succ α: $ succ α ≡ ($ α ∗ $ one)%I.
-  Proof.
-    by rewrite -tc_split /one natural_addition_comm natural_addition_succ natural_addition_zero_left_id.
-  Qed.
-
-  Lemma tcwp_rwp e E s Φ:
-    twp s E e Φ ≡ rwp s E e Φ.
-  Proof. reflexivity. Qed.
-
-  Lemma tcwp_burn_credit e E s (Φ: val Λ → iProp Σ):
-    to_val e = None →
-    ⊢ ($ one -∗ (▷ RSWP e at 0 @ s; E ⟨⟨ v, Φ v ⟩⟩) -∗ WP e @ s; E [{ v, Φ v }])%I.
-  Proof.
-    iIntros (?) "Hone Hwp". rewrite tcwp_rwp.
-    iApply (rwp_take_step  with "[Hwp] [Hone]"); first done.
-    - iIntros "_". iApply rswp_do_step. by iNext.
-    - iApply (@auth_src_update _ _ (ordA SI) with "Hone").
-      eapply succ_greater.
-  Qed.
-
-  Lemma tc_weaken (α β: Ord) e s E Φ:
-    to_val e = None
-    → β ⪯ α
-    → ($β -∗ WP e @ s; E [{ Φ }]) ∗ $ α ⊢ WP e @ s; E [{ Φ }].
-  Proof.
-    intros He [->|]; iIntros "[Hwp Hc]".
-    - by iApply "Hwp".
-    - iApply (rwp_weaken with "[Hwp] [Hc]"); first done.
-      + iExact "Hwp".
-      + by iApply (@auth_src_update _ _ (ordA SI) with "Hc").
-  Qed.
-
-  Lemma tc_alloc_zero s E e Φ: ($ zero -∗ WP e @ s; E [{ Φ }]) ⊢ WP e @ s; E [{ Φ }].
-  Proof.
-    iIntros "H".
-    iMod (@own_unit _ _ _ sourceG_inG sourceG_name) as "Hz".
-    replace (ε: @authR SI (auth_sourceUR SI (ordA SI)))
-      with (◯ zero: @authR SI (auth_sourceUR SI (ordA SI))) by reflexivity.
-    by iSpecialize ("H" with "Hz").
-  Qed.
-
-  Global Instance tc_timeless α : Timeless ($ α).
-  Proof. apply _. Qed.
-
-  Global Instance zero_persistent : Persistent ($ zero).
-  Proof.
-    apply own_core_persistent, auth_frag_core_id.
-    replace zero with (core zero) by reflexivity.
-    apply cmra_core_core_id.
-  Qed.
-
-  Global Instance tcwp_elim_wand p e s E Φ Ψ :
-    ElimModal True p false (twp s E e Φ) emp (twp s E e Ψ) (∀ v, Φ v ={E}=∗ Ψ v).
-  Proof.
-    iIntros (_) "(P & HPQ)". iPoseProof (bi.intuitionistically_if_elim with "P") as "P".
-    iApply (rwp_strong_mono with "P"); auto. iIntros (v) "HΦ". by iApply ("HPQ" with "[] HΦ").
-  Qed.
-End lemmas.
-
-
-
-(* adequacy lemmas *)
-Lemma tcwp_adequacy {SI} {Σ: gFunctors SI} {Λ} `{!ref_irisG Λ Σ} `{!tcG Σ} `{LargeIndex SI} Φ (e: expr Λ) σ (n: nat) (α: Ord):
-  satisfiable_at ⊤ (●$ α ∗ ref_state_interp σ n ∗ (WP e [{ v, Φ v}]))%I
-  → ex_loop erased_step ([e], σ)
-  → False.
-Proof.
-  specialize (@rwp_adequacy SI Σ Ord Λ _ _ _ Φ α e σ n NotStuck).
-  simpl; rewrite /srcA. intros Had Hsat Hloop. eapply Had; auto.
-  by apply wf_ord_lt.
-Qed.
-
-(* instantiation with the ordinal index to be sure *)
-Lemma tcwp_adequacy' {Λ} {Σ: gFunctors ordI} `{!ref_irisG Λ Σ} `{!tcG Σ} Φ e (n: nat) σ (α: Ord):
-  satisfiable_at ⊤ (●$ α ∗ ref_state_interp σ n ∗ (WP e [{ v, Φ v}]))%I
-  → ex_loop erased_step ([e], σ)
-  → False.
-Proof.
-  apply tcwp_adequacy.
-Qed.
diff --git a/theories/program_logic/weakestpre.v b/theories/program_logic/weakestpre.v
deleted file mode 100644
index f7a523d327814b87040ac390cb4ba7341846e29b..0000000000000000000000000000000000000000
--- a/theories/program_logic/weakestpre.v
+++ /dev/null
@@ -1,723 +0,0 @@
-From iris.base_logic.lib Require Export fancy_updates.
-From iris.base_logic.lib Require Export logical_step.
-From iris.program_logic Require Export language.
-From iris.bi Require Export weakestpre.
-From iris.proofmode Require Import base tactics classes.
-Set Default Proof Using "Type".
-Import uPred.
-
-Section eventually.
-
-  Context {SI} {PROP: sbi SI} `{FU: BiFUpd SI PROP}.
-
-
-  Global Instance big_later_elim p (P Q: PROP):
-    ElimModal True p false (⧍ P) P (⧍ Q) Q.
-  Proof.
-    iIntros (_) "(P & HPQ)". iPoseProof (intuitionistically_if_elim with "P") as "P".
-    iDestruct "P" as (n) "P". iExists n. iNext. by iApply "HPQ".
-  Qed.
-
-  Global Instance plain_big_later `{BP: BiPlainly SI PROP} (P: PROP): Plain P → Plain (⧍ P).
-  Proof. apply _. Qed.
-
-  Global Instance plain_big_laterN `{BP: BiPlainly SI PROP} (P: PROP) n: Plain P → Plain (⧍^n P).
-  Proof. intros HP. induction n; simpl; apply _. Qed.
-
-  Lemma eventuallyN_plain `{BP: BiPlainly SI PROP} `{@BiFUpdPlainly SI PROP FU BP} (P : PROP) n E:
-    Plain P → (<E>_n P) ⊢ |={E}=> ▷^(S n) P.
-  Proof.
-    iIntros (HP) "H". iInduction n as [ | n] "IH".
-    - iMod "H". by iModIntro.
-    - simpl. iSpecialize ("IH" with "H").
-      iMod "IH".
-      iPoseProof (fupd_trans with "IH") as "IH".
-      iPoseProof (fupd_plain_later with "IH") as "IH".
-      iMod "IH". iModIntro.
-      iNext. by iApply except_0_later.
-  Qed.
-
-  Lemma eventually_plain `{BP: BiPlainly SI PROP} `{@BiFUpdPlainly SI PROP FU BP} (P : PROP) E:
-    Plain P → (<E> P) ⊢ |={E}=> ⧍ P.
-  Proof.
-    intros HP. iIntros "H".
-    unfold eventually. iMod "H". iDestruct "H" as (n) "H".
-    iDestruct (eventuallyN_plain _ with "H") as "H".
-    iMod "H". iModIntro. eauto.
-  Qed.
-
-  Existing Instance elim_eventuallyN.
-  Lemma lstep_fupd_plain `{BP: BiPlainly SI PROP} `{@BiFUpdPlainly SI PROP FU BP} (P : PROP):
-    Plain P → ((>={⊤}=={⊤}=> P) ⊢ |={⊤}=> ⧍ P)%I.
-  Proof.
-    iIntros (HP) "H".
-    iApply (fupd_plain_mask _ ∅). iMod "H".
-    iApply eventually_plain.
-    iApply eventually_fupd_right.
-    iMod "H" as (n) "H". iApply (eventuallyN_eventually (n)).  iMod "H".
-    by iApply (fupd_plain_mask _ ⊤).
-  Qed.
-
-  Lemma lstep_fupdN_plain `{BP: BiPlainly SI PROP} `{@BiFUpdPlainly SI PROP FU BP} (P : PROP) n:
-    Plain P → ((>={⊤}=={⊤}=>^n P) ⊢ |={⊤}=> ⧍^n P)%I.
-  Proof.
-    intros HP. iIntros "H". iInduction n as [|n] "IH"; simpl.
-    - by iModIntro.
-    - iAssert (>={⊤}=={⊤}=> ⧍^n P)%I with "[H]" as "H".
-      { do 2 iMod "H". iModIntro. iDestruct "H" as (n') "H".
-        iApply (eventuallyN_eventually (n' )). iMod "H".
-        iMod "H". by iSpecialize ("IH" with "H").
-      }
-      iApply (lstep_fupd_plain with "H").
-  Qed.
-End eventually.
-
-
-Class irisG (Λ : language) {SI} (Σ : gFunctors SI) := IrisG {
-  iris_invG :> invG Σ;
-
-  (** The state interpretation is an invariant that should hold in between each
-  step of reduction. Here [Λstate] is the global state, [list Λobservation] are
-  the remaining observations, and [nat] is the number of forked-off threads
-  (not the total number of threads, which is one higher because there is always
-  a main thread). *)
-  state_interp : state Λ → list (observation Λ) → nat → iProp Σ;
-
-  (** A fixed postcondition for any forked-off thread. For most languages, e.g.
-  heap_lang, this will simply be [True]. However, it is useful if one wants to
-  keep track of resources precisely, as in e.g. Iron. *)
-  fork_post : val Λ → iProp Σ;
-}.
-Global Opaque iris_invG.
-
-Definition wp_pre {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} (s : stuckness)
-    (wp : coPset -d> expr Λ -d> (val Λ -d> iProp Σ) -d> iProp Σ) :
-    coPset -d> expr Λ -d> (val Λ -d> iProp Σ) -d> iProp Σ := λ E e1 Φ,
-  match to_val e1 with
-  | Some v => |={E}=> Φ v
-  | None => ∀ σ1 κ κs n,
-    state_interp σ1 (κ ++ κs) n -∗ >={E}=={∅}=> (
-       ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-       ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ -∗ |={∅,∅,E}▷=> (
-         state_interp σ2 κs (length efs + n) ∗
-         wp E e2 Φ ∗
-         [∗ list] i ↦ ef ∈ efs, wp ⊤ ef fork_post))
-  end%I.
-
-Local Instance wp_pre_contractive {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} s : Contractive (wp_pre s).
-Proof.
-  rewrite /wp_pre=> n wp wp' Hwp E e1 Φ.
-  do 20 f_equiv. f_contractive. intros β Hβ. do 3 f_equiv. apply (Hwp β Hβ).
-  do 3 f_equiv. apply (Hwp β Hβ).
-Qed.
-
-Definition wp_def {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} (s : stuckness) :
-  coPset → expr Λ → (val Λ → iProp Σ) → iProp Σ := fixpoint (wp_pre s).
-Definition wp_aux {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} : seal (@wp_def SI Σ Λ _). by eexists. Qed.
-Instance wp' {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} : Wp Λ (iProp Σ) stuckness := wp_aux.(unseal).
-Definition wp_eq {SI} {Σ: gFunctors SI}  `{!irisG Λ Σ} : wp = @wp_def SI Σ Λ  _ := wp_aux.(seal_eq).
-
-Definition swp_def {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} (k: nat) (s : stuckness) (E: coPset)  (e1: expr Λ) (Φ: val Λ → iProp Σ) : iProp Σ :=
-  (∀ σ1 κ κs n,
-    state_interp σ1 (κ ++ κs) n -∗ >={E}=={∅}=>_k (
-       ⌜if s is NotStuck then reducible e1 σ1 else True⌝ ∗
-       ∀ e2 σ2 efs, ⌜prim_step e1 σ1 κ e2 σ2 efs⌝ -∗ |={∅,∅,E}▷=> (
-         state_interp σ2 κs (length efs + n) ∗
-         WP e2 @ s; E {{ v, Φ v }} ∗
-         [∗ list] i ↦ ef ∈ efs, WP ef @ s; ⊤ {{ v, fork_post v }})))%I.
-Definition swp_aux {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} : seal (@swp_def SI Σ Λ _). by eexists. Qed.
-Instance swp' {SI} {Σ: gFunctors SI} `{!irisG Λ Σ} : Swp Λ (iProp Σ) stuckness := swp_aux.(unseal).
-Definition swp_eq {SI} {Σ: gFunctors SI}  `{!irisG Λ Σ} : swp = @swp_def SI Σ Λ  _ :=
-  swp_aux.(seal_eq).
-
-Section wp.
-Context {SI} {Σ: gFunctors SI}  `{!irisG Λ Σ}.
-Implicit Types s : stuckness.
-Implicit Types P : iProp Σ.
-Implicit Types Φ : val Λ → iProp Σ.
-Implicit Types v : val Λ.
-Implicit Types e : expr Λ.
-
-(* Weakest pre *)
-Lemma wp_unfold s E e Φ :
-  WP e @ s; E {{ Φ }} ⊣⊢ wp_pre s (wp (PROP:=iProp Σ)  s) E e Φ.
-Proof. rewrite wp_eq. apply (fixpoint_unfold (wp_pre s)). Qed.
-
-Lemma swp_unfold k s E e Φ :
-  SWP e at k @ s; E {{ Φ }} ⊣⊢ swp_def k s E e Φ.
-Proof. by rewrite swp_eq. Qed.
-
-
-Global Instance wp_ne s E e n :
-  Proper (pointwise_relation _ (dist n) ==> dist n) (wp (PROP:=iProp Σ) s E e).
-Proof.
-  revert e. induction (index_lt_wf SI n) as [n _ IH]=> e Φ Ψ HΦ.
-  rewrite !wp_unfold /wp_pre.
-  (* FIXME: figure out a way to properly automate this proof *)
-  (* FIXME: reflexivity, as being called many times by f_equiv and f_contractive
-  is very slow here *)
-  do 20 f_equiv. f_contractive. intros β Hβ.
-  do 3 f_equiv. eapply IH; eauto.
-  intros v. eapply dist_le; eauto.
-Qed.
-Global Instance wp_proper s E e :
-  Proper (pointwise_relation _ (≡) ==> (≡)) (wp (PROP:=iProp Σ) s E e).
-Proof.
-  by intros Φ Φ' ?; apply equiv_dist=>n; apply wp_ne=>v; apply equiv_dist.
-Qed.
-
-Global Instance swp_ne k s E e n :
-  Proper (pointwise_relation _ (dist n) ==> dist n) (swp (PROP:=iProp Σ) k s E e).
-Proof.
-  intros Φ Ψ HΦ. rewrite !swp_unfold /swp_def.
-  (* FIXME: figure out a way to properly automate this proof *)
-  (* FIXME: reflexivity, as being called many times by f_equiv and f_contractive
-  is very slow here *)
-  do 19 f_equiv. f_contractive. intros β Hβ.
-  do 3 f_equiv. eapply wp_ne.
-  intros v. eapply dist_le; eauto.
-Qed.
-Global Instance swp_proper k s E e :
-  Proper (pointwise_relation _ (≡) ==> (≡)) (swp k (PROP:=iProp Σ) s E e).
-Proof.
-  by intros Φ Φ' ?; apply equiv_dist=>n; apply swp_ne=>v; apply equiv_dist.
-Qed.
-
-Lemma wp_value' s E Φ v : Φ v ⊢ WP of_val v @ s; E {{ Φ }}.
-Proof. iIntros "HΦ". rewrite wp_unfold /wp_pre to_of_val. auto. Qed.
-Lemma wp_value_inv' s E Φ v : WP of_val v @ s; E {{ Φ }} ={E}=∗ Φ v.
-Proof. by rewrite wp_unfold /wp_pre to_of_val. Qed.
-
-Section gstep.
-Local Existing Instance elim_gstep.
-Lemma wp_strong_mono s1 s2 E1 E2 e Φ Ψ :
-  s1 ⊑ s2 → E1 ⊆ E2 →
-  WP e @ s1; E1 {{ Φ }} -∗ (∀ v, Φ v ={E2}=∗ Ψ v) -∗ WP e @ s2; E2 {{ Ψ }}.
-Proof.
-  iIntros (? HE) "H HΦ". iLöb as "IH" forall (e E1 E2 HE Φ Ψ).
-  rewrite !wp_unfold /wp_pre.
-  destruct (to_val e) as [v|] eqn:?.
-  { iApply ("HΦ" with "[> -]"). by iApply (fupd_mask_mono E1 _). }
-  iIntros (σ1 κ κs n) "Hσ". iMod (fupd_intro_mask' E2 E1) as "Hclose"; first done.
-  iMod ("H" with "[$]") as "[? H]".
-  iSplit; [by destruct s1, s2|]. iIntros (e2 σ2 efs Hstep).
-  iSpecialize ("H" with "[//]"). iMod "H". iModIntro. iNext. iMod "H". iMod "Hclose" as "_".
-  iModIntro.
-  iDestruct "H" as "(Hσ & H & Hefs)". iFrame "Hσ". iSplitR "Hefs".
-  - iApply ("IH" with "[//] H HΦ").
-  - iApply (big_sepL_impl with "Hefs"); iIntros "!#" (k ef _).
-    iIntros "H". iApply ("IH" with "[] H"); auto.
-Qed.
-
-Lemma fupd_wp s E e Φ : (|={E}=> WP e @ s; E {{ Φ }}) ⊢ WP e @ s; E {{ Φ }}.
-Proof.
-  rewrite wp_unfold /wp_pre. iIntros "H". destruct (to_val e) as [v|] eqn:?.
-  { by iMod "H". }
-  iIntros (σ1 κ κs n) "Hσ1". iMod "H". by iApply "H".
-Qed.
-Lemma wp_fupd s E e Φ : WP e @ s; E {{ v, |={E}=> Φ v }} ⊢ WP e @ s; E {{ Φ }}.
-Proof. iIntros "H". iApply (wp_strong_mono s s E with "H"); auto. Qed.
-
-
-Lemma wp_atomic E1 E2 e s Φ `{!Atomic StronglyAtomic e} :
-  (|={E1,E2}=> WP e @ s; E2 {{ v, |={E2,E1}=> Φ v }}) ⊢ WP e @ s; E1 {{ Φ }}.
-Proof.
-  iIntros "H". rewrite !wp_unfold /wp_pre.
-  destruct (to_val e) as [v|] eqn:He.
-  { by iDestruct "H" as ">>> $". }
-  iIntros (σ1 κ κs n) "Hσ". iMod "H".
-  iMod ("H" $! σ1 with "Hσ") as "[$ H]".
-  iIntros (e2 σ2 efs Hstep). iSpecialize ("H" with "[//]"). iMod "H". iModIntro. iNext.
-  iMod "H" as "(Hσ & H & Hefs)".
-  + rewrite wp_unfold /wp_pre. destruct (to_val e2) as [v2|] eqn:He2.
-    * rewrite wp_unfold /wp_pre He2. iDestruct "H" as ">> $". by iFrame.
-    * specialize (atomic _ _ _ _ _ Hstep) as []; congruence.
-Qed.
-
-
-Local Existing Instance elim_gstepN.
-Lemma swp_strong_mono k1 k2 s1 s2 E1 E2 e Φ Ψ :
-  s1 ⊑ s2 → E1 ⊆ E2 → k1 ≤ k2 →
-  SWP e at k1 @ s1; E1 {{ Φ }} -∗ (∀ v, Φ v ={E2}=∗ Ψ v) -∗ SWP e at k2 @ s2; E2 {{ Ψ }}.
-Proof.
-  iIntros (? HE Hk) "H HΦ". rewrite !swp_unfold /swp_def.
-  iIntros (σ1 κ κs n) "S". iMod (fupd_intro_mask' E2 E1) as "E"; eauto.
-  iSpecialize ("H" with "S"). iApply (gstepN_mono _ _ _ _ _ _ Hk).
-  iMod ("H") as "[? H]".
-  iSplit; [by destruct s1, s2|]. iIntros (e2 σ2 efs Hstep).
-  iSpecialize ("H" with "[//]"). iMod "H". iModIntro. iNext. iMod "H". iMod "E" as "_".
-  iModIntro.
-  iDestruct "H" as "(Hσ & H & Hefs)". iFrame "Hσ". iSplitR "Hefs".
-  - iApply (wp_strong_mono with "H"); eauto.
-  - iApply (big_sepL_impl with "Hefs"); iIntros "!#" (k ef _).
-    iIntros "H". iApply (wp_strong_mono with "H"); eauto.
-Qed.
-
-Lemma fupd_swp k s E e Φ : (|={E}=> SWP e at k @ s; E {{ Φ }})%I ⊢ SWP e at k @ s; E {{ Φ }}.
-Proof.
-  rewrite swp_unfold /swp_def. iIntros "SWP".
-  iIntros (σ1 κ κs n) "S". iMod "SWP".
-  iApply "SWP"; iFrame.
-Qed.
-
-Lemma swp_fupd k s E e Φ : SWP e at k @ s; E {{ v, |={E}=> Φ v}} ⊢ SWP e at k @ s; E {{ Φ }}.
-Proof. iIntros "H". iApply (swp_strong_mono k k s s E with "H"); auto. Qed.
-
-
-Lemma swp_atomic k E1 E2 e s Φ `{!Atomic StronglyAtomic e} :
-  (|={E1, E2}=> SWP e at k @ s; E2 {{ v, |={E2, E1}=> Φ v}})%I ⊢ SWP e at k @ s; E1 {{ Φ }}.
-Proof.
-  rewrite !swp_unfold /swp_def. iIntros "SWP". iIntros (σ1 κ κs n) "S".
-  iMod "SWP". iMod ("SWP" with "S") as "[$ SWP]".
-  iIntros (e2 σ2 efs Hstep). iMod ("SWP" with "[//]") as "SWP". iModIntro. iNext.
-  iMod "SWP" as "($& SWP & $)". destruct (atomic _ _ _ _ _ Hstep) as [v Hv].
-  rewrite !wp_unfold /wp_pre Hv. do 2 iMod "SWP". by do 2 iModIntro.
-Qed.
-
-Lemma swp_wp k s E e Φ : to_val e = None →
-   SWP e at k @ s; E {{ Φ }} ⊢ WP e @ s; E {{ Φ }}%I.
-Proof.
-  intros H; rewrite swp_unfold wp_unfold /swp_def /wp_pre H.
-  iIntros "SWP". iIntros (σ1 κ κs n) "S".
-  iApply gstepN_gstep. iMod ("SWP" with "S") as "$".
-Qed.
-
-Lemma swp_step k E e s Φ : ▷ SWP e at k @ s; E {{ Φ }} ⊢ SWP e at S k @ s; E {{ Φ }}.
-Proof.
-  rewrite !swp_unfold /swp_def. iIntros "SWP". iIntros (σ1 κ κs n) "S".
-  iMod (fupd_intro_mask') as "M". apply empty_subseteq.
-  do 3 iModIntro. iMod "M" as "_".
-  iMod ("SWP" with "S") as "$".
-Qed.
-
-
-Lemma wp_bind K `{!LanguageCtx K} s E e Φ :
-  WP e @ s; E {{ v, WP K (of_val v) @ s; E {{ Φ }} }} ⊢ WP K e @ s; E {{ Φ }}.
-Proof.
-  iIntros "H". iLöb as "IH" forall (E e Φ). rewrite wp_unfold /wp_pre.
-  destruct (to_val e) as [v|] eqn:He.
-  { apply of_to_val in He as <-. by iApply fupd_wp. }
-  rewrite wp_unfold /wp_pre fill_not_val //.
-  iIntros (σ1 κ κs n) "Hσ". iMod ("H" with "[$]") as "[% H]"; iSplit.
-  { iPureIntro. destruct s; last done.
-    unfold reducible in *. naive_solver eauto using fill_step. }
-  iIntros (e2 σ2 efs Hstep).
-  destruct (fill_step_inv e σ1 κ e2 σ2 efs) as (e2'&->&?); auto.
-  iMod ("H" $! e2' σ2 efs with "[//]") as "H". iIntros "!> !>".
-  iMod "H" as "(Hσ & H & Hefs)".
-  iModIntro. iFrame "Hσ Hefs". by iApply "IH".
-Qed.
-
-Lemma swp_bind k K `{!LanguageCtx K} s E e Φ : to_val e = None →
-  SWP e at k @ s; E {{ v, WP K (of_val v) @ s; E {{ Φ }} }} ⊢ SWP K e at k @ s; E {{ Φ }}.
-Proof.
-  iIntros (H) "H". rewrite !swp_unfold /swp_def.
-  iIntros (σ1 κ κs n) "Hσ". iMod ("H" with "[$]") as "[% H]"; iSplit.
-  { iPureIntro. destruct s; last done.
-    unfold reducible in *. naive_solver eauto using fill_step. }
-  iIntros (e2 σ2 efs Hstep).
-  destruct (fill_step_inv e σ1 κ e2 σ2 efs) as (e2'&->&?); auto.
-  iMod ("H" $! e2' σ2 efs with "[//]") as "H". iIntros "!> !>".
-  iMod "H" as "(Hσ & H & Hefs)".
-  iModIntro. iFrame "Hσ Hefs". by iApply wp_bind.
-Qed.
-
-
-Lemma wp_bind_inv K `{!LanguageCtx K} s E e Φ :
-  WP K e @ s; E {{ Φ }} ⊢ WP e @ s; E {{ v, WP K (of_val v) @ s; E {{ Φ }} }}.
-Proof.
-  iIntros "H". iLöb as "IH" forall (E e Φ). rewrite !wp_unfold /wp_pre.
-  destruct (to_val e) as [v|] eqn:He.
-  { apply of_to_val in He as <-. by rewrite !wp_unfold /wp_pre. }
-  rewrite fill_not_val //.
-  iIntros (σ1 κ κs n) "Hσ". iMod ("H" with "[$]") as "[% H]"; iSplit.
-  { destruct s; eauto using reducible_fill. }
-  iIntros (e2 σ2 efs Hstep).
-  iMod ("H" $! (K e2) σ2 efs with "[]") as "H"; [by eauto using fill_step|].
-  iIntros "!> !>". iMod "H" as "(Hσ & H & Hefs)".
-  iModIntro. iFrame "Hσ Hefs". by iApply "IH".
-Qed.
-
-Lemma swp_bind_inv K `{!LanguageCtx K} k s E e Φ : to_val e = None →
-  SWP K e at k @ s; E {{ Φ }} ⊢ SWP e at k @ s; E {{ v, WP K (of_val v) @ s; E {{ Φ }} }}.
-Proof.
-  iIntros (H) "H". rewrite !swp_unfold /swp_def.
-  iIntros (σ1 κ κs n) "Hσ". iMod ("H" with "[$]") as "[% H]"; iSplit.
-  { destruct s; eauto using reducible_fill. }
-  iIntros (e2 σ2 efs Hstep).
-  iMod ("H" $! (K e2) σ2 efs with "[]") as "H"; [by eauto using fill_step|].
-  iIntros "!> !>". iMod "H" as "(Hσ & H & Hefs)".
-  iModIntro. iFrame "Hσ Hefs". by iApply wp_bind_inv.
-Qed.
-
-(** * Derived rules *)
-Lemma wp_mono s E e Φ Ψ : (∀ v, Φ v ⊢ Ψ v) → WP e @ s; E {{ Φ }} ⊢ WP e @ s; E {{ Ψ }}.
-Proof.
-  iIntros (HΦ) "H"; iApply (wp_strong_mono with "H"); auto.
-  iIntros (v) "?". by iApply HΦ.
-Qed.
-Lemma wp_stuck_mono s1 s2 E e Φ :
-  s1 ⊑ s2 → WP e @ s1; E {{ Φ }} ⊢ WP e @ s2; E {{ Φ }}.
-Proof. iIntros (?) "H". iApply (wp_strong_mono with "H"); auto. Qed.
-Lemma wp_stuck_weaken s E e Φ :
-  WP e @ s; E {{ Φ }} ⊢ WP e @ E ?{{ Φ }}.
-Proof. apply wp_stuck_mono. by destruct s. Qed.
-Lemma wp_mask_mono s E1 E2 e Φ : E1 ⊆ E2 → WP e @ s; E1 {{ Φ }} ⊢ WP e @ s; E2 {{ Φ }}.
-Proof. iIntros (?) "H"; iApply (wp_strong_mono with "H"); auto. Qed.
-Global Instance wp_mono' s E e :
-  Proper (pointwise_relation _ (⊢) ==> (⊢)) (wp (PROP:=iProp Σ) s E e).
-Proof. by intros Φ Φ' ?; apply wp_mono. Qed.
-
-Lemma wp_value s E Φ e v : IntoVal e v → Φ v ⊢ WP e @ s; E {{ Φ }}.
-Proof. intros <-. by apply wp_value'. Qed.
-Lemma wp_value_fupd' s E Φ v : (|={E}=> Φ v) ⊢ WP of_val v @ s; E {{ Φ }}.
-Proof. intros. by rewrite -wp_fupd -wp_value'. Qed.
-Lemma wp_value_fupd s E Φ e v `{!IntoVal e v} :
-  (|={E}=> Φ v) ⊢ WP e @ s; E {{ Φ }}.
-Proof. intros. rewrite -wp_fupd -wp_value //. Qed.
-Lemma wp_value_inv s E Φ e v : IntoVal e v → WP e @ s; E {{ Φ }} ={E}=∗ Φ v.
-Proof. intros <-. by apply wp_value_inv'. Qed.
-
-Lemma wp_frame_l s E e Φ R : R ∗ WP e @ s; E {{ Φ }} ⊢ WP e @ s; E {{ v, R ∗ Φ v }}.
-Proof. iIntros "[? H]". iApply (wp_strong_mono with "H"); auto with iFrame. Qed.
-Lemma wp_frame_r s E e Φ R : WP e @ s; E {{ Φ }} ∗ R ⊢ WP e @ s; E {{ v, Φ v ∗ R }}.
-Proof. iIntros "[H ?]". iApply (wp_strong_mono with "H"); auto with iFrame. Qed.
-
-End gstep.
-
-Existing Instance elim_eventuallyN.
-Lemma wp_step_fupd s E1 E2 e P Φ :
-  to_val e = None → E2 ⊆ E1 →
-  (|={E1,E2}▷=> P) -∗ WP e @ s; E2 {{ v, P ={E1}=∗ Φ v }} -∗ WP e @ s; E1 {{ Φ }}.
-Proof.
-  rewrite !wp_unfold /wp_pre. iIntros (-> ?) "HR H".
-  iIntros (σ1 κ κs n) "Hσ". iMod "HR".
-  iMod ("H" with "[$]") as ">H". iDestruct "H" as (n1) "H".
-  iApply (gstepN_gstep _ _ _ (S n1)). iApply gstepN_later; first eauto. iNext.
-  iModIntro. iMod "H". iMod "H" as "[$ H]". iModIntro.
-  iIntros(e2 σ2 efs Hstep).
-  iSpecialize ("H" $! e2 σ2 efs with "[% //]"). iMod "H". iModIntro. iNext.
-  iMod "H" as "(Hσ & H & Hefs)".
-  iMod "HR". iModIntro. iFrame "Hσ Hefs".
-  iApply (wp_strong_mono s s E2 with "H"); [done..|].
-  iIntros (v) "H". by iApply "H".
-Qed.
-
-
-Lemma wp_step_gstep s E e P Φ :
-  to_val e = None →
-  (>={E}=={E}=> P) -∗ WP e @ s; ∅ {{ v, P ={E}=∗ Φ v }} -∗ WP e @ s; E {{ Φ }}.
-Proof.
-  rewrite !wp_unfold /wp_pre. iIntros (->) "HR H".
-  iIntros (σ1 κ κs n) "Hσ". iMod "HR". iMod "HR". iDestruct "HR" as (n1) "HR".
-  iMod ("H" with "[$]") as ">H". iDestruct "H" as (n2) "H".
-  iApply (gstepN_gstep _ _ _ (n1 + n2)).
-  iModIntro. iApply eventuallyN_compose.
-  iMod "HR". iMod "H". iMod "H" as "[$ H]". iMod "HR".
-  iMod (fupd_intro_mask' _ ∅) as "Hcnt"; first set_solver.
-  iModIntro. iIntros(e2 σ2 efs Hstep).
-  iSpecialize ("H" $! e2 σ2 efs with "[% //]"). iMod "H". iModIntro. iNext.
-  iMod "H" as "($ & H & $)". iMod "Hcnt". iModIntro.
-  iApply (wp_strong_mono s s ∅ with "H"); [done | set_solver|].
-  iIntros (v) "Hv". iApply ("Hv" with "HR").
-Qed.
-
-Lemma swp_step_fupd k s E1 E2 e P Φ :
-  E2 ⊆ E1 →
-  (|={E1,E2}▷=> P) -∗ SWP e at k @ s; E2 {{ v, P ={E1}=∗ Φ v }} -∗ SWP e at k @ s; E1 {{ Φ }}.
-Proof.
-  rewrite !swp_unfold /swp_def. iIntros (?) "HR H".
-  iIntros (σ1 κ κs n) "Hσ". iMod "HR". iMod ("H" with "[$]") as "H". iModIntro.
-  iMod "H". iMod "H" as "[$ H]". iModIntro. iIntros(e2 σ2 efs Hstep).
-  iSpecialize ("H" $! e2 σ2 efs with "[% //]"). iMod "H". iModIntro. iNext.
-  iMod "H" as "(Hσ & H & Hefs)".
-  iMod "HR". iModIntro. iFrame "Hσ Hefs".
-  iApply (wp_strong_mono s s E2 with "H"); [done..|].
-  iIntros (v) "H". by iApply "H".
-Qed.
-
-Lemma wp_frame_step_l s E1 E2 e Φ R :
-  to_val e = None → E2 ⊆ E1 →
-  (|={E1,E2}▷=> R) ∗ WP e @ s; E2 {{ Φ }} ⊢ WP e @ s; E1 {{ v, R ∗ Φ v }}.
-Proof.
-  iIntros (??) "[Hu Hwp]". iApply (wp_step_fupd with "Hu"); try done.
-  iApply (wp_mono with "Hwp"). by iIntros (?) "$$".
-Qed.
-Lemma wp_frame_step_r s E1 E2 e Φ R :
-  to_val e = None → E2 ⊆ E1 →
-  WP e @ s; E2 {{ Φ }} ∗ (|={E1,E2}▷=> R) ⊢ WP e @ s; E1 {{ v, Φ v ∗ R }}.
-Proof.
-  rewrite [(WP _ @ _; _ {{ _ }} ∗ _)%I]comm; setoid_rewrite (comm _ _ R).
-  apply wp_frame_step_l.
-Qed.
-Lemma wp_frame_step_l' s E e Φ R :
-  to_val e = None → ▷ R ∗ WP e @ s; E {{ Φ }} ⊢ WP e @ s; E {{ v, R ∗ Φ v }}.
-Proof. iIntros (?) "[??]". iApply (wp_frame_step_l s E E); try iFrame; eauto. Qed.
-Lemma wp_frame_step_r' s E e Φ R :
-  to_val e = None → WP e @ s; E {{ Φ }} ∗ ▷ R ⊢ WP e @ s; E {{ v, Φ v ∗ R }}.
-Proof. iIntros (?) "[??]". iApply (wp_frame_step_r s E E); try iFrame; eauto. Qed.
-
-Lemma wp_wand s E e Φ Ψ :
-  WP e @ s; E {{ Φ }} -∗ (∀ v, Φ v -∗ Ψ v) -∗ WP e @ s; E {{ Ψ }}.
-Proof.
-  iIntros "Hwp H". iApply (wp_strong_mono with "Hwp"); auto.
-  iIntros (?) "?". by iApply "H".
-Qed.
-Lemma wp_wand_l s E e Φ Ψ :
-  (∀ v, Φ v -∗ Ψ v) ∗ WP e @ s; E {{ Φ }} ⊢ WP e @ s; E {{ Ψ }}.
-Proof. iIntros "[H Hwp]". iApply (wp_wand with "Hwp H"). Qed.
-Lemma wp_wand_r s E e Φ Ψ :
-  WP e @ s; E {{ Φ }} ∗ (∀ v, Φ v -∗ Ψ v) ⊢ WP e @ s; E {{ Ψ }}.
-Proof. iIntros "[Hwp H]". iApply (wp_wand with "Hwp H"). Qed.
-Lemma wp_frame_wand_l s E e Q Φ :
-  Q ∗ WP e @ s; E {{ v, Q -∗ Φ v }} -∗ WP e @ s; E {{ Φ }}.
-Proof.
-  iIntros "[HQ HWP]". iApply (wp_wand with "HWP").
-  iIntros (v) "HΦ". by iApply "HΦ".
-Qed.
-
-(* we can pull out a logical step from a WP when switching to the SWP *)
-Local Existing Instance elim_fupd_step.
-Instance elim_fupd_stepN b E P Q n:
-  ElimModal True b false (|={E, E}▷=>^n P)%I P (|={E, E}▷=>^n Q)%I Q.
-Proof.
-  iIntros (_) "(P & HPQ)". iPoseProof (intuitionistically_if_elim with "P") as "P".
-  iInduction n as [ |n] "IH"; cbn.
-  - by iApply "HPQ".
-  - iMod "P". fold Nat.iter. by iApply ("IH" with "HPQ").
-Qed.
-Lemma fupd_fupd_step E P n :
- (|={E}=> |={E, E}▷=>^n P)%I -∗ |={E, E}▷=>^n (|={E}=> P)%I.
-Proof.
-  iIntros "H". iInduction n as [ | n] "IH"; cbn.
-  iApply "H".
-  iMod "H".
-  iApply "IH". iMod "H". iModIntro. iApply "H".
-Qed.
-
-Lemma fupd_step_fupd E P n :
- (|={E, E}▷=>^n |={E}=> P)%I -∗ (|={E}=> |={E, E}▷=>^n P)%I .
-Proof.
-  iIntros "H". iInduction n as [ | n] "IH". cbn.
-  iApply "H". iApply "IH". iModIntro.
-  iMod "H". iModIntro. iNext. iApply fupd_fupd_step.
-  iMod "H". iApply "IH". iApply "H".
-Qed.
-
-Lemma swp_wp_lstep k2 s E e Φ : to_val e = None →
-  (>={E}=={E}=> SWP e at k2 @ s ; E {{ Φ }}) ⊢ WP e @ s; E {{ Φ }}%I.
-Proof.
-  intros H; rewrite wp_unfold swp_unfold /wp_pre /swp_def H.
-  iIntros "WP". iIntros (σ1 κ κs n) "S".
-  do 2 iMod "WP". iDestruct ("WP") as (k1) "WP".
-  iApply (lstepN_lstep _ _ (k1 + (1 + k2))). iModIntro. iApply eventuallyN_compose.
-  iMod ("WP"). iApply eventuallyN_compose. iMod "WP".
-  iMod ("WP" with "S") as "WP".
-  do 4 iModIntro. do 2 iMod "WP". iModIntro.
-  iApply "WP".
-Qed.
-End wp.
-
-
-Section swp.
-  Context {SI} {Σ: gFunctors SI}  `{!irisG Λ Σ}.
-  Implicit Types s : stuckness.
-  Implicit Types P : iProp Σ.
-  Implicit Types Φ : val Λ → iProp Σ.
-  Implicit Types v : val Λ.
-  Implicit Types e : expr Λ.
-  Variable (k: nat).
-
-  Lemma swp_mono s E e Φ Ψ : (∀ v, Φ v ⊢ Ψ v) → SWP e at k @ s; E {{ Φ }} ⊢ SWP e at k @ s; E {{ Ψ }}.
-  Proof.
-    iIntros (HΦ) "H"; iApply (swp_strong_mono with "H"); auto.
-    iIntros (v) "?". by iApply HΦ.
-  Qed.
-  Lemma swp_stuck_mono s1 s2 E e Φ :
-    s1 ⊑ s2 → SWP e at k @ s1; E {{ Φ }} ⊢ SWP e at k @ s2; E {{ Φ }}.
-  Proof. iIntros (?) "H". iApply (swp_strong_mono with "H"); auto. Qed.
-  Lemma swp_stuck_weaken s E e Φ :
-    SWP e at k @ s; E {{ Φ }} ⊢ SWP e at k @ E ?{{ Φ }}.
-  Proof. apply swp_stuck_mono. by destruct s. Qed.
-  Lemma swp_mask_mono s E1 E2 e Φ : E1 ⊆ E2 → SWP e at k @ s; E1 {{ Φ }} ⊢ SWP e at k @ s; E2 {{ Φ }}.
-  Proof. iIntros (?) "H"; iApply (swp_strong_mono with "H"); auto. Qed.
-  Global Instance swp_mono' s E e :
-    Proper (pointwise_relation _ (⊢) ==> (⊢)) (swp (PROP:=iProp Σ) k s E e).
-  Proof. by intros Φ Φ' ?; apply swp_mono. Qed.
-
-  Lemma swp_frame_l s E e Φ R : R ∗ SWP e at k @ s; E {{ Φ }} ⊢ SWP e at k @ s; E {{ v, R ∗ Φ v }}.
-  Proof. iIntros "[? H]". iApply (swp_strong_mono with "H"); auto with iFrame. Qed.
-  Lemma swp_frame_r s E e Φ R : SWP e at k @ s; E {{ Φ }} ∗ R ⊢ SWP e at k @ s; E {{ v, Φ v ∗ R }}.
-  Proof. iIntros "[H ?]". iApply (swp_strong_mono with "H"); auto with iFrame. Qed.
-
-  Lemma swp_frame_step_l s E1 E2 e Φ R :
-    to_val e = None → E2 ⊆ E1 →
-    (|={E1,E2}▷=> R) ∗ SWP e at k @ s; E2 {{ Φ }} ⊢ SWP e at k @ s; E1 {{ v, R ∗ Φ v }}.
-  Proof.
-    iIntros (??) "[Hu Hwp]". iApply (swp_step_fupd with "Hu"); try done.
-    iApply (swp_mono with "Hwp"). by iIntros (?) "$$".
-  Qed.
-  Lemma swp_frame_step_r s E1 E2 e Φ R :
-    to_val e = None → E2 ⊆ E1 →
-    SWP e at k @ s; E2 {{ Φ }} ∗ (|={E1,E2}▷=> R) ⊢ SWP e at k @ s; E1 {{ v, Φ v ∗ R }}.
-  Proof.
-    rewrite [(WP _ @ _; _ {{ _ }} ∗ _)%I]comm; setoid_rewrite (comm _ _ R).
-    apply swp_frame_step_l.
-  Qed.
-  Lemma swp_frame_step_l' s E e Φ R :
-    to_val e = None → ▷ R ∗ SWP e at k @ s; E {{ Φ }} ⊢ SWP e at k @ s; E {{ v, R ∗ Φ v }}.
-  Proof. iIntros (?) "[??]". iApply (swp_frame_step_l s E E); try iFrame; eauto. Qed.
-  Lemma swp_frame_step_r' s E e Φ R :
-    to_val e = None → SWP e at k @ s; E {{ Φ }} ∗ ▷ R ⊢ SWP e at k @ s; E {{ v, Φ v ∗ R }}.
-  Proof. iIntros (?) "[??]". iApply (swp_frame_step_r s E E); try iFrame; eauto. Qed.
-
-  Lemma swp_wand s E e Φ Ψ :
-    SWP e at k @ s; E {{ Φ }} -∗ (∀ v, Φ v -∗ Ψ v) -∗ SWP e at k @ s; E {{ Ψ }}.
-  Proof.
-    iIntros "Hwp H". iApply (swp_strong_mono with "Hwp"); auto.
-    iIntros (?) "?". by iApply "H".
-  Qed.
-  Lemma swp_wand_l s E e Φ Ψ :
-    (∀ v, Φ v -∗ Ψ v) ∗ SWP e at k @ s; E {{ Φ }} ⊢ SWP e at k @ s; E {{ Ψ }}.
-  Proof. iIntros "[H Hwp]". iApply (swp_wand with "Hwp H"). Qed.
-  Lemma swp_wand_r s E e Φ Ψ :
-    SWP e at k @ s; E {{ Φ }} ∗ (∀ v, Φ v -∗ Ψ v) ⊢ SWP e at k @ s; E {{ Ψ }}.
-  Proof. iIntros "[Hwp H]". iApply (swp_wand with "Hwp H"). Qed.
-  Lemma swp_frame_wand_l s E e Q Φ :
-    Q ∗ SWP e at k @ s; E {{ v, Q -∗ Φ v }} -∗ SWP e at k @ s; E {{ Φ }}.
-  Proof.
-    iIntros "[HQ HWP]". iApply (swp_wand with "HWP").
-    iIntros (v) "HΦ". by iApply "HΦ".
-  Qed.
-
-  Lemma swp_finish E e s Φ : SWP e at 0%nat @ s; E {{ Φ }} ⊢ SWP e at 0%nat @ s; E {{ Φ }}.
-  Proof. eauto. Qed.
-End swp.
-
-(** Proofmode class instances *)
-Section proofmode_classes.
-  Context {SI} {Σ: gFunctors SI} `{!irisG Λ Σ}.
-  Implicit Types P Q : iProp Σ.
-  Implicit Types Φ : val Λ → iProp Σ.
-
-  Global Instance frame_wp p s E e R Φ Ψ :
-    (∀ v, Frame p R (Φ v) (Ψ v)) →
-    Frame p R (WP e @ s; E {{ Φ }}) (WP e @ s; E {{ Ψ }}).
-  Proof. rewrite /Frame=> HR. rewrite wp_frame_l. apply wp_mono, HR. Qed.
-
-  Global Instance frame_swp k p s E e R Φ Ψ :
-    (∀ v, Frame p R (Φ v) (Ψ v)) →
-    Frame p R (SWP e at k @ s; E {{ Φ }}) (SWP e at k @ s; E {{ Ψ }}).
-  Proof. rewrite /Frame=> HR. rewrite swp_frame_l. apply swp_mono, HR. Qed.
-
-  Global Instance is_except_0_wp s E e Φ : IsExcept0 (WP e @ s; E {{ Φ }}).
-  Proof. by rewrite /IsExcept0 -{2}fupd_wp -except_0_fupd -fupd_intro. Qed.
-
-  Global Instance is_except_0_swp k s E e Φ : IsExcept0 (SWP e at k @ s; E {{ Φ }}).
-  Proof. by rewrite /IsExcept0 -{2}fupd_swp -except_0_fupd -fupd_intro. Qed.
-
-  Global Instance elim_modal_bupd_wp p s E e P Φ :
-    ElimModal True p false (|==> P) P (WP e @ s; E {{ Φ }}) (WP e @ s; E {{ Φ }}).
-  Proof.
-    by rewrite /ElimModal intuitionistically_if_elim
-      (bupd_fupd E) fupd_frame_r wand_elim_r fupd_wp.
-  Qed.
-
-   Global Instance elim_modal_bupd_swp k p s E e P Φ :
-    ElimModal True p false (|==> P) P (SWP e at k @ s; E {{ Φ }}) (SWP e at k @ s; E {{ Φ }}).
-  Proof.
-    by rewrite /ElimModal intuitionistically_if_elim
-      (bupd_fupd E) fupd_frame_r wand_elim_r fupd_swp.
-  Qed.
-
-  Global Instance elim_modal_fupd_wp p s E e P Φ :
-    ElimModal True p false (|={E}=> P) P (WP e @ s; E {{ Φ }}) (WP e @ s; E {{ Φ }}).
-  Proof.
-    by rewrite /ElimModal intuitionistically_if_elim
-      fupd_frame_r wand_elim_r fupd_wp.
-  Qed.
-
-  Global Instance elim_modal_fupd_swp k p s E e P Φ :
-    ElimModal True p false (|={E}=> P) P (SWP e at k @ s; E {{ Φ }}) (SWP e at k @ s; E {{ Φ }}).
-  Proof.
-    by rewrite /ElimModal intuitionistically_if_elim
-      fupd_frame_r wand_elim_r fupd_swp.
-  Qed.
-
-  Global Instance elim_modal_fupd_wp_atomic s p E1 E2 e P Φ :
-    Atomic StronglyAtomic e →
-    ElimModal True p false (|={E1,E2}=> P) P
-            (WP e @ s; E1 {{ Φ }}) (WP e @ s; E2 {{ v, |={E2,E1}=> Φ v }})%I.
-  Proof.
-    intros. by rewrite /ElimModal intuitionistically_if_elim
-      fupd_frame_r wand_elim_r wp_atomic.
-  Qed.
-
-  Global Instance elim_modal_fupd_swp_atomic k s p E1 E2 e P Φ :
-    Atomic StronglyAtomic e →
-    ElimModal True p false (|={E1,E2}=> P) P
-            (SWP e at k @ s; E1 {{ Φ }}) (SWP e at k @ s; E2 {{ v, |={E2,E1}=> Φ v }})%I.
-  Proof.
-    intros. by rewrite /ElimModal intuitionistically_if_elim
-      fupd_frame_r wand_elim_r swp_atomic.
-  Qed.
-
-
-  Global Instance add_modal_fupd_wp s E e P Φ :
-    AddModal (|={E}=> P) P (WP e @ s; E {{ Φ }}).
-  Proof. by rewrite /AddModal fupd_frame_r wand_elim_r fupd_wp. Qed.
-
-  Global Instance add_modal_fupd_swp k s E e P Φ :
-    AddModal (|={E}=> P) P (SWP e at k @ s; E {{ Φ }}).
-  Proof. by rewrite /AddModal fupd_frame_r wand_elim_r fupd_swp. Qed.
-
-
-  Global Instance elim_acc_wp {X} s E1 E2 α β γ e Φ :
-    Atomic StronglyAtomic e →
-    ElimAcc (X:=X) (fupd E1 E2) (fupd E2 E1)
-            α β γ (WP e @ s; E1 {{ Φ }})
-            (λ x, WP e @ s; E2 {{ v, |={E2}=> β x ∗ (γ x -∗? Φ v) }})%I.
-  Proof.
-    intros ?. rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply (wp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-
-  Global Instance elim_acc_swp {X} k s E1 E2 α β γ e Φ :
-    Atomic StronglyAtomic e →
-    ElimAcc (X:=X) (fupd E1 E2) (fupd E2 E1)
-            α β γ (SWP e at k @ s; E1 {{ Φ }})
-            (λ x, SWP e at k @ s; E2 {{ v, |={E2}=> β x ∗ (γ x -∗? Φ v) }})%I.
-  Proof.
-    intros ?. rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply (swp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-
-  Global Instance elim_acc_wp_nonatomic {X} E α β γ e s Φ :
-    ElimAcc (X:=X) (fupd E E) (fupd E E)
-            α β γ (WP e @ s; E {{ Φ }})
-            (λ x, WP e @ s; E {{ v, |={E}=> β x ∗ (γ x -∗? Φ v) }})%I.
-  Proof.
-    rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply wp_fupd.
-    iApply (wp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-
-  Global Instance elim_acc_swp_nonatomic {X} k E α β γ e s Φ :
-    ElimAcc (X:=X) (fupd E E) (fupd E E)
-            α β γ (SWP e at k @ s; E {{ Φ }})
-            (λ x, SWP e at k @ s; E {{ v, |={E}=> β x ∗ (γ x -∗? Φ v) }})%I.
-  Proof.
-    rewrite /ElimAcc.
-    iIntros "Hinner >Hacc". iDestruct "Hacc" as (x) "[Hα Hclose]".
-    iApply swp_fupd.
-    iApply (swp_wand with "(Hinner Hα)").
-    iIntros (v) ">[Hβ HΦ]". iApply "HΦ". by iApply "Hclose".
-  Qed.
-End proofmode_classes.
-