diff --git a/ProofMode.md b/ProofMode.md
index 1ec85aae0be89256272d166175a15ae628e12495..a7fa7c4376790efb01f4ab36d0b1f163e660ac2a 100644
--- a/ProofMode.md
+++ b/ProofMode.md
@@ -38,12 +38,17 @@ Context management
   the resulting goal.
 - `iPoseProof pm_trm as "H"` : put `pm_trm` into the context as a new hypothesis
   `H`.
-- `iAssert P with "spat" as "ipat"` : create a new goal with conclusion `P` and
-  put `P` in the context of the original goal. The specialization pattern
-  `spat` specifies which hypotheses will be consumed by proving `P`. The
-  introduction pattern `ipat` specifies how to eliminate `P`.
-- `iAssert P with "spat" as %cpat` : assert `P` and eliminate it using the Coq
-  introduction pattern `cpat`.
+- `iAssert P with "spat" as "ipat"` : generates a new subgoal `P` and adds the
+  hypothesis `P` to the current goal. The specialization pattern `spat`
+  specifies which hypotheses will be consumed by proving `P`. The introduction
+  pattern `ipat` specifies how to eliminate `P`.
+  In case all branches of `ipat` start with a `#` (which causes `P` to be moved
+  to the persistent context) or with an `%` (which causes `P` to be moved to the
+  pure Coq context), then one can use all hypotheses for proving `P` as well as
+  for proving the current goal.
+- `iAssert P as %cpat` : assert `P` and eliminate it using the Coq introduction
+  pattern `cpat`. All hypotheses can be used for proving `P` as well as for
+  proving the current goal.
 
 Introduction of logical connectives
 -----------------------------------
@@ -67,13 +72,16 @@ Elimination of logical connectives
 ----------------------------------
 
 - `iExFalso` : Ex falso sequitur quod libet.
-- `iDestruct pm_trm as (x1 ... xn) "ipat"` : elimination of existential
-  quantifiers using Coq introduction patterns `x1 ... xn` and elimination of
-  object level connectives using the proof mode introduction pattern `ipat`.
-  In case all branches of `ipat` start with an `#` (moving the hypothesis to the
-  persistent context) or `%` (moving the hypothesis to the pure Coq context),
-  one can use all hypotheses for proving the premises of `pm_trm`, as well as
-  for proving the resulting goal.
+- `iDestruct pm_trm as (x1 ... xn) "ipat"` : elimination of a series of
+  existential quantifiers using Coq introduction patterns `x1 ... xn`, and
+  elimination of an object level connective using the proof mode introduction
+  pattern `ipat`.
+  In case all branches of `ipat` start with a `#` (which causes the hypothesis
+  to be moved to the persistent context) or with an `%` (which causes the
+  hypothesis to be moved to the pure Coq context), then one can use all
+  hypotheses for proving the premises of `pm_trm`, as well as for proving the
+  resulting goal. Note that in this case the hypotheses still need to be
+  subdivided among the spatial premises.
 - `iDestruct pm_trm as %cpat` : elimination of a pure hypothesis using the Coq
   introduction pattern `cpat`. When using this tactic, all hypotheses can be
   used for proving the premises of `pm_trm`, as well as for proving the
diff --git a/theories/proofmode/coq_tactics.v b/theories/proofmode/coq_tactics.v
index c51703240d1ad5f930d9057b466d829cf3eecbb1..63e5989af0d5b9c8fc569d2933bac3827c239c98 100644
--- a/theories/proofmode/coq_tactics.v
+++ b/theories/proofmode/coq_tactics.v
@@ -608,13 +608,15 @@ Proof.
   by rewrite right_id HP HQ.
 Qed.
 
