diff --git a/proofmode/classes.v b/proofmode/classes.v
index a88e3daf7589a50410093919cddc839a0d754576..c25740c0c9c1663c832a2ac94b72beea773ae048 100644
--- a/proofmode/classes.v
+++ b/proofmode/classes.v
@@ -312,4 +312,7 @@ Proof. rewrite /IntoExist=> HP ?. by rewrite HP later_exist. Qed.
 Global Instance into_exist_always {A} P (Φ : A → uPred M) :
   IntoExist P Φ → IntoExist (□ P) (λ a, □ (Φ a))%I.
 Proof. rewrite /IntoExist=> HP. by rewrite HP always_exist. Qed.
+
+Class TimelessElim (Q : uPred M) :=
+  timeless_elim `{!TimelessP P} R : (R ⊢ Q) → ▷ P ★ (P -★ R) ⊢ Q.
 End classes.
diff --git a/proofmode/coq_tactics.v b/proofmode/coq_tactics.v
index 1ac516bbdb8313132fb8a765750b5d36be08700b..3b3bb0f129fda78c3c36315d29df4e322e46078a 100644
--- a/proofmode/coq_tactics.v
+++ b/proofmode/coq_tactics.v
@@ -375,6 +375,16 @@ Proof.
   by rewrite right_id always_and_sep_l' wand_elim_r HQ.
 Qed.
 
+Lemma tac_timeless Δ Δ' i p P Q :
+  TimelessElim Q →
+  envs_lookup i Δ = Some (p, ▷ P)%I → TimelessP P →
+  envs_simple_replace i p (Esnoc Enil i P) Δ = Some Δ' →
+  (Δ' ⊢ Q) → Δ ⊢ Q.
+Proof.
+  intros ???? HQ. rewrite envs_simple_replace_sound //; simpl.
+  rewrite always_if_later right_id. by apply timeless_elim.
+Qed.
+
 (** * Always *)
 Lemma tac_always_intro Δ Q : envs_persistent Δ = true → (Δ ⊢ Q) → Δ ⊢ □ Q.
 Proof. intros. by apply: always_intro. Qed.
diff --git a/proofmode/pviewshifts.v b/proofmode/pviewshifts.v
index e919ea13ed79a7e39039e44bd2c0b6a4d6ae6c57..8695abb15ce6943967504f3e8450b25da8c085c0 100644
--- a/proofmode/pviewshifts.v
+++ b/proofmode/pviewshifts.v
@@ -30,6 +30,12 @@ Global Instance into_wand_pvs E1 E2 R P Q :
   IntoWand R P Q → IntoWand R (|={E1,E2}=> P) (|={E1,E2}=> Q) | 100.
 Proof. rewrite /IntoWand=>->. apply wand_intro_l. by rewrite pvs_wand_r. Qed.
 
+Global Instance timeless_elim_pvs E1 E2 Q : TimelessElim (|={E1,E2}=> Q).
+Proof.
+  intros P ? R HR. rewrite (pvs_timeless E1 P) pvs_frame_r.
+  by rewrite wand_elim_r HR pvs_trans; last set_solver.
+Qed.
+
 Class IsFSA {A} (P : iProp Λ Σ) (E : coPset)
     (fsa : FSA Λ Σ A) (fsaV : Prop) (Φ : A → iProp Λ Σ) := {
   is_fsa : P ⊣⊢ fsa E Φ;
@@ -48,6 +54,12 @@ Global Instance to_assert_pvs {A} P Q E (fsa : FSA Λ Σ A) fsaV Φ :
 Proof.
   intros. by rewrite /IntoAssert pvs_frame_r wand_elim_r (is_fsa Q) fsa_pvs_fsa.
 Qed.
+Global Instance timeless_elim_fsa {A} Q E (fsa : FSA Λ Σ A) fsaV Φ :
+  IsFSA Q E fsa fsaV Φ → TimelessElim Q.
+Proof.
+  intros ? P ? R. rewrite (is_fsa Q) -{2}fsa_pvs_fsa. intros <-.
+  by rewrite (pvs_timeless _ P) pvs_frame_r wand_elim_r.
+Qed.
 
 Lemma tac_pvs_intro Δ E1 E2 Q : E1 = E2 → (Δ ⊢ Q) → Δ ⊢ |={E1,E2}=> Q.
 Proof. intros -> ->. apply pvs_intro. Qed.
@@ -74,26 +86,6 @@ Proof.
   intros ? -> ??. rewrite (is_fsa Q) -fsa_pvs_fsa.
   eapply tac_pvs_elim; set_solver.
 Qed.
-
-Lemma tac_pvs_timeless Δ Δ' E1 E2 i p P Q :
-  envs_lookup i Δ = Some (p, ▷ P)%I → TimelessP P →
-  envs_simple_replace i p (Esnoc Enil i P) Δ = Some Δ' →
-  (Δ' ={E1,E2}=> Q) → Δ ={E1,E2}=> Q.
-Proof.
-  intros ??? HQ. rewrite envs_simple_replace_sound //; simpl.
-  rewrite always_if_later (pvs_timeless E1 (â–¡?_ P)%I) pvs_frame_r.
-  by rewrite right_id wand_elim_r HQ pvs_trans; last set_solver.
-Qed.
-
-Lemma tac_pvs_timeless_fsa {A} (fsa : FSA Λ Σ A) fsaV Δ Δ' E i p P Q Φ :
-  IsFSA Q E fsa fsaV Φ →
-  envs_lookup i Δ = Some (p, ▷ P)%I → TimelessP P →
-  envs_simple_replace i p (Esnoc Enil i P) Δ = Some Δ' →
-  (Δ' ⊢ fsa E Φ) → Δ ⊢ Q.
-Proof.
-  intros ????. rewrite (is_fsa Q) -fsa_pvs_fsa.
-  eauto using tac_pvs_timeless.
-Qed.
 End pvs.
 
 Tactic Notation "iPvsIntro" := apply tac_pvs_intro; first try fast_done.
@@ -161,26 +153,5 @@ Tactic Notation "iPvs" open_constr(H) "as" "(" simple_intropattern(x1)
   iDestructHelp H as (fun H =>
     iPvsCore H; last iDestruct H as ( x1 x2 x3 x4 x5 x6 x7 x8 ) pat).
 
-Tactic Notation "iTimeless" constr(H) :=
-  match goal with
-  | |- _ ⊢ |={_,_}=> _ =>
-     eapply tac_pvs_timeless with _ H _ _;
-       [env_cbv; reflexivity || fail "iTimeless:" H "not found"
-       |let P := match goal with |- TimelessP ?P => P end in
-        apply _ || fail "iTimeless: " P "not timeless"
-       |env_cbv; reflexivity|simpl]
-  | |- _ =>
-     eapply tac_pvs_timeless_fsa with _ _ _ _ H _ _ _;
-       [let P := match goal with |- IsFSA ?P _ _ _ _ => P end in
-        apply _ || fail "iTimeless: " P "not a pvs"
-       |env_cbv; reflexivity || fail "iTimeless:" H "not found"
-       |let P := match goal with |- TimelessP ?P => P end in
-        apply _ || fail "iTimeless: " P "not timeless"
-       |env_cbv; reflexivity|simpl]
-  end.
-
-Tactic Notation "iTimeless" constr(H) "as" constr(Hs) :=
-  iTimeless H; iDestruct H as Hs.
-
 Hint Extern 2 (of_envs _ ⊢ _) =>
   match goal with |- _ ⊢ (|={_}=> _)%I => iPvsIntro end.
diff --git a/proofmode/tactics.v b/proofmode/tactics.v
index 8e6a504daeeecd6610e9e955fc0f37e0fa613d72..3901386c43ad909a114baeac44a5608ad5a6b1fd 100644
--- a/proofmode/tactics.v
+++ b/proofmode/tactics.v
@@ -501,6 +501,15 @@ Tactic Notation "iNext":=
     |let P := match goal with |- FromLater ?P _ => P end in
      apply _ || fail "iNext:" P "does not contain laters"|].
 
+Tactic Notation "iTimeless" constr(H) :=
+  eapply tac_timeless with _ H _ _;
+    [let Q := match goal with |- TimelessElim ?Q => Q end in
+     apply _ || fail "iTimeless: cannot eliminate later in goal" Q
+    |env_cbv; reflexivity || fail "iTimeless:" H "not found"
+    |let P := match goal with |- TimelessP ?P => P end in
+     apply _ || fail "iTimeless: " P "not timeless"
+    |env_cbv; reflexivity|].
+
 (** * Introduction tactic *)
 Local Tactic Notation "iIntro" "(" simple_intropattern(x) ")" := first
   [ (* (∀ _, _) *) apply tac_forall_intro; intros x