diff --git a/theories/proofmode/classes.v b/theories/proofmode/classes.v
index acef2f557eaa54b25e517d41736ef37700d32c74..2f1826329edda965abee1916c413120fc9394a8a 100644
--- a/theories/proofmode/classes.v
+++ b/theories/proofmode/classes.v
@@ -93,24 +93,29 @@ modality:
 - Introduction is only allowed when the context is empty.
 - Introduction is only allowed when all hypotheses satisfy some predicate
   `C : PROP → Prop` (where `C` should be a type class).
-- Introduction will only keep the hypotheses that satisfy some predicate
-  `C : PROP → Prop` (where `C` should be a type class).
+- Introduction will transform each hypotheses using a type class
+  `C : PROP → PROP → Prop`, where the first parameter is the input and the
+  second parameter is the output. Hypotheses that cannot be transformed (i.e.
+  for which no instance of `C` can be found) will be cleared.
 - Introduction will clear the context.
 - Introduction will keep the context as-if.
 
 Formally, these actions correspond to the following inductive type: *)
+
 Inductive always_intro_spec (PROP : bi) :=
   | AIEnvIsEmpty
   | AIEnvForall (C : PROP → Prop)
-  | AIEnvFilter (C : PROP → Prop)
+  | AIEnvTransform (C : PROP → PROP → Prop)
   | AIEnvClear
   | AIEnvId.
 Arguments AIEnvIsEmpty {_}.
 Arguments AIEnvForall {_} _.
-Arguments AIEnvFilter {_} _.
+Arguments AIEnvTransform {_} _.
 Arguments AIEnvClear {_}.
 Arguments AIEnvId {_}.
 
+Notation AIEnvFilter C := (AIEnvTransform (TCDiag C)).
+
 (* An always-style modality is then a record packing together the modality with
 the laws it should satisfy to justify the given actions for both contexts: *)
 Record always_modality_mixin {PROP : bi} (M : PROP → PROP)
@@ -118,7 +123,8 @@ Record always_modality_mixin {PROP : bi} (M : PROP → PROP)
   always_modality_mixin_persistent :
     match pspec with
     | AIEnvIsEmpty => True
-    | AIEnvForall C | AIEnvFilter C => ∀ P, C P → □ P ⊢ M (□ P)
+    | AIEnvForall C => ∀ P, C P → □ P ⊢ M (□ P)
+    | AIEnvTransform C => ∀ P Q, C P Q → □ P ⊢ M (□ Q)
     | AIEnvClear => True
     | AIEnvId => ∀ P, □ P ⊢ M (□ P)
     end;
@@ -126,7 +132,7 @@ Record always_modality_mixin {PROP : bi} (M : PROP → PROP)
     match sspec with
     | AIEnvIsEmpty => True
     | AIEnvForall C => ∀ P, C P → P ⊢ M P
-    | AIEnvFilter C => (∀ P, C P → P ⊢ M P) ∧ (∀ P, Absorbing (M P))
+    | AIEnvTransform C => (∀ P Q, C P Q → P ⊢ M Q) ∧ (∀ P, Absorbing (M P))
     | AIEnvClear => ∀ P, Absorbing (M P)
     | AIEnvId => False
     end;
@@ -154,8 +160,8 @@ Section always_modality.
   Lemma always_modality_persistent_forall C P :
     always_modality_persistent_spec M = AIEnvForall C → C P → □ P ⊢ M (□ P).
   Proof. destruct M as [??? []]; naive_solver. Qed.
-  Lemma always_modality_persistent_filter C P :
-    always_modality_persistent_spec M = AIEnvFilter C → C P → □ P ⊢ M (□ P).
+  Lemma always_modality_persistent_transform C P Q :
+    always_modality_persistent_spec M = AIEnvTransform C → C P Q → □ P ⊢ M (□ Q).
   Proof. destruct M as [??? []]; naive_solver. Qed.
   Lemma always_modality_persistent_id P :
     always_modality_persistent_spec M = AIEnvId → □ P ⊢ M (□ P).
@@ -163,11 +169,11 @@ Section always_modality.
   Lemma always_modality_spatial_forall C P :
     always_modality_spatial_spec M = AIEnvForall C → C P → P ⊢ M P.
   Proof. destruct M as [??? []]; naive_solver. Qed.