-Lemma tac_assert_persistent Δ Δ' j P Q :
-  envs_app true (Esnoc Enil j P) Δ = Some Δ' →
-  (Δ ⊢ P) → PersistentP P → (Δ' ⊢ Q) → Δ ⊢ Q.
+Lemma tac_assert_persistent Δ Δ1 Δ2 Δ' lr js j P Q :
+  envs_split lr js Δ = Some (Δ1,Δ2) →
+  envs_app false (Esnoc Enil j P) Δ = Some Δ' →
+  (Δ1 ⊢ P) → PersistentP P →
+  (Δ' ⊢ Q) → Δ ⊢ Q.
 Proof.
-  intros ? HP ??.
-  rewrite -(idemp uPred_and Δ) {1}HP envs_app_sound //; simpl.
-  by rewrite right_id {1}(persistentP P) always_and_sep_l wand_elim_r.
+  intros ?? HP ? <-. rewrite -(idemp uPred_and Δ) {1}envs_split_sound //.
+  rewrite HP sep_elim_l (always_and_sep_l P) envs_app_sound //; simpl.
+  by rewrite right_id wand_elim_r.
 Qed.
 
 Lemma tac_pose_proof Δ Δ' j P Q :
diff --git a/theories/proofmode/intro_patterns.v b/theories/proofmode/intro_patterns.v
index 54a95c7248c09686e9d8aee25d91b4ec0cfe0757..42760a8f817b1b4aee90fb4433b985acc412d987 100644
--- a/theories/proofmode/intro_patterns.v
+++ b/theories/proofmode/intro_patterns.v
@@ -17,14 +17,6 @@ Inductive intro_pat :=
   | IAll : intro_pat
   | IClear : list (bool * string) → intro_pat. (* true = frame, false = clear *)
 
-Fixpoint intro_pat_persistent (p : intro_pat) :=
-  match p with
-  | IPureElim => true
-  | IAlwaysElim _ => true
-  | IList pps => forallb (forallb intro_pat_persistent) pps
-  | _ => false
-  end.
-
 Module intro_pat.
 Inductive token :=
   | TName : string → token
@@ -186,3 +178,20 @@ Ltac parse_one s :=
      end
   end.
 End intro_pat.
+
+Fixpoint intro_pat_persistent (p : intro_pat) :=
+  match p with
+  | IPureElim => true
+  | IAlwaysElim _ => true
+  | IList pps => forallb (forallb intro_pat_persistent) pps
+  | _ => false
+  end.
+
+Ltac intro_pat_persistent p :=
+  lazymatch type of p with
+  | intro_pat => eval cbv in (intro_pat_persistent p)
+  | string =>
+     let pat := intro_pat.parse_one p in
+     eval cbv in (intro_pat_persistent pat)
+  | _ => p
+  end.
diff --git a/theories/proofmode/tactics.v b/theories/proofmode/tactics.v
index 3d3c2b9b1d2095cafdbe982a50931ef81e0f1e4f..d9aa76cd8d1b4d025e5e031e7a1302cc2886095f 100644
--- a/theories/proofmode/tactics.v
+++ b/theories/proofmode/tactics.v
@@ -325,18 +325,11 @@ Local Tactic Notation "iSpecializePat" constr(H) constr(pat) :=
          |go H1 pats]
     end in let pats := spec_pat.parse pat in go H pats.
 
-(* p = whether the conclusion of the specialized term is persistent. It can
-either be a Boolean or an introduction pattern, which will be coerced in true
-when it only contains `#` or `%` patterns at the top-level. *)
+(* The argument [p] denotes whether the conclusion of the specialized term is
+persistent. It can either be a Boolean or an introduction pattern, which will be
+coerced into [true] when it only contains `#` or `%` patterns at the top-level. *)
 Tactic Notation "iSpecializeCore" open_constr(t) "as" constr(p) tactic(tac) :=
-  let p :=
-    lazymatch type of p with
-    | intro_pat => eval cbv in (intro_pat_persistent p)
-    | string =>
-       let pat := intro_pat.parse_one p in
-       eval cbv in (intro_pat_persistent pat)
-    | _ => p
-    end in
+  let p := intro_pat_persistent p in
   lazymatch t with
   | ITrm ?H ?xs ?pat =>
     lazymatch type of H with
@@ -1122,41 +1115,61 @@ Tactic Notation "iLöb" "as" constr (IH) "forall" "(" ident(x1) ident(x2)
   iRevertIntros(x1 x2 x3 x4 x5 x6 x7 x8) Hs with (iLöbCore as IH).
 
 (** * Assert *)
-Tactic Notation "iAssertCore" open_constr(Q) "with" constr(Hs) "as" tactic(tac) :=
+(* The argument [p] denotes whether [Q] is persistent. It can either be a
+Boolean or an introduction pattern, which will be coerced into [true] when it
+only contains `#` or `%` patterns at the top-level. *)
+Tactic Notation "iAssertCore" open_constr(Q)
+    "with" constr(Hs) "as" constr(p) tactic(tac) :=
   iStartProof;
+  let p := intro_pat_persistent p in
   let H := iFresh in
   let Hs := spec_pat.parse Hs in
   lazymatch Hs with
   | [SGoalPersistent] =>
-     eapply tac_assert_persistent with _ H Q;
+     eapply tac_assert_persistent with _ _ _ true [] H Q;
        [env_cbv; reflexivity
+       |env_cbv; reflexivity
        |(*goal*)
        |apply _ || fail "iAssert:" Q "not persistent"
        |tac H]
   | [SGoal (SpecGoal ?m ?lr ?Hs_frame ?Hs)] =>
      let Hs' := eval cbv in (if lr then Hs else Hs_frame ++ Hs) in
-     eapply tac_assert with _ _ _ lr Hs' H Q _;
-       [match m with
-        | false => apply elim_modal_dummy
-        | true => apply _ || fail "iAssert: goal not a modality"
-        end
-       |env_cbv; reflexivity || fail "iAssert:" Hs "not found"
-       |env_cbv; reflexivity
-       |iFrame Hs_frame (*goal*)
-       |tac H]
+     match p with
+     | false =>
+       eapply tac_assert with _ _ _ lr Hs' H Q _;
+         [match m with
+          | false => apply elim_modal_dummy
+          | true => apply _ || fail "iAssert: goal not a modality"
+          end
+         |env_cbv; reflexivity || fail "iAssert:" Hs "not found"
+         |env_cbv; reflexivity
+         |iFrame Hs_frame (*goal*)
+         |tac H]
+     | true =>
+       eapply tac_assert_persistent with _ _ _ lr Hs' H Q;
+         [env_cbv; reflexivity
+         |env_cbv; reflexivity
+         |(*goal*)
+         |apply _ || fail "iAssert:" Q "not persistent"
+         |tac H]
+     end
   | ?pat => fail "iAssert: invalid pattern" pat
   end.
 
 Tactic Notation "iAssert" open_constr(Q) "with" constr(Hs) "as" constr(pat) :=
-  iAssertCore Q with Hs as (fun H => iDestructHyp H as pat).
+  iAssertCore Q with Hs as pat (fun H => iDestructHyp H as pat).
 Tactic Notation "iAssert" open_constr(Q) "as" constr(pat) :=
-  iAssert Q with "[]" as pat.
+  let p := intro_pat_persistent pat in
+  match p with
+  | true => iAssert Q with "[-]" as pat
+  | false => iAssert Q with "[]" as pat
+  end.
 
 Tactic Notation "iAssert" open_constr(Q) "with" constr(Hs)
     "as" "%" simple_intropattern(pat) :=
-  iAssertCore Q with Hs as (fun H => iPure H as pat).
+  iAssertCore Q with Hs as true (fun H => iPure H as pat).
 Tactic Notation "iAssert" open_constr(Q) "as" "%" simple_intropattern(pat) :=
-  iAssert Q with "[]" as %pat.
+  iAssert Q with "[-]" as %pat.
 
 (** * Rewrite *)
 Local Ltac iRewriteFindPred :=
diff --git a/theories/tests/proofmode.v b/theories/tests/proofmode.v
index 833b8fdc1f88cfb0b2e870089be3e35f4e58f35a..9e8e37be3adee535af4b05a800058d7b6bb2ab9f 100644
--- a/theories/tests/proofmode.v
+++ b/theories/tests/proofmode.v
@@ -105,3 +105,13 @@ End iris.
 Lemma demo_9 (M : ucmraT) (x y z : M) :
   ✓ x → ⌜y ≡ z⌝ -∗ (✓ x ∧ ✓ x ∧ y ≡ z : uPred M).
 Proof. iIntros (Hv) "Hxy". by iFrame (Hv Hv) "Hxy". Qed.
+
+Lemma demo_10 (M : ucmraT) (P Q : uPred M) : P -∗ Q -∗ True.
+Proof.
+  iIntros "HP HQ".
+  iAssert True%I as "#_". { by iClear "HP HQ". }
+  iAssert True%I with "[HP]" as "#_". { Fail iClear "HQ". by iClear "HP". }
+  iAssert True%I as %_. { by iClear "HP HQ". }
+  iAssert True%I with "[HP]" as %_. { Fail iClear "HQ". by iClear "HP". }
+  done.
+Qed.