Commit 1c0a0e04 by Robbert Krebbers

### Enable proof mode to destruct non-separating conjunctions in spatial context.

```This is allowed as long as one of the conjuncts is thrown away (i.e. is a
wildcard _ in the introduction pattern). It corresponds to the principle of
"external choice" in linear logic.```
parent 832cc0a5
 ... ... @@ -11,9 +11,9 @@ Implicit Types P Q : iProp Σ. Implicit Types Φ : val → iProp Σ. Implicit Types Δ : envs (iResUR Σ). Global Instance into_sep_mapsto l q v : IntoSep false (l ↦{q} v) (l ↦{q/2} v) (l ↦{q/2} v). Proof. by rewrite /IntoSep heap_mapsto_op_eq Qp_div_2. Qed. Global Instance into_and_mapsto l q v : IntoAnd false (l ↦{q} v) (l ↦{q/2} v) (l ↦{q/2} v). Proof. by rewrite /IntoAnd heap_mapsto_op_eq Qp_div_2. Qed. Lemma tac_wp_alloc Δ Δ' E j e v Φ : to_val e = Some v → ... ...
 ... ... @@ -169,44 +169,44 @@ Global Instance into_op_Some {A : cmraT} (a : A) b1 b2 : IntoOp a b1 b2 → IntoOp (Some a) (Some b1) (Some b2). Proof. by constructor. Qed. (* IntoSep *) Global Instance into_sep_sep p P Q : IntoSep p (P ★ Q) P Q. Proof. by apply mk_into_sep_sep. Qed. Global Instance into_sep_ownM p (a b1 b2 : M) : (* IntoAnd *) Global Instance into_and_sep p P Q : IntoAnd p (P ★ Q) P Q. Proof. by apply mk_into_and_sep. Qed. Global Instance into_and_ownM p (a b1 b2 : M) : IntoOp a b1 b2 → IntoSep p (uPred_ownM a) (uPred_ownM b1) (uPred_ownM b2). Proof. intros. apply mk_into_sep_sep. by rewrite (into_op a) ownM_op. Qed. IntoAnd p (uPred_ownM a) (uPred_ownM b1) (uPred_ownM b2). Proof. intros. apply mk_into_and_sep. by rewrite (into_op a) ownM_op. Qed. Global Instance into_sep_and P Q : IntoSep true (P ∧ Q) P Q. Global Instance into_and_and P Q : IntoAnd true (P ∧ Q) P Q. Proof. done. Qed. Global Instance into_sep_and_persistent_l P Q : PersistentP P → IntoSep false (P ∧ Q) P Q. Proof. intros; by rewrite /IntoSep /= always_and_sep_l. Qed. Global Instance into_sep_and_persistent_r P Q : PersistentP Q → IntoSep false (P ∧ Q) P Q. Proof. intros; by rewrite /IntoSep /= always_and_sep_r. Qed. Global Instance into_sep_later p P Q1 Q2 : IntoSep p P Q1 Q2 → IntoSep p (▷ P) (▷ Q1) (▷ Q2). Proof. rewrite /IntoSep=>->. destruct p; by rewrite ?later_and ?later_sep. Qed. Global Instance into_sep_big_sepM Global Instance into_and_and_persistent_l P Q : PersistentP P → IntoAnd false (P ∧ Q) P Q. Proof. intros; by rewrite /IntoAnd /= always_and_sep_l. Qed. Global Instance into_and_and_persistent_r P Q : PersistentP Q → IntoAnd false (P ∧ Q) P Q. Proof. intros; by rewrite /IntoAnd /= always_and_sep_r. Qed. Global Instance into_and_later p P Q1 Q2 : IntoAnd p P Q1 Q2 → IntoAnd p (▷ P) (▷ Q1) (▷ Q2). Proof. rewrite /IntoAnd=>->. destruct p; by rewrite ?later_and ?later_sep. Qed. Global Instance into_and_big_sepM `{Countable K} {A} (Φ Ψ1 Ψ2 : K → A → uPred M) p m : (∀ k x, IntoSep p (Φ k x) (Ψ1 k x) (Ψ2 k x)) → IntoSep p ([★ map] k ↦ x ∈ m, Φ k x) (∀ k x, IntoAnd p (Φ k x) (Ψ1 k x) (Ψ2 k x)) → IntoAnd p ([★ map] k ↦ x ∈ m, Φ k x) ([★ map] k ↦ x ∈ m, Ψ1 k x) ([★ map] k ↦ x ∈ m, Ψ2 k x). Proof. rewrite /IntoSep=> HΦ. destruct p. rewrite /IntoAnd=> HΦ. destruct p. - apply and_intro; apply big_sepM_mono; auto. + intros k x ?. by rewrite HΦ and_elim_l. + intros k x ?. by rewrite HΦ and_elim_r. - rewrite -big_sepM_sepM. apply big_sepM_mono; auto. Qed. Global Instance into_sep_big_sepS `{Countable A} (Φ Ψ1 Ψ2 : A → uPred M) p X : (∀ x, IntoSep p (Φ x) (Ψ1 x) (Ψ2 x)) → IntoSep p ([★ set] x ∈ X, Φ x) ([★ set] x ∈ X, Ψ1 x) ([★ set] x ∈ X, Ψ2 x). Global Instance into_and_big_sepS `{Countable A} (Φ Ψ1 Ψ2 : A → uPred M) p X : (∀ x, IntoAnd p (Φ x) (Ψ1 x) (Ψ2 x)) → IntoAnd p ([★ set] x ∈ X, Φ x) ([★ set] x ∈ X, Ψ1 x) ([★ set] x ∈ X, Ψ2 x). Proof. rewrite /IntoSep=> HΦ. destruct p. rewrite /IntoAnd=> HΦ. destruct p. - apply and_intro; apply big_sepS_mono; auto. + intros x ?. by rewrite HΦ and_elim_l. + intros x ?. by rewrite HΦ and_elim_r. ... ...
 ... ... @@ -32,12 +32,12 @@ Global Arguments from_and : clear implicits. Class FromSep (P Q1 Q2 : uPred M) := from_sep : Q1 ★ Q2 ⊢ P. Global Arguments from_sep : clear implicits. Class IntoSep (p : bool) (P Q1 Q2 : uPred M) := into_sep : P ⊢ if p then Q1 ∧ Q2 else Q1 ★ Q2. Global Arguments into_sep : clear implicits. Class IntoAnd (p : bool) (P Q1 Q2 : uPred M) := into_and : P ⊢ if p then Q1 ∧ Q2 else Q1 ★ Q2. Global Arguments into_and : clear implicits. Lemma mk_into_sep_sep p P Q1 Q2 : (P ⊢ Q1 ★ Q2) → IntoSep p P Q1 Q2. Proof. rewrite /IntoSep=>->. destruct p; auto using sep_and. Qed. Lemma mk_into_and_sep p P Q1 Q2 : (P ⊢ Q1 ★ Q2) → IntoAnd p P Q1 Q2. Proof. rewrite /IntoAnd=>->. destruct p; auto using sep_and. Qed. Class IntoOp {A : cmraT} (a b1 b2 : A) := into_op : a ≡ b1 ⋅ b2. Global Arguments into_op {_} _ _ _ {_}. ... ...
 ... ... @@ -652,15 +652,29 @@ Proof. Qed. (** * Conjunction/separating conjunction elimination *) Lemma tac_sep_destruct Δ Δ' i p j1 j2 P P1 P2 Q : envs_lookup i Δ = Some (p, P) → IntoSep p P P1 P2 → Lemma tac_and_destruct Δ Δ' i p j1 j2 P P1 P2 Q : envs_lookup i Δ = Some (p, P) → IntoAnd p P P1 P2 → envs_simple_replace i p (Esnoc (Esnoc Enil j1 P1) j2 P2) Δ = Some Δ' → (Δ' ⊢ Q) → Δ ⊢ Q. Proof. intros. rewrite envs_simple_replace_sound //; simpl. rewrite (into_sep p P). intros. rewrite envs_simple_replace_sound //; simpl. rewrite (into_and p P). by destruct p; rewrite /= ?right_id (comm _ P1) ?always_and_sep wand_elim_r. Qed. (* Using this tactic, one can destruct a (non-separating) conjunction in the spatial context as long as one of the conjuncts is thrown away. It corresponds to the principle of "external choice" in linear logic. *) Lemma tac_and_destruct_choice Δ Δ' i p (lr : bool) j P P1 P2 Q : envs_lookup i Δ = Some (p, P) → IntoAnd true P P1 P2 → envs_simple_replace i p (Esnoc Enil j (if lr then P1 else P2)) Δ = Some Δ' → (Δ' ⊢ Q) → Δ ⊢ Q. Proof. intros. rewrite envs_simple_replace_sound //; simpl. rewrite right_id (into_and true P). destruct lr. - by rewrite and_elim_l wand_elim_r. - by rewrite and_elim_r wand_elim_r. Qed. (** * Framing *) Lemma tac_frame Δ Δ' i p R P Q : envs_lookup_delete i Δ = Some (p, R, Δ') → Frame R P Q → ... ...
 ... ... @@ -6,9 +6,9 @@ Section ghost. Context `{inG Σ A}. Implicit Types a b : A. Global Instance into_sep_own p γ a b1 b2 : IntoOp a b1 b2 → IntoSep p (own γ a) (own γ b1) (own γ b2). Proof. intros. apply mk_into_sep_sep. by rewrite (into_op a) own_op. Qed. Global Instance into_and_own p γ a b1 b2 : IntoOp a b1 b2 → IntoAnd p (own γ a) (own γ b1) (own γ b2). Proof. intros. apply mk_into_and_sep. by rewrite (into_op a) own_op. Qed. Global Instance from_sep_own γ a b : FromSep (own γ (a ⋅ b)) (own γ a) (own γ b) | 90. Proof. by rewrite /FromSep own_op. Qed. ... ...