-  Lemma always_modality_spatial_filter C P :
-    always_modality_spatial_spec M = AIEnvFilter C → C P → P ⊢ M P.
+  Lemma always_modality_spatial_transform C P Q :
+    always_modality_spatial_spec M = AIEnvTransform C → C P Q → P ⊢ M Q.
   Proof. destruct M as [??? []]; naive_solver. Qed.
-  Lemma always_modality_spatial_filter_absorbing C P :
-    always_modality_spatial_spec M = AIEnvFilter C → Absorbing (M P).
+  Lemma always_modality_spatial_transform_absorbing C P :
+    always_modality_spatial_spec M = AIEnvTransform C → Absorbing (M P).
   Proof. destruct M as [??? []]; naive_solver. Qed.
   Lemma always_modality_spatial_clear P :
     always_modality_spatial_spec M = AIEnvClear → Absorbing (M P).
diff --git a/theories/proofmode/coq_tactics.v b/theories/proofmode/coq_tactics.v
index 840d129b0194424968ca9e44f40b46e103e5d48d..5209a681520962c4f71cb69b407bf1f37d7240c3 100644
--- a/theories/proofmode/coq_tactics.v
+++ b/theories/proofmode/coq_tactics.v
@@ -584,23 +584,24 @@ Lemma tac_pure_revert Δ φ Q : envs_entails Δ (⌜φ⌝ → Q) → (φ → env
 Proof. rewrite envs_entails_eq. intros HΔ ?. by rewrite HΔ pure_True // left_id. Qed.
 
 (** * Always modalities *)
-Class FilterPersistentEnv
-    (M : always_modality PROP) (C : PROP → Prop) (Γ1 Γ2 : env PROP) := {
-  filter_persistent_env :
-    (∀ P, C P → □ P ⊢ M (□ P)) →
+(** Transforming *)
+Class TransformPersistentEnv
+    (M : always_modality PROP) (C : PROP → PROP → Prop) (Γ1 Γ2 : env PROP) := {
+  transform_persistent_env :
+    (∀ P Q, C P Q → □ P ⊢ M (□ Q)) →
     □ ([∧] Γ1) ⊢ M (□ ([∧] Γ2));
-  filter_persistent_env_wf : env_wf Γ1 → env_wf Γ2;
-  filter_persistent_env_dom i : Γ1 !! i = None → Γ2 !! i = None;
+  transform_persistent_env_wf : env_wf Γ1 → env_wf Γ2;
+  transform_persistent_env_dom i : Γ1 !! i = None → Γ2 !! i = None;
 }.
-Global Instance filter_persistent_env_nil M C : FilterPersistentEnv M C Enil Enil.
+Global Instance transform_persistent_env_nil M C : TransformPersistentEnv M C Enil Enil.
 Proof.
   split=> // HC /=. rewrite !persistently_pure !affinely_True_emp.
   by rewrite affinely_emp -always_modality_emp.
 Qed.
-Global Instance filter_persistent_env_snoc M (C : PROP → Prop) Γ Γ' i P :
-  C P →
-  FilterPersistentEnv M C Γ Γ' →
-  FilterPersistentEnv M C (Esnoc Γ i P) (Esnoc Γ' i P).
+Global Instance transform_persistent_env_snoc M (C : PROP → PROP → Prop) Γ Γ' i P Q :
+  C P Q →
+  TransformPersistentEnv M C Γ Γ' →
+  TransformPersistentEnv M C (Esnoc Γ i P) (Esnoc Γ' i Q).
 Proof.
   intros ? [HΓ Hwf Hdom]; split; simpl.
   - intros HC. rewrite affinely_persistently_and HC // HΓ //.
@@ -608,9 +609,9 @@ Proof.
   - inversion 1; constructor; auto.
   - intros j. destruct (ident_beq _ _); naive_solver.
 Qed.
-Global Instance filter_persistent_env_snoc_not M (C : PROP → Prop) Γ Γ' i P :
-  FilterPersistentEnv M C Γ Γ' →
-  FilterPersistentEnv M C (Esnoc Γ i P) Γ' | 100.
+Global Instance transform_persistent_env_snoc_not M (C : PROP → PROP → Prop) Γ Γ' i P :
+  TransformPersistentEnv M C Γ Γ' →
+  TransformPersistentEnv M C (Esnoc Γ i P) Γ' | 100.
 Proof.
   intros [HΓ Hwf Hdom]; split; simpl.
   - intros HC. by rewrite and_elim_r HΓ.
@@ -618,20 +619,20 @@ Proof.
   - intros j. destruct (ident_beq _ _); naive_solver.
 Qed.
 
-Class FilterSpatialEnv
-    (M : always_modality PROP) (C : PROP → Prop) (Γ1 Γ2 : env PROP) := {
-  filter_spatial_env :
-    (∀ P, C P → P ⊢ M P) → (∀ P, Absorbing (M P)) →
+Class TransformSpatialEnv
+    (M : always_modality PROP) (C : PROP → PROP → Prop) (Γ1 Γ2 : env PROP) := {
+  transform_spatial_env :
+    (∀ P Q, C P Q → P ⊢ M Q) → (∀ P, Absorbing (M P)) →
     ([∗] Γ1) ⊢ M ([∗] Γ2);
-  filter_spatial_env_wf : env_wf Γ1 → env_wf Γ2;
-  filter_spatial_env_dom i : Γ1 !! i = None → Γ2 !! i = None;
+  transform_spatial_env_wf : env_wf Γ1 → env_wf Γ2;
+  transform_spatial_env_dom i : Γ1 !! i = None → Γ2 !! i = None;
 }.
-Global Instance filter_spatial_env_nil M C : FilterSpatialEnv M C Enil Enil.
+Global Instance transform_spatial_env_nil M C : TransformSpatialEnv M C Enil Enil.
 Proof. split=> // HC /=. by rewrite -always_modality_emp. Qed.
-Global Instance filter_spatial_env_snoc M (C : PROP → Prop) Γ Γ' i P :
-  C P →
-  FilterSpatialEnv M C Γ Γ' →
-  FilterSpatialEnv M C (Esnoc Γ i P) (Esnoc Γ' i P).
+Global Instance transform_spatial_env_snoc M (C : PROP → PROP → Prop) Γ Γ' i P Q :
+  C P Q →
+  TransformSpatialEnv M C Γ Γ' →
+  TransformSpatialEnv M C (Esnoc Γ i P) (Esnoc Γ' i Q).
 Proof.
   intros ? [HΓ Hwf Hdom]; split; simpl.
   - intros HC ?. by rewrite {1}(HC P) // HΓ // always_modality_sep.
@@ -639,9 +640,9 @@ Proof.
   - intros j. destruct (ident_beq _ _); naive_solver.
 Qed.
 
-Global Instance filter_spatial_env_snoc_not M (C : PROP → Prop) Γ Γ' i P :
-  FilterSpatialEnv M C Γ Γ' →
-  FilterSpatialEnv M C (Esnoc Γ i P) Γ' | 100.
+Global Instance transform_spatial_env_snoc_not M (C : PROP → PROP → Prop) Γ Γ' i P :
+  TransformSpatialEnv M C Γ Γ' →
+  TransformSpatialEnv M C (Esnoc Γ i P) Γ' | 100.
 Proof.
   intros [HΓ Hwf Hdom]; split; simpl.
   - intros HC ?. by rewrite HΓ // sep_elim_r.
@@ -649,28 +650,29 @@ Proof.
   - intros j. destruct (ident_beq _ _); naive_solver.
 Qed.
 
+(** The actual tactic *)
 Ltac tac_always_cases :=
   simplify_eq/=;
   repeat match goal with
   | H : TCAnd _ _ |- _ => destruct H
   | H : TCEq ?x _ |- _ => inversion H; subst x; clear H
   | H : TCForall _ _ |- _ => apply TCForall_Forall in H
-  | H : FilterPersistentEnv _ _ _ _ |- _ => destruct H
-  | H : FilterSpatialEnv _ _ _ _ |- _ => destruct H
+  | H : TransformPersistentEnv _ _ _ _ |- _ => destruct H
+  | H : TransformSpatialEnv _ _ _ _ |- _ => destruct H
   end; simpl; auto using Enil_wf.
 
 Lemma tac_always_intro Γp Γs Γp' Γs' M Q Q' :
   FromAlways M Q' Q →
   match always_modality_persistent_spec M with
   | AIEnvForall C => TCAnd (TCForall C (env_to_list Γp)) (TCEq Γp Γp')
-  | AIEnvFilter C => FilterPersistentEnv M C Γp Γp'
+  | AIEnvTransform C => TransformPersistentEnv M C Γp Γp'
   | AIEnvIsEmpty => TCAnd (TCEq Γp Enil) (TCEq Γp' Enil)
   | AIEnvClear => TCEq Γp' Enil
   | AIEnvId => TCEq Γp Γp'
   end →
   match always_modality_spatial_spec M with
   | AIEnvForall C => TCAnd (TCForall C (env_to_list Γs)) (TCEq Γs Γs')
-  | AIEnvFilter C => FilterSpatialEnv M C Γs Γs'
+  | AIEnvTransform C => TransformSpatialEnv M C Γs Γs'
   | AIEnvIsEmpty => TCAnd (TCEq Γs Enil) (TCEq Γs' Enil)
   | AIEnvClear => TCEq Γs' Enil
   | AIEnvId => TCEq Γs Γs'
@@ -689,15 +691,15 @@ Proof.
     + by rewrite {1}affinely_elim_emp (always_modality_emp M)
         persistently_True_emp affinely_persistently_emp.
     + eauto using always_modality_persistent_forall_big_and.
-    + eauto using always_modality_persistent_filter.
+    + eauto using always_modality_persistent_transform.
     + by rewrite {1}affinely_elim_emp (always_modality_emp M)
         persistently_True_emp affinely_persistently_emp.
     + eauto using always_modality_persistent_id.
   - destruct (always_modality_spatial_spec M) eqn:?; tac_always_cases.
     + by rewrite -always_modality_emp.
     + eauto using always_modality_spatial_forall_big_sep.
-    + eauto using always_modality_spatial_filter,
-        always_modality_spatial_filter_absorbing.
+    + eauto using always_modality_spatial_transform,
+        always_modality_spatial_transform_absorbing.
     + rewrite -(always_modality_spatial_clear M) // -always_modality_emp.
       by rewrite -absorbingly_True_emp absorbingly_pure -True_intro.
     + by destruct (always_modality_spatial_id M).
diff --git a/theories/proofmode/monpred.v b/theories/proofmode/monpred.v
index ae5a975dc089cc9b3a38037ff2257d87fae0457b..7c21befe8b4649358930b5a097bdb1bd1194a136 100644
--- a/theories/proofmode/monpred.v
+++ b/theories/proofmode/monpred.v
@@ -21,9 +21,10 @@ Context {I : biIndex} {PROP : bi}.
     always_modality_mixin (@monPred_absolutely I PROP)
       (AIEnvFilter Absolute) (AIEnvForall Absolute).
   Proof.
-    split; eauto using bi.equiv_entails_sym, absolute_absolutely,
-       monPred_absolutely_mono, monPred_absolutely_and,
-       monPred_absolutely_sep_2 with typeclass_instances.
+    split; intros; try match goal with H : TCDiag _ _ _ |- _ => destruct H end;
+      eauto using bi.equiv_entails_sym, absolute_absolutely,
+        monPred_absolutely_mono, monPred_absolutely_and,
+        monPred_absolutely_sep_2 with typeclass_instances.
   Qed.
   Definition always_modality_absolutely :=
     AlwaysModality _ always_modality_absolutely_mixin.
@@ -33,9 +34,10 @@ Context {I : biIndex} {PROP : bi}.
     always_modality_mixin (@monPred_absolutely I PROP)
       (AIEnvFilter Absolute) (AIEnvFilter Absolute).
   Proof.
-    split; eauto using bi.equiv_entails_sym, absolute_absolutely,
-       monPred_absolutely_mono, monPred_absolutely_and,
-       monPred_absolutely_sep_2 with typeclass_instances.
+    split; split_and?; intros; try match goal with H : TCDiag _ _ _ |- _ => destruct H end;
+      eauto using bi.equiv_entails_sym, absolute_absolutely,
+        monPred_absolutely_mono, monPred_absolutely_and,
+        monPred_absolutely_sep_2 with typeclass_instances.
   Qed.
   Definition always_modality_absolutely_filter_spatial `{BiAffine PROP} :=
     AlwaysModality _ always_modality_absolutely_filter_spatial_mixin.