We define assertions of Hoare logic using a shallow embedding. That is,
assertions are predicates over the contents of the stack and memory.
This file defines the data type of assertions, the usual connectives of
Hoare logic (∧, ¬, ↔, ∀ and ∃), the connectives of separation
logic (emp, ↦, ★), and other connectives that are more specific to
our development. We overload the usual notations in assert_scope to obtain
nicely looking assertions.
Require Export expression_eval_separation type_system memory_singleton.
Require Import type_system_decidable.
Local Obligation Tactic :=
idtac.
Local Hint Extern 1 (
_ ⊆
_) =>
etransitivity; [
eassumption|].
Local Hint Extern 1 (
_ ⊆
_) =>
etransitivity; [|
eassumption].
Local Hint Extern 1 (
_ ⊆{
_}
_) =>
etransitivity; [
eassumption|].
Local Hint Extern 1 (
_ ⊆{
_}
_) =>
etransitivity; [|
eassumption].
Definition of assertions
Record assert (
K :
Set) `{
Env K} :=
Assert {
assert_holds :
env K →
memenv K →
funenv K →
stack K →
nat →
mem K →
Prop;
assert_weaken Γ1 Γ2 Δ1 Δ2 δ1 δ2 ρ
n n'
m :
✓ Γ1 → ✓{Γ1,Δ1}
m → ✓{Δ1}* ρ →
assert_holds Γ1 Δ1 δ1 ρ
n m →
Γ1 ⊆ Γ2 → Δ1 ⇒ₘ Δ2 → δ1 ⊆ δ2 →
n' ≤
n →
assert_holds Γ2 Δ2 δ2 ρ
n'
m
}.
Add Printing Constructor assert.
Delimit Scope assert_scope with A.
Bind Scope assert_scope with assert.
Arguments Assert {
_ _}
_ _.
Arguments assert_holds {
_ _}
_%
A _ _ _ _ _ _.
Arguments assert_weaken {
_ _}
_%
A _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _.
The relation P ⊆@{Γ} Q states that the assertion Q is a logical
consequence of P in Γ and P ≡@{Γ} Q states that P and Q are logically
equivalent in Γ.
Instance assert_entails `{
Env K} :
SubsetEqE (
env K *
funenv K) (
assert K) := λ Γδ
P Q,
∀ Γ Δ δ ρ
n m,
Γδ.1 ⊆ Γ → ✓ Γ → Γδ.2 ⊆ δ → ✓{Γ,Δ} δ → ✓{Γ,Δ}
m → ✓{Δ}* ρ →
assert_holds P Γ Δ δ ρ
n m →
assert_holds Q Γ Δ δ ρ
n m.
Instance assert_equiv `{
Env K} :
EquivE (
env K *
funenv K) (
assert K) := λ Γδ
P Q,
P ⊆{Γδ}
Q ∧
Q ⊆{Γδ}
P.
Hoare logic connectives
Definitions and notations of the usual connectives of Hoare logic.
Program Definition assert_False `{
Env K} :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
False
|}.
Next Obligation.
naive_solver. Qed.
Notation "'
False'" :=
assert_False :
assert_scope.
Program Definition assert_True `{
Env K} :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
True
|}.
Next Obligation.
naive_solver. Qed.
Notation "'
True'" :=
assert_True :
assert_scope.
Program Definition assert_impl `{
Env K} (
P Q :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m := ∀ Γ' Δ' δ'
n',
Γ ⊆ Γ' → ✓ Γ' → Δ ⇒ₘ Δ' → δ ⊆ δ' → ✓{Γ',Δ'} δ' → ✓{Γ',Δ'}
m →
n' ≤
n →
assert_holds P Γ' Δ' δ' ρ
n'
m →
assert_holds Q Γ' Δ' δ' ρ
n'
m
|}.
Next Obligation.
intros ?? P Q Γ1 Γ2 Δ1 Δ2 δ1 δ2 ρ n1 n2 m ??? HPQ ???? Γ3 Δ3 δ3 n3 ????????.
apply HPQ; eauto; lia.
Qed.
Infix "→" :=
assert_impl :
assert_scope.
Notation "(→)" :=
assert_impl (
only parsing) :
assert_scope.
Notation "(
P →)" := (
assert_impl P) (
only parsing) :
assert_scope.
Notation "(→
Q )" := (λ
P,
assert_impl P Q) (
only parsing) :
assert_scope.
Program Definition assert_and `{
Env K} (
P Q :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
assert_holds P Γ Δ δ ρ
n m ∧
assert_holds Q Γ Δ δ ρ
n m
|}.
Next Obligation.
naive_solver eauto using assert_weaken. Qed.
Infix "∧" :=
assert_and :
assert_scope.
Notation "(∧)" :=
assert_and (
only parsing) :
assert_scope.
Notation "(
P ∧)" := (
assert_and P) (
only parsing) :
assert_scope.
Notation "(∧
Q )" := (λ
P,
assert_and P Q) (
only parsing) :
assert_scope.
Program Definition assert_or `{
Env K} (
P Q :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
assert_holds P Γ Δ δ ρ
n m ∨
assert_holds Q Γ Δ δ ρ
n m
|}.
Next Obligation.
naive_solver eauto using assert_weaken. Qed.
Infix "∨" :=
assert_or :
assert_scope.
Notation "(∨)" :=
assert_or (
only parsing) :
assert_scope.
Notation "(
P ∨)" := (
assert_or P) (
only parsing) :
assert_scope.
Notation "(∨
Q )" := (λ
P,
assert_or P Q) (
only parsing) :
assert_scope.
Definition assert_not `{
Env K} (
P :
assert K) :
assert K := (
P →
False)%
A.
Notation "¬
P" := (
assert_not P) :
assert_scope.
Definition assert_iff `{
Env K} (
P Q :
assert K) :
assert K :=
((
P →
Q) ∧ (
Q →
P))%
A.
Infix "↔" :=
assert_iff :
assert_scope.
Notation "(↔)" :=
assert_iff (
only parsing) :
assert_scope.
Notation "(
P ↔)" := (
assert_iff P) (
only parsing) :
assert_scope.
Notation "(↔
Q )" := (λ
P,
assert_iff P Q) (
only parsing) :
assert_scope.
Program Definition assert_forall `{
Env K} `(
P:
A →
assert K) :
assert K := {|
assert_holds := λ Γ Δ δ ρ
n m, ∀
x,
assert_holds (
P x) Γ Δ δ ρ
n m
|}.
Next Obligation.
naive_solver eauto using assert_weaken. Qed.
Notation "∀
x ..
y ,
P" :=
(
assert_forall (λ
x, .. (
assert_forall (λ
y,
P)) ..)) :
assert_scope.
Program Definition assert_exist `{
Env K} `(
P :
A →
assert K):
assert K := {|
assert_holds := λ Γ Δ δ ρ
n m, ∃
x,
assert_holds (
P x) Γ Δ δ ρ
n m
|}.
Next Obligation.
naive_solver eauto using assert_weaken. Qed.
Notation "∃
x ..
y ,
P" :=
(
assert_exist (λ
x, .. (
assert_exist (λ
y,
P)) ..)) :
assert_scope.
Program Definition assert_later `{
Env K} (
P :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m := ∀
n',
n' <
n →
assert_holds P Γ Δ δ ρ
n'
m
|}.
Next Obligation.
intros ?? P Γ1 Γ2 Δ1 Δ2 δ1 δ2 ρ n1 n2 m ???????? n3 ?.
eapply assert_weaken with _ _ _ n3; eauto with lia.
Qed.
Notation "▷
P" := (
assert_later P) (
at level 20) :
assert_scope.
Separation logic connectives
The assertion emp asserts that the memory is empty. The assertion P ★ Q
(called separating conjunction) asserts that the memory can be split into two
disjoint parts such that P holds in the one part, and Q in the other.
Program Definition assert_eq_mem `{
Env K} (
m :
mem K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m' :=
m' =
m
|}.
Next Obligation.
naive_solver. Qed.
Program Definition assert_Prop `{
Env K} (
P :
Prop) :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
P ∧
m = ∅
|}.
Next Obligation.
naive_solver. Qed.
Notation "⌜
P ⌝" := (
assert_Prop P) (
format "⌜
P ⌝") :
assert_scope.
Notation "'
emp'" := (
assert_Prop True) :
assert_scope.
Program Definition assert_sep `{
EnvSpec K} (
P Q :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m := ∃
m1 m2,
m =
m1 ∪
m2 ∧ ⊥[
m1;
m2] ∧
assert_holds P Γ Δ δ ρ
n m1 ∧
assert_holds Q Γ Δ δ ρ
n m2
|}.
Next Obligation.
intros ??? P Q Γ1 Γ2 Δ1 Δ2 δ1 δ2 ρ n m ???? (m1&m2&->&?&?&?) ????.
eauto 15 using assert_weaken, cmap_valid_subseteq,
@sep_union_subseteq_l, @sep_union_subseteq_r.
Qed.
Infix "★" :=
assert_sep (
at level 80,
right associativity) :
assert_scope.
Notation "(★)" :=
assert_sep (
only parsing) :
assert_scope.
Notation "(
P ★)" := (
assert_sep P) (
only parsing) :
assert_scope.
Notation "(★
Q )" := (λ
P,
assert_sep P Q) (
only parsing) :
assert_scope.
Class MemExt `{
EnvSpec K} (
P :
assert K) :
Prop :=
mem_ext Γ δ : (
P ★
True)%
A ⊆{Γ,δ}
P.
Hint Extern 10 (
MemExt _) =>
apply _.
Program Definition assert_wand `{
Env K} (
P Q :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m2 := ∀ Γ' Δ' δ'
n'
m1,
Γ ⊆ Γ' → ✓ Γ' → Δ ⇒ₘ Δ' → δ ⊆ δ' → ✓{Γ',Δ'} δ' →
n' ≤
n →
✓{Γ',Δ'}
m1 → ✓{Γ',Δ'}
m2 → ⊥[
m1;
m2] →
assert_holds P Γ' Δ' δ' ρ
n'
m1 →
assert_holds Q Γ' Δ' δ' ρ
n' (
m1 ∪
m2)
|}.
Next Obligation.
intros ?? P Q Γ Γ2 Δ Δ2 δ1 δ2 ρ n n2 m ??? HPQ ???? Γ3 Δ3 δ3 n3 ???????????.
apply HPQ; eauto; lia.
Qed.
Infix "-★" :=
assert_wand (
at level 90) :
assert_scope.
Notation "(-★)" :=
assert_wand (
only parsing) :
assert_scope.
Notation "(
P -★)" := (
assert_wand P) (
only parsing) :
assert_scope.
Notation "(-★
Q )" := (λ
P,
assert_wand P Q) (
only parsing) :
assert_scope.
The assertion Π Ps states that the memory can be split into disjoint
parts such that for each part the corresponding assertion in Ps holds.
Definition assert_sep_list `{
EnvSpec K} :
list (
assert K) →
assert K :=
foldr (★)%
A emp%
A.
Notation "'Π'
Ps" := (
assert_sep_list Ps)
(
at level 20,
format "Π
Ps") :
assert_scope.
The assertion e ⇓ v : τlr asserts that the expression e evaluates to v
and e ⇓ - : τlr asserts that the expression e evaluates to an arbitrary
value (in other words, e does not impose undefined behavior).
Notation vassert K := (
lrval K →
assert K).
Program Definition assert_expr `{
EnvSpec K} (
e :
expr K) :
vassert K := λ ν, {|
assert_holds Γ Δ δ ρ
n m := ∃ τ
lr, (Γ,Δ,ρ.*2) ⊢
e : τ
lr ∧ ⟦
e ⟧ Γ ρ
m =
Some ν
|}.
Next Obligation.
intros ??? e ν Γ1 Γ2 Δ1 Δ2 δ1 δ2 ρ n1 n2 m ??? (τlr&?&?) ??;
exists τlr; split; eauto using expr_typed_weaken, expr_eval_weaken,
mem_lookup_weaken, mem_forced_weaken.
Qed.
Notation "
e ⇓ ν" := (
assert_expr e ν)%
A
(
at level 60, ν
at next level,
format "
e '⇓' ν") :
assert_scope.
Notation "
e ⇓ -" := (∃ ν,
e ⇓ ν)%
A
(
at level 60,
format "
e '⇓' '-'") :
assert_scope.
The assertion e1 ↦{μ,γ} e2 asserts that the memory consists of
exactly one object at address e1 with permission x and contents e2. The
assertion e1 ↦{μ,γ} - asserts that the memory consists of exactly one
object at address e1 with permission x and arbitrary contents. The Boolean
μ denotes whether the object has been obtained via malloc.
Program Definition assert_singleton `{
EnvSpec K}
(
e1 :
expr K) (μ :
bool) (γ :
perm)
(
e2 :
expr K) (τ :
type K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m := ∃
a v,
(Γ,Δ,ρ.*2) ⊢
e1 :
inl (
TType τ) ∧ ⟦
e1 ⟧ Γ ρ ∅ =
Some (
inl (
Ptr a)) ∧
(Γ,Δ,ρ.*2) ⊢
e2 :
inr τ ∧ ⟦
e2 ⟧ Γ ρ ∅ =
Some (
inr v) ∧
mem_singleton Γ Δ
a μ γ
v τ
m
|}.
Next Obligation.
intros ??? e1 e2 ml γ τ Γ1 Γ2 Δ1 Δ2 δ1 δ2 ρ n1 n2 m ??? (a&v&?&?&?&?&?) ??.
exists a v; split_ands; eauto using expr_typed_weaken,
expr_eval_weaken_empty, mem_singleton_weaken, cmap_valid_memenv_valid.
Qed.
Notation "
e1 ↦{ μ , γ }
e2 : τ" := (
assert_singleton e1 μ γ
e2 τ)%
A
(
at level 20, μ
at next level, γ
at next level,
e2 at next level,
τ
at next level,
format "
e1 ↦{ μ , γ }
e2 : τ") :
assert_scope.
Notation "
e1 ↦{ μ , γ } - : τ" :=
(∃
v,
e1 ↦{μ,γ} (#
v) : τ)%
A
(
at level 20, μ
at next level, γ
at next level,
τ
at next level,
format "
e1 ↦{ μ , γ } - : τ") :
assert_scope.
The assertion P ◊ asserts that P holds if all sequenced locations
are unlocked.
Program Definition assert_unlock `{
EnvSpec K} (
P :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
assert_holds P Γ Δ δ ρ
n (
mem_unlock_all m)
|}.
Next Obligation.
naive_solver eauto using assert_weaken, mem_unlock_all_valid.
Qed.
Notation "
P ◊" := (
assert_unlock P) (
at level 20) :
assert_scope.
Class UnlockIndep `{
EnvSpec K} (
P :
assert K) :
Prop :=
unlock_indep Γ δ :
P ⊆{Γ,δ} (
P ◊)%
A.
Hint Extern 10 (
UnlockIndep _) =>
apply _.
To deal with block scope variables we need to lift an assertion such that
the De Bruijn indexes of its variables are increased. We define the lifting
P↑ of an assertion P semantically, and prove that it indeed behaves as
expected.
Program Definition assert_lift `{
Env K} (
P :
assert K) :
assert K := {|
assert_holds Γ Δ δ ρ
n m :=
assert_holds P Γ Δ δ (
tail ρ)
n m
|}.
Next Obligation.
naive_solver eauto using assert_weaken, Forall_tail. Qed.
Notation "
P ↑" := (
assert_lift P) (
at level 20) :
assert_scope.
Class StackIndep `{
Env K} (
P :
assert K) :
Prop :=
stack_indep Γ δ : (
P ↑)%
A ≡{Γ,δ}
P.
Hint Extern 10 (
StackIndep _) =>
apply _.
Section assertions.
Context `{
EnvSpec K}.
Implicit Types Γ :
env K.
Hint Unfold Proper respectful pointwise_relation :
assert.
Hint Unfold subseteqE assert_entails equivE assert_equiv :
assert.
Hint Unfold StackIndep UnlockIndep :
assert.
Hint Extern 100 (⊥
_) =>
solve_sep_disjoint.
Hint Extern 100 (
_ ⊥
_) =>
solve_sep_disjoint.
Hint Extern 100 (
sep_valid _) =>
solve_sep_disjoint.
Hint Immediate cmap_valid_sep_valid.
Hint Extern 0 (
_ ⊢
_ :
_ ↣
_) =>
typed_constructor;
try omega.
Hint Extern 0 (
_ ⊢
_ :
_) =>
typed_constructor.
Ltac solve t :=
repeat first
[
progress simplify_equality'
|
progress autounfold with assert in *];
naive_solver t.
Lemma assert_entails_spec P Q Γ Δ δ ρ
n m :
✓ Γ → ✓{Γ,Δ} δ → ✓{Γ,Δ}
m → ✓{Δ}* ρ →
P ⊆{Γ,δ}
Q →
assert_holds P Γ Δ δ ρ
n m →
assert_holds Q Γ Δ δ ρ
n m.
Proof.
intros ???? HPQ; apply HPQ; auto. Qed.
Ordinary logic connections
Global Instance:
PreOrder (⊆{Γ,δ}).
Proof.
split; solve eauto. Qed.
Global Instance:
Equivalence (≡{Γ,δ}).
Proof.
split; red; solve eauto. Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==>
iff) (⊆{Γ,δ}).
Proof.
solve eauto. Qed.
Global Instance:
Proper (
flip (⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (→)%
A.
Proof.
intros Γ1 δ1 P1 P2 HP Q1 Q2 HQ Γ2 Δ1 δ2 ρ n m ?????? HPQ Γ3 Δ2 δ3 n2 ????????.
eapply HQ; eauto 8 using indexes_valid_weaken.
Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (→)%
A.
Proof.
by intros ???? [??] ?? [??]; split; f_equiv. Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (∧)%
A.
Proof.
solve eauto. Qed.
Global Instance:
Proper ((⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (∧)%
A.
Proof.
solve eauto. Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (∨)%
A.
Proof.
solve eauto. Qed.
Global Instance:
Proper ((⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (∨)%
A.
Proof.
solve eauto. Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (↔)%
A.
Proof.
by intros ????????; unfold assert_iff; do 2 f_equiv. Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}))
assert_not.
Proof.
by intros ?????; unfold assert_not; f_equiv. Qed.
Global Instance:
Proper (
flip (⊆{Γ,δ}) ==> (⊆{Γ,δ}))
assert_not.
Proof.
by intros ?????; unfold assert_not; f_equiv. Qed.
Global Instance:
Proper (
pointwise_relation _ (≡{Γ,δ}) ==> (≡{Γ,δ})) (@
assert_forall _ _ A).
Proof.
solve eauto. Qed.
Global Instance:
Proper (
pointwise_relation _ (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (@
assert_forall _ _ A).
Proof.
solve eauto. Qed.
Global Instance:
Proper (
pointwise_relation _ (≡{Γ,δ}) ==> (≡{Γ,δ})) (@
assert_exist _ _ A).
Proof.
solve eauto. Qed.
Global Instance:
Proper (
pointwise_relation _ (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (@
assert_exist _ _ A).
Proof.
solve eauto. Qed.
Global Instance:
Proper (
pointwise_relation _ (
flip (⊆{Γ,δ})) ==> (
flip (⊆{Γ,δ})))
(@
assert_exist _ _ A).
Proof.
solve eauto. Qed.
Global Instance:
Commutative (≡{Γ,δ}) (↔)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Commutative (≡{Γ,δ}) (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Associative (≡{Γ,δ}) (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Idempotent (≡{Γ,δ}) (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
LeftId (≡{Γ,δ})
True%
A (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
RightId (≡{Γ,δ})
True%
A (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
LeftAbsorb (≡{Γ,δ})
False%
A (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
RightAbsorb (≡{Γ,δ})
False%
A (∧)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Commutative (≡{Γ,δ}) (∨)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Associative (≡{Γ,δ}) (∨)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Idempotent (≡{Γ,δ}) (∨)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
LeftId (≡{Γ,δ})
False%
A (∨)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
RightId (≡{Γ,δ})
False%
A (∨)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
LeftAbsorb (≡{Γ,δ})
True%
A (∨)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
RightAbsorb (≡{Γ,δ})
True%
A (∨)%
A.
Proof.
red; solve eauto. Qed.
Lemma assert_False_elim Γ δ
P :
False%
A ⊆{Γ,δ}
P.
Proof.
solve eauto. Qed.
Lemma assert_True_intro Γ δ
P :
P ⊆{Γ,δ}
True%
A.
Proof.
solve eauto. Qed.
Lemma assert_and_l Γ δ
P Q : (
P ∧
Q)%
A ⊆{Γ,δ}
P.
Proof.
solve eauto. Qed.
Lemma assert_and_r Γ δ
P Q : (
P ∧
Q)%
A ⊆{Γ,δ}
Q.
Proof.
solve eauto. Qed.
Lemma assert_impl_and Γ δ
P Q :
P ⊆{Γ,δ}
Q →
P ≡{Γ,δ} (
P ∧
Q)%
A.
Proof.
solve eauto. Qed.
Lemma assert_and_intro Γ δ
P Q1 Q2 :
P ⊆{Γ,δ}
Q1 →
P ⊆{Γ,δ}
Q2 →
P ⊆{Γ,δ} (
Q1 ∧
Q2)%
A.
Proof.
solve eauto. Qed.
Lemma assert_and_elim_l Γ δ
P1 P2 Q :
P1 ⊆{Γ,δ}
Q → (
P1 ∧
P2)%
A ⊆{Γ,δ}
Q.
Proof.
solve eauto. Qed.
Lemma assert_and_elim_r Γ δ
P1 P2 Q :
P2 ⊆{Γ,δ}
Q → (
P1 ∧
P2)%
A ⊆{Γ,δ}
Q.
Proof.
solve eauto. Qed.
Lemma assert_or_l Γ δ
P Q :
P ⊆{Γ,δ} (
P ∨
Q)%
A.
Proof.
solve eauto. Qed.
Lemma assert_or_r Γ δ
P Q :
Q ⊆{Γ,δ} (
P ∨
Q)%
A.
Proof.
solve eauto. Qed.
Lemma assert_forall_intro {
A} Γ δ
P (
Q :
A →
assert K) :
(∀
x,
P ⊆{Γ,δ}
Q x) →
P ⊆{Γ,δ} (∀
x,
Q x)%
A.
Proof.
solve eauto. Qed.
Lemma assert_forall_elim {
A} Γ δ (
P :
A →
assert K)
Q x :
(
P x ⊆{Γ,δ}
Q) → (∀
x,
P x)%
A ⊆{Γ,δ}
Q.
Proof.
solve eauto. Qed.
Lemma assert_exist_intro {
A} Γ δ
P (
Q :
A →
assert K)
x :
P ⊆{Γ,δ}
Q x →
P ⊆{Γ,δ} (∃
x,
Q x)%
A.
Proof.
solve eauto. Qed.
Lemma assert_exist_elim {
A} Γ δ (
P :
A →
assert K)
Q :
(∀
x,
P x ⊆{Γ,δ}
Q) → (∃
x,
P x)%
A ⊆{Γ,δ}
Q.
Proof.
solve eauto. Qed.
Lemma assert_and_exist {
A} Γ δ
P (
Q :
A →
assert K) :
(
P ∧ ∃
x,
Q x)%
A ≡{Γ,δ} (∃
x,
P ∧
Q x)%
A.
Proof.
solve eauto. Qed.
Lemma assert_exist_and {
A} Γ δ (
P :
A →
assert K)
Q :
((∃
x,
P x) ∧
Q)%
A ≡{Γ,δ} (∃
x,
P x ∧
Q)%
A.
Proof.
solve eauto. Qed.
Lemma assert_exist_exist {
A B} Γ δ (
P :
A →
B →
assert K) :
(∃
x y,
P x y)%
A ≡{Γ,δ} (∃
y x,
P x y)%
A.
Proof.
solve eauto. Qed.
Later
Lemma assert_later_lob Γ δ
P : (▷
P →
P)%
A ⊆{Γ,δ}
P.
Proof.
intros Γ1 Δ δ1 ρ n m ?????? HP; induction n as [|n IH].
{ apply HP; eauto. intros n'; lia. }
eapply HP; eauto. intros n' ?.
eapply assert_weaken with _ _ δ1 n; eauto with lia.
eapply IH, assert_weaken with _ _ _ (S n); eauto with lia.
Qed.
Lemma assert_later_weaken Γ δ
P :
P ⊆{Γ,δ} (▷
P)%
A.
Proof.
intros Γ1 Δ ρ δ1 n m ??????? n' ?.
eapply assert_weaken with _ _ _ n; eauto with lia.
Qed.
Lemma assert_later_impl Γ δ
P Q : (▷(
P →
Q))%
A ⊆{Γ,δ} (▷
P → ▷
Q)%
A.
Proof.
intros Γ1 Δ1 δ1 ρ n1 m ?????? HPQ Γ2 Δ2 δ2 n2 ???????? n3 ?.
eapply HPQ; eauto; lia.
Qed.
Lemma assert_later_and Γ δ
P Q : (▷(
P ∧
Q))%
A ≡{Γ,δ} (▷
P ∧ ▷
Q)%
A.
Proof.
solve eauto. Qed.
Lemma assert_later_or Γ δ
P Q : (▷
P ∨ ▷
Q)%
A ⊆{Γ,δ} (▷(
P ∨
Q))%
A.
Proof.
solve eauto. Qed.
Lemma assert_later_forall {
A} Γ δ (
P :
A →
assert K) :
(▷(∀
x,
P x))%
A ≡{Γ,δ} (∀
x, ▷(
P x))%
A.
Proof.
solve eauto. Qed.
Lemma assert_later_exists {
A} Γ δ (
P :
A →
assert K) :
(∃
x, ▷(
P x))%
A ⊆{Γ,δ} (▷(∃
x,
P x))%
A.
Proof.
solve eauto. Qed.
Separation logic connectives
Global Instance:
Proper (
impl ==> (⊆{Γ,δ}))
assert_Prop.
Proof.
solve eauto. Qed.
Global Instance:
Proper (
iff ==> (≡{Γ,δ}))
assert_Prop.
Proof.
solve eauto. Qed.
Global Instance:
Proper ((⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (★)%
A.
Proof.
solve ltac:(eauto 15 using cmap_valid_subseteq,
@sep_union_subseteq_l, @sep_union_subseteq_r).
Qed.
Global Instance:
Proper (
flip (⊆{Γ,δ}) ==>
flip (⊆{Γ,δ}) ==>
flip (⊆{Γ,δ})) (★)%
A.
Proof.
solve ltac:(eauto 15 using cmap_valid_subseteq,
@sep_union_subseteq_l, @sep_union_subseteq_r).
Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (★)%
A.
Proof.
by intros ???? [??] ?? [??]; split;
apply (_ : Proper ((⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (★)%A).
Qed.
Global Instance:
Proper (
Forall2 (≡{Γ,δ}) ==> (≡{Γ,δ}))
assert_sep_list.
Proof.
induction 1; simpl; [done|];
by apply (_ : Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (★)%A).
Qed.
Global Instance:
Proper (
flip (⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (-★)%
A.
Proof.
intros Γ1 δ1 P1 P2 HP Q1 Q2 HQ Γ2 Δ1 δ2 ρ n1 m
?????? HPQ Γ3 Δ2 δ3 n2 ???????????.
apply HQ; eauto 10 using indexes_valid_weaken, cmap_union_valid_2.
Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}) ==> (≡{Γ,δ})) (-★)%
A.
Proof.
by intros ???? [??] ?? [??]; split;
apply (_ : Proper (flip (⊆{Γ,δ}) ==> (⊆{Γ,δ}) ==> (⊆{Γ,δ})) (-★)%A).
Qed.
Global Instance:
Commutative (⊆{Γ,δ}) (★)%
A.
Proof.
intros Γ δ P Q Γ1 Δ δ1 ρ n m ?????? (m1&m2&->&?&?&?).
exists m2 m1. rewrite sep_commutative by auto; auto.
Qed.
Global Instance:
Commutative (≡{Γ,δ}) (★)%
A.
Proof.
split; by rewrite (commutative (★)%A). Qed.
Global Instance:
LeftId (≡{Γ,δ})
emp%
A (★)%
A.
Proof.
intros δ Γ; intros P; split.
* intros Γ1 Δ δ1 ρ n m ?????? (m1&m2&->&?&[_ ->]&?).
rewrite sep_left_id by auto; auto.
* intros Γ1 Δ δ1 ρ n m ???????. eexists ∅, m.
rewrite sep_left_id, sep_disjoint_equiv_empty,
sep_disjoint_list_singleton by eauto; solve eauto.
Qed.
Global Instance:
RightId (≡{Γ,δ})
emp%
A (★)%
A.
Proof.
intros ???. by rewrite (commutative _), (left_id _ _). Qed.
Global Instance:
LeftAbsorb (≡{Γ,δ})
False%
A (★)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
RightAbsorb (≡{Γ,δ})
False%
A (★)%
A.
Proof.
red; solve eauto. Qed.
Global Instance:
Associative (≡{Γ,δ}) (★)%
A.
Proof.
intros Γ δ. assert (∀ P Q R, ((P ★ Q) ★ R)%A ⊆{Γ,δ} (P ★ (Q ★ R))%A).
{ intros P Q R Γ1 Δ δ1 ρ ? n ?????? (?&m3&->&?&(m1&m2&->&?&?&?)&?).
exists m1 (m2 ∪ m3); rewrite sep_associative by auto; split_ands; auto.
exists m2 m3; auto. }
assert (∀ P Q R, (P ★ (Q ★ R))%A ⊆{Γ,δ} ((P ★ Q) ★ R)%A).
{ intros P Q R Γ1 Δ δ1 ρ ? n ?????? (m1&?&->&?&?&(m2&m3&->&?&?&?)).
exists (m1 ∪ m2) m3; rewrite sep_associative by auto; split_ands; auto.
exists m1 m2; auto. }
split; auto.
Qed.
Lemma assert_Prop_impl Γ δ (
P Q :
Prop) : ⌜
P →
Q ⌝%
A ⊆{Γ,δ} (⌜
P⌝ → ⌜
Q⌝)%
A.
Proof.
solve eauto. Qed.
Lemma assert_Prop_not Γ δ (
P :
Prop) : ⌜ ¬
P ⌝%
A ⊆{Γ,δ} (¬⌜
P⌝)%
A.
Proof.
solve eauto. Qed.
Lemma assert_Prop_and Γ δ (
P Q :
Prop) : ⌜
P ∧
Q ⌝%
A ≡{Γ,δ} (⌜
P⌝ ∧ ⌜
Q⌝)%
A.
Proof.
solve eauto. Qed.
Lemma assert_Prop_or Γ δ (
P Q :
Prop) : ⌜
P ∨
Q ⌝%
A ≡{Γ,δ} (⌜
P⌝ ∨ ⌜
Q⌝)%
A.
Proof.
solve eauto. Qed.
Lemma assert_Prop_l Γ δ (
P :
Prop)
Q :
P → (⌜
P ⌝ ★
Q)%
A ≡{Γ,δ}
Q.
Proof.
intros. assert (P ↔ True) as -> by (by split; intros _).
by rewrite (left_id emp%A _).
Qed.
Lemma assert_Prop_r Γ δ (
P :
Prop)
Q :
P → (
Q ★ ⌜
P ⌝)%
A ≡{Γ,δ}
Q.
Proof.
intros. by rewrite (commutative (★))%A, assert_Prop_l. Qed.
Lemma assert_Prop_intro_l Γ δ (
P :
Prop)
Q R :
(
P →
Q ⊆{Γ,δ}
R) → (⌜
P ⌝ ★
Q)%
A ⊆{Γ,δ}
R.
Proof.
intros HQR Γ1 Δ δ1 ρ n ????? Hm ? (m1&m2&->&?&[? ->]&?).
rewrite sep_left_id in Hm |- * by auto; by apply HQR.
Qed.
Lemma assert_Prop_intro_r Γ δ (
P :
Prop)
Q R :
(
P →
Q ⊆{Γ,δ}
R) → (
Q ★ ⌜
P ⌝)%
A ⊆{Γ,δ}
R.
Proof.
rewrite (commutative (★)%A). by apply assert_Prop_intro_l. Qed.
Lemma assert_Prop_True Γ δ
P (
Q :
Prop) :
P ⊆{Γ,δ} (⌜
Q ⌝ ★
True)%
A →
P ⊆{Γ,δ} (⌜
Q ⌝ ★
P)%
A.
Proof.
intros HPQ Γ1 Δ δ1 ρ n m ?????? HP.
destruct (HPQ Γ1 Δ δ1 ρ n m) as (m1&m2&->&?&[? ->]&?); auto.
rewrite sep_left_id in HP by auto; solve eauto.
Qed.
Lemma assert_sep_preserving Γ δ
P P'
Q Q' :
P ⊆{Γ,δ}
P' →
Q ⊆{Γ,δ}
Q' → (
P ★
Q)%
A ⊆{Γ,δ} (
P' ★
Q')%
A.
Proof.
intros HP HQ. by rewrite HP, HQ. Qed.
Lemma assert_sep_exist {
A} Γ δ
P (
Q :
A →
assert K) :
(
P ★ ∃
x,
Q x)%
A ≡{Γ,δ} (∃
x,
P ★
Q x)%
A.
Proof.
solve eauto. Qed.
Lemma assert_exist_sep {
A} Γ δ (
P :
A →
assert K)
Q :
((∃
x,
P x) ★
Q)%
A ≡{Γ,δ} (∃
x,
P x ★
Q)%
A.
Proof.
solve eauto. Qed.
Lemma assert_wand_intro Γ δ
P Q R : (
P ★
Q)%
A ⊆{Γ,δ}
R →
P ⊆{Γ,δ} (
Q -★
R)%
A.
Proof.
intros HPQR Γ1 Δ1 ρ δ1 n1 m1 ?????? HP Γ2 Δ2 δ2 n2 m2 ????????? HQ.
apply HPQR; eauto using indexes_valid_weaken, cmap_union_valid_2.
exists m1 m2; split_ands; eauto using assert_weaken, @sep_commutative.
Qed.
Lemma assert_wand_elim Γ δ
P Q : ((
P -★
Q) ★
P)%
A ⊆{Γ,δ}
Q.
Proof.
intros Γ1 Δ1 ρ δ1 n ??????? (m1&m2&->&?&HQ&?).
rewrite sep_commutative by auto; eapply HQ; eauto using
cmap_valid_subseteq, @sep_union_subseteq_l, @sep_union_subseteq_r.
Qed.
Global Instance:
LeftId (≡{Γ,δ})
emp%
A (-★)%
A.
Proof.
intros Γ P; split.
* rewrite <-(right_id _ (★)%A); apply assert_wand_elim.
* apply assert_wand_intro. by rewrite (right_id _ (★)%A).
Qed.
Lemma assert_Forall_holds_2 (
Ps :
list (
assert K)) Γ Δ δ ρ
ms n :
⊥
ms →
Forall2 (λ (
P :
assert K)
m,
assert_holds P Γ Δ δ ρ
n m)
Ps ms →
assert_holds (Π
Ps)%
A Γ Δ δ ρ
n (⋃
ms).
Proof.
intros Hms HPs. revert Hms. induction HPs; solve eauto. Qed.
Lemma assert_Forall_holds (
Ps :
list (
assert K)) Γ Δ δ ρ
n m :
assert_holds (Π
Ps)%
A Γ Δ δ ρ
n m ↔ ∃
ms,
m = ⋃
ms ∧ ⊥
ms ∧
Forall2 (λ (
P :
assert K)
m,
assert_holds P Γ Δ δ ρ
n m)
Ps ms.
Proof.
split; [|naive_solver eauto using assert_Forall_holds_2].
revert m. induction Ps as [|P Ps IH].
{ intros m [? ->]. eexists []. by repeat constructor. }
intros ? (m1&m2&->&?&?&?); destruct (IH m2) as (ms&->&?&?); trivial.
exists (m1 :: ms); auto.
Qed.
Lemma assert_Forall_holds_vec {
vn} (
Ps :
vec (
assert K)
vn) Γ Δ δ ρ
n m :
assert_holds (Π
Ps)%
A Γ Δ δ ρ
n m ↔ ∃
ms :
vec _ vn,
m = ⋃
ms ∧ ⊥
ms ∧
∀
i,
assert_holds (
Ps !!!
i) Γ Δ δ ρ
n (
ms !!!
i).
Proof.
rewrite assert_Forall_holds; split.
* intros (ms&->&?&Hms). assert (vn = length ms); [|subst vn].
{ by erewrite <-Forall2_length, vec_to_list_length by eauto. }
exists (list_to_vec ms); rewrite ?vec_to_list_of_list.
by rewrite <-(vec_to_list_of_list ms), Forall2_vlookup in Hms.
* intros [ms ?]; exists ms; by rewrite Forall2_vlookup.
Qed.
Lemma assert_memext_l Γ δ
P Q :
MemExt P → (
P ★
Q)%
A ⊆{Γ,δ}
P.
Proof.
intros; transitivity (P ★ True)%A;
auto using assert_sep_preserving, assert_True_intro.
Qed.
Lemma assert_memext_r Γ δ
P Q :
MemExt P → (
Q ★
P)%
A ⊆{Γ,δ}
P.
Proof.
rewrite (commutative (★)%A). apply assert_memext_l. Qed.
Lemma assert_memext_l' Γ δ
P Q R :
MemExt R →
P ⊆{Γ,δ}
R → (
P ★
Q)%
A ⊆{Γ,δ}
R.
Proof.
intros. rewrite <-(assert_memext_l _ _ R) by done.
eauto using assert_sep_preserving.
Qed.
Lemma assert_memext_r' Γ δ
P Q R :
MemExt R →
Q ⊆{Γ,δ}
R → (
P ★
Q)%
A ⊆{Γ,δ}
R.
Proof.
rewrite (commutative (★)%A). apply assert_memext_l'. Qed.
Global Instance assert_eval_memext e ν :
MemExt (
e ⇓ ν)%
A.
Proof.
intros Γ δ Γ' Δ δ' ρ n m ???? Hm ? (m1&m2&->&?&(τlr&?&?)&?).
exists τlr; split; auto.
rewrite cmap_union_valid in Hm by auto; destruct Hm.
eapply expr_eval_subseteq with _ m1 _; eauto using @sep_union_subseteq_l'.
Qed.
Lemma assert_int_typed_eval Γ δ
P x τ
i :
int_typed x τ
i →
P ⊆{Γ,δ} (#
intV{τ
i}
x ⇓
inr (
intV{τ
i}
x))%
A.
Proof.
intros ? Γ' Δ ρ δ' n m ??????.
eexists (inr (intT τi)%T); split; auto using lockset_empty_valid.
Qed.
Lemma assert_eval_int_typed Γ δ
e x τ
i :
(
e ⇓
inr (
intV{τ
i}
x))%
A ⊆{Γ,δ} (⌜
int_typed x τ
i ⌝ ★
True)%
A.
Proof.
intros Γ' Δ δ' ρ n m ?????? (τlr&?&?).
assert ((Γ',Δ) ⊢ inr (intV{τi} x) : τlr) by eauto using expr_eval_typed.
assert (sep_valid m) by eauto.
typed_inversion_all; exists (∅ : mem K) m; eauto 9 using @sep_left_id, eq_sym.
Qed.
Lemma assert_eval_int_typed' Γ δ
e x τ
i :
(
e ⇓
inr (
intV{τ
i}
x))%
A ⊆{Γ,δ} (⌜
int_typed x τ
i ⌝ ★
e ⇓
inr (
intV{τ
i}
x))%
A.
Proof.
eauto using assert_Prop_True, assert_eval_int_typed. Qed.
Hint Extern 1 (
unop_typed _ _ _) =>
constructor.
Hint Extern 1 (
base_unop_typed _ _ _) =>
constructor.
Lemma assert_eval_int_unop Γ δ
op e x τ
i :
int_unop_ok op x τ
i →
(
e ⇓
inr (
intV{τ
i}
x))%
A
⊆{Γ,δ} (@{
op}
e ⇓
inr (
intV{
int_unop_type_of op τ
i} (
int_unop op x τ
i)))%
A.
Proof.
intros ? Γ' Δ δ' ρ n m ?????? (τlr&?&?).
assert ((Γ',Δ) ⊢ inr (intV{τi} x) : τlr) by eauto using expr_eval_typed.
typed_inversion_all;
simplify_option_equality; eauto 20 using lockset_empty_valid.
Qed.
Lemma assert_eval_int_unop' Γ δ
P op e x y τ
i σ
i :
P ⊆{Γ,δ} (
e ⇓
inr (
intV{τ
i}
x))%
A →
int_unop_type_of op τ
i = σ
i →
int_unop_ok op x τ
i →
int_unop op x τ
i =
y →
P ⊆{Γ,δ} (@{
op}
e ⇓
inr (
intV{σ
i}
y))%
A.
Proof.
intros; subst; rewrite <-assert_eval_int_unop by eauto; eauto. Qed.
Hint Extern 1 (
binop_typed _ _ _ _) =>
constructor.
Hint Extern 1 (
base_binop_typed _ _ _ _) =>
constructor.
Lemma assert_eval_int_binop Γ δ
op e1 e2 x1 x2 τ
i1 τ
i2 :
(
int_binop_ok op x1 τ
i1 x2 τ
i2) →
(
e1 ⇓
inr (
intV{τ
i1}
x1) ∧
e2 ⇓
inr (
intV{τ
i2}
x2))%
A ⊆{Γ,δ} (
e1 @{
op}
e2 ⇓
inr (
intV{
int_binop_type_of op τ
i1 τ
i2} (
int_binop op x1 τ
i1 x2 τ
i2)))%
A.
Proof.
intros Hok Γ' Δ δ' ρ n m ?????? [(τlr1&?&?) (τlr2&?&?)].
assert ((Γ',Δ) ⊢ inr (intV{τi1} x1) : τlr1) by eauto using expr_eval_typed.
assert ((Γ',Δ) ⊢ inr (intV{τi2} x2) : τlr2) by eauto using expr_eval_typed.
typed_inversion_all.
simplify_option_equality; eauto 20 using lockset_empty_valid.
Qed.
Lemma assert_eval_int_binop' Γ δ
P op e1 e2 x1 x2 y τ
i1 τ
i2 σ
i :
P ⊆{Γ,δ} (
e1 ⇓
inr (
intV{τ
i1}
x1))%
A →
P ⊆{Γ,δ} (
e2 ⇓
inr (
intV{τ
i2}
x2))%
A →
σ
i =
int_binop_type_of op τ
i1 τ
i2 →
int_binop_ok op x1 τ
i1 x2 τ
i2 →
int_binop op x1 τ
i1 x2 τ
i2 =
y →
P ⊆{Γ,δ} (
e1 @{
op}
e2 ⇓
inr (
intV{σ
i}
y))%
A.
Proof.
intros; subst;
rewrite <-assert_eval_int_binop by eauto; eauto using assert_and_intro.
Qed.
Lemma assert_eval_int_arithop' Γ δ
P op e1 e2 x1 x2 y τ
i1 τ
i2 σ
i :
P ⊆{Γ,δ} (
e1 ⇓
inr (
intV{τ
i1}
x1))%
A →
P ⊆{Γ,δ} (
e2 ⇓
inr (
intV{τ
i2}
x2))%
A →
σ
i =
int_promote τ
i1 ∪
int_promote τ
i2 →
int_pre_arithop_ok op (
int_pre_cast σ
i x1) (
int_pre_cast σ
i x2) σ
i →
int_pre_arithop op (
int_pre_cast σ
i x1) (
int_pre_cast σ
i x2) σ
i =
y →
P ⊆{Γ,δ} (
e1 @{
ArithOp op}
e2 ⇓
inr (
intV{σ
i}
y))%
A.
Proof.
intros ?? -> ??.
rewrite assert_Prop_True by (rewrite <-(assert_eval_int_typed _ _ e1); auto).
apply assert_Prop_intro_l; intros.
rewrite assert_Prop_True by (rewrite <-(assert_eval_int_typed _ _ e2); auto).
apply assert_Prop_intro_l; intros; eapply assert_eval_int_binop'; eauto.
* by apply int_arithop_ok_more.
* unfold int_binop. by rewrite int_arithop_spec by auto.
Qed.
Hint Extern 1 (
cast_typed _ _) =>
constructor.
Hint Extern 1 (
base_cast_typed _ _) =>
constructor.
Lemma assert_eval_int_cast Γ δ
e x τ
i σ
i :
int_cast_ok σ
i x →
(
e ⇓
inr (
intV{τ
i}
x))%
A
⊆{Γ,δ} (
cast{(
intT σ
i)%
T}
e ⇓
inr (
intV{σ
i} (
int_cast σ
i x)))%
A.
Proof.
intros ? Γ' Δ δ' ρ n m ?????? (τlr&?&?).
assert ((Γ',Δ) ⊢ inr (intV{τi} x) : τlr) by eauto using expr_eval_typed.
typed_inversion_all; simplify_option_equality.
eauto 20 using lockset_empty_valid, TBase_valid, TInt_valid.
Qed.
Lemma assert_eval_int_cast' Γ δ
P e x τ
i σ
i y :
P ⊆{Γ,δ} (
e ⇓
inr (
intV{τ
i}
x))%
A →
int_cast_ok σ
i x →
int_cast σ
i x =
y →
P ⊆{Γ,δ} (
cast{(
intT σ
i)%
T}
e ⇓
inr (
intV{σ
i}
y))%
A.
Proof.
intros; subst; rewrite <-assert_eval_int_cast by eauto; eauto. Qed.
Lemma assert_eval_int_cast_self' Γ δ
P e x τ
i :
P ⊆{Γ,δ} (
e ⇓
inr (
intV{τ
i}
x))%
A →
P ⊆{Γ,δ} (
cast{(
intT τ
i)%
T}
e ⇓
inr (
intV{τ
i}
x))%
A.
Proof.
intros HP. rewrite HP, assert_eval_int_typed'.
eauto using assert_Prop_intro_l,
assert_eval_int_cast', int_cast_ok_self, int_cast_self.
Qed.
Lemma assert_eval_singleton_l Γ δ
a e μ γ τ :
(%
a ↦{μ,γ}
e : τ)%
A ⊆{Γ,δ} (%
a ⇓
inl a)%
A.
Proof.
intros Γ' Δ δ' ρ n m ?????? (a'&v&?&?&?&?&?);
eexists (inl (TType τ)); simplify_option_equality; eauto.
Qed.
Lemma assert_eval_singleton_r Γ δ
e v μ γ τ :
(
e ↦{μ,γ} #
v : τ)%
A ⊆{Γ,δ} (#
v ⇓
inr v)%
A.
Proof.
intros Γ' Δ δ' ρ n m ?????? (a&v'&?&?&?&?&?);
eexists (inr τ); simplify_option_equality; eauto.
Qed.
Lemma assert_singleton_l Γ δ
e1 e2 μ γ τ :
(
e1 ↦{μ,γ}
e2 : τ)%
A ≡{Γ,δ} (∃
a, (
e1 ⇓
inl a ∧
emp) ★ %
a ↦{μ,γ}
e2 : τ)%
A.
Proof.
split.
* intros Γ' Δ δ' ρ n m ?????? (a&v&?&?&?&?&?); exists (Ptr a).
assert (sep_valid m) by eauto using cmap_valid_sep_valid.
eexists ∅, m; split_ands; simplify_option_equality; eauto 20 using
@sep_left_id, eq_sym, lockset_empty_valid, mem_singleton_typed_addr_typed.
* intros Γ' Δ δ' ρ n m_ ???? Hm ?
(?&?&m&->&?&((τlr&?&?)&_&->)&(a&v&?&?&?&?&?)); simplify_option_equality.
exists a v; rewrite sep_left_id in Hm |- * by auto; split_ands; auto.
cut (τlr = inl (TType τ)); [intros ->; auto|typed_inversion_all].
apply (typed_unique (Γ',Δ) (inl (Ptr a)));
eauto using expr_eval_typed, cmap_empty_valid, cmap_valid_memenv_valid.
Qed.
Lemma assert_singleton_l_2 Γ δ
e1 e2 μ γ
a τ :
((
e1 ⇓
inl a ∧
emp) ★ %
a ↦{μ,γ}
e2 : τ)%
A ⊆{Γ,δ} (
e1 ↦{μ,γ}
e2 : τ)%
A.
Proof.
rewrite (assert_singleton_l _ _ e1); solve eauto. Qed.
Lemma assert_singleton_l_ Γ δ
e μ γ τ :
(
e ↦{μ,γ} - : τ)%
A ≡{Γ,δ} (∃
a, (
e ⇓
inl a ∧
emp) ★ %
a ↦{μ,γ} - : τ)%
A.
Proof.
setoid_rewrite (assert_singleton_l Γ δ e).
by setoid_rewrite (assert_sep_exist Γ δ); rewrite assert_exist_exist.
Qed.
Lemma assert_singleton_l_2_ Γ δ
e μ γ
a τ :
((
e ⇓
inl a ∧
emp) ★ %
a ↦{μ,γ} - : τ)%
A ⊆{Γ,δ} (
e ↦{μ,γ} - : τ)%
A.
Proof.
rewrite (assert_singleton_l_ _ _ e); solve eauto. Qed.
Lemma assert_singleton_int_typed Γ δ
e μ γ
z τ
i :
(
e ↦{μ,γ} #
intV{τ
i}
z :
intT τ
i)%
A ⊆{Γ,δ} (⌜
int_typed z τ
i ⌝ ★
True)%
A.
Proof.
rewrite assert_eval_singleton_r; apply assert_eval_int_typed. Qed.
Lemma assert_singleton_int_typed' Γ δ
e μ γ
z τ
i :
(
e ↦{μ,γ} #
intV{τ
i}
z :
intT τ
i)%
A
⊆{Γ,δ} (⌜
int_typed z τ
i ⌝ ★ (
e ↦{μ,γ} #
intV{τ
i}
z :
intT τ
i))%
A.
Proof.
by apply assert_Prop_True, assert_singleton_int_typed. Qed.
Lemma assert_expr_lift Γ δ
e ν :
vars e = ∅ → (
e↑ ⇓ ν)%
A ≡{Γ,δ} (
e ⇓ ν)%
A.
Proof.
split; intros Γ' Δ δ' ρ n m ?????? (τlr&?&?); exists τlr; split.
* by apply expr_typed_var_free with (tail (ρ.*2)), expr_typed_lift.
* erewrite expr_eval_var_free, <-expr_eval_lift; eauto.
* eapply expr_typed_lift, expr_typed_var_free; eauto.
* erewrite expr_eval_lift, <-expr_eval_var_free by done; eauto.
Qed.
Lemma assert_singleton_lift_l Γ δ
e1 e2 μ γ τ :
vars e1 = ∅ → (
e1↑ ↦{μ,γ}
e2 : τ)%
A ≡{Γ,δ} (
e1 ↦{μ,γ}
e2 : τ)%
A.
Proof.
split; intros Γ' Δ δ' ρ n m ?????? (a&v&?&?&?&?&?);
exists a v; split_ands; auto.
* by apply expr_typed_var_free with (tail (ρ.*2)), expr_typed_lift.
* erewrite expr_eval_var_free, <-expr_eval_lift; eauto.
* eapply expr_typed_lift, expr_typed_var_free; eauto.
* erewrite expr_eval_lift, <-expr_eval_var_free by done; eauto.
Qed.
Lemma assert_singleton_lift_r Γ δ
e1 e2 μ γ τ :
vars e2 = ∅ → (
e1 ↦{μ,γ} (
e2↑) : τ)%
A ≡{Γ,δ} (
e1 ↦{μ,γ}
e2 : τ)%
A.
Proof.
split; intros Γ' Δ δ' ρ n m ?????? (a&v&?&?&?&?&?);
exists a v; split_ands; auto.
* by apply expr_typed_var_free with (tail (ρ.*2)), expr_typed_lift.
* erewrite expr_eval_var_free, <-expr_eval_lift; eauto.
* eapply expr_typed_lift, expr_typed_var_free; eauto.
* erewrite expr_eval_lift, <-expr_eval_var_free by done; eauto.
Qed.
Lemma assert_singleton_eval Γ δ
e v μ γ τ :
Some Readable ⊆
perm_kind γ → (
e ↦{μ,γ} #
v : τ)%
A ⊆{Γ,δ} (
load e ⇓
inr v)%
A.
Proof.
intros ? Γ1 Δ δ' ρ n ??????? (a&v'&?&?&?&?&?); simplify_option_equality.
assert (✓{Γ1} Δ) by eauto using cmap_valid_memenv_valid.
eexists (inr τ); split_ands; eauto using mem_singleton_typed_addr_typed,
addr_typed_type_valid, type_valid_complete.
erewrite (expr_eval_weaken _ _ _ _ _ ∅) by eauto using cmap_empty_valid,
cmap_subseteq_index_alive, mem_lookup_subseteq, mem_forced_subseteq,
@sep_subseteq_empty; simpl.
by erewrite option_guard_True, mem_lookup_singleton
by eauto using mem_singleton_forced.
Qed.
Lemma assert_singleton_union_lr Γ δ
e1 e2 μ γ1 γ2 τ :
⊥[γ1;γ2] → ¬
sep_unmapped γ1 → ¬
sep_unmapped γ2 →
(
e1 ↦{μ,γ1 ∪ γ2}
e2 : τ)%
A ≡{Γ,δ} (
e1 ↦{μ,γ1}
e2 : τ ★
e1 ↦{μ,γ2}
e2 : τ)%
A.
Proof.
intros; split.
* intros Γ1 Δ δ' ρ n ??????? (a&v&?&?&?&?&?).
destruct (mem_singleton_union_rev Γ1 Δ m a μ γ1 γ2 v τ)
as (m1&m2&->&?&?&?); auto.
exists m1 m2; split_ands; solve ltac:eauto.
* intros Γ1 Δ δ' ρ n ??????? (?&?&->&?&(a1&v1&?&?&?&?&?)&(a2&v2&?&?&?&?&?));
simplify_equality'; exists a1 v1; eauto 10 using mem_singleton_union.
Qed.
Lemma assert_singleton_union_l Γ δ
e1 e2 μ γ1 γ2 τ :
⊥[γ1;γ2] → ¬
sep_unmapped γ1 → γ2 ≠ ∅ →
(
e1 ↦{μ,γ1 ∪ γ2}
e2 : τ)%
A ≡{Γ,δ} (
e1 ↦{μ,γ1}
e2 : τ ★
e1 ↦{μ,γ2} - : τ)%
A.
Proof.
intros; split.
* intros Γ1 Δ1 δ1 ρ n ??????? (a&v&?&?&?&?&?).
destruct (decide (sep_unmapped γ2)).
+ destruct (mem_singleton_union_rev_unmapped Γ1 Δ1 m a μ γ1 γ2 v τ)
as (m1&m2&->&?&?&?); auto using @sep_unmapped_empty_alt.
assert ((Γ1,Δ1) ⊢ val_new Γ1 τ : τ).
{ eauto using val_new_typed,
mem_singleton_typed_addr_typed, addr_typed_type_valid. }
exists m1 m2; simplify_option_equality;
eauto 20 using lockset_empty_valid.
+ destruct (mem_singleton_union_rev Γ1 Δ1 m a μ γ1 γ2 v τ)
as (m1&m2&->&?&?&?); auto.
exists m1 m2; solve ltac:(eauto using expr_eval_typed,
lockset_empty_valid, cmap_empty_valid, cmap_valid_memenv_valid).
* intros Γ1 Δ1 δ1 ρ n ???????
(?&?&->&?&(a1&v1&?&?&?&?&?)&(?&a2&v2&?&?&?&?&?));
simplify_option_equality; exists a1 v1; split_ands; auto.
by eapply (mem_singleton_union _ _ _ _ _ _ _ _ v1 v2); eauto.
Qed.
Lemma assert_singleton_union_r Γ δ
e1 e2 μ γ1 γ2 τ :
⊥[γ1;γ2] → γ1 ≠ ∅ → ¬
sep_unmapped γ2 →
(
e1 ↦{μ,γ1 ∪ γ2}
e2 : τ)%
A ≡{Γ,δ} (
e1 ↦{μ,γ1} - : τ ★
e1 ↦{μ,γ2}
e2 : τ)%
A.
Proof.
intros. rewrite (commutative (★)%A), sep_commutative by auto.
by rewrite assert_singleton_union_l by auto.
Qed.
Lemma assert_singleton_union Γ δ
e1 μ γ1 γ2 τ :
⊥[γ1;γ2] → γ1 ≠ ∅ → γ2 ≠ ∅ →
(
e1 ↦{μ,γ1 ∪ γ2} - : τ)%
A ≡{Γ,δ} (
e1 ↦{μ,γ1} - : τ ★
e1 ↦{μ,γ2} - : τ)%
A.
Proof.
intros; split.
* intros Γ1 Δ δ1 ρ n ??????? (?&a&v&?&?&?&?&?); simplify_option_equality;
typed_inversion_all; destruct (decide (sep_unmapped γ2)).
{ destruct (mem_singleton_union_rev_unmapped Γ1 Δ m a μ γ1 γ2 v τ)
as (m1&m2&->&?&?&?); auto using @sep_unmapped_empty_alt.
assert ((Γ1,Δ) ⊢ val_new Γ1 τ : τ).
{ eauto using val_new_typed,
mem_singleton_typed_addr_typed, addr_typed_type_valid. }
exists m1 m2; split_ands; eauto 10 using lockset_empty_valid. }
destruct (decide (sep_unmapped γ1)).
{ destruct (mem_singleton_union_rev_unmapped Γ1 Δ m a μ γ2 γ1 v τ)
as (m1&m2&->&?&?&?); auto using @sep_unmapped_empty_alt.
{ by rewrite sep_commutative by auto. }
assert ((Γ1,Δ) ⊢ val_new Γ1 τ : τ).
{ eauto using val_new_typed,
mem_singleton_typed_addr_typed, addr_typed_type_valid. }
exists m2 m1; eauto 30 using @sep_commutative. }
destruct (mem_singleton_union_rev Γ1 Δ m a μ γ1 γ2 v τ)
as (m1&m2&->&?&?&?); eauto 40.
* intros Γ1 Δ δ1 ρ n ???????
(?&?&->&?&(?&a1&v1&?&?&?&?&?)&(?&a2&v2&?&?&?&?&?));
simplify_option_equality; destruct (decide (sep_unmapped γ1)).
+ eexists v2, a1, v2; split_ands; eauto.
by eapply (mem_singleton_union _ _ _ _ _ _ _ _ v1 v2); eauto.
+ eexists v1, a1, v1; split_ands; eauto.
by eapply (mem_singleton_union _ _ _ _ _ _ _ _ v1 v2); eauto.
Qed.
Lemma assert_singleton_array Γ δ
e μ γ
vs τ
n :
length vs =
n →
n ≠ 0 →
(
e ↦{μ,γ} #(
VArray τ
vs) : (τ.[
n]))%
A
≡{Γ,δ} (Π
imap (λ
i v, (
e %>
RArray i τ
n) ↦{μ,γ} #
v : τ)
vs)%
A.
Proof.
intros Hn Hn'. split.
* intros Γ1 Δ δ1 ρ n' ????? Hm ? (a&v&?&?&_&Hvs&w&->&->&Hw&Hw'&Ha&_&?&?).
apply cmap_valid_memenv_valid in Hm; clear Hn Hn'.
assert (∃ ws, w = MArray τ ws ∧ length ws = n ∧
vs = to_val Γ1 <$> ws ∧ (Γ1,Δ) ⊢* ws : τ) as (ws&->&Hn&->&Hws).
{ destruct w; simplify_option_equality; typed_inversion_all; eauto. }
assert (Forall (not ∘ Forall (∅ =) ∘ ctree_flatten) ws) as Hemp.
{ clear Hn Hw Hvs.
induction Hws as [|w ws]; constructor; decompose_Forall_hyps; eauto.
eapply ctree_Forall_not, Forall_impl; naive_solver. }
erewrite cmap_singleton_array_union by eauto.
apply assert_Forall_holds_2; eauto using cmap_singleton_array_disjoint.
cut (0 + length ws ≤ n); [|lia]; unfold imap; generalize 0 as j.
clear Hemp Hn Hvs Hw; induction Hws as [|w ws]; intros j ?;
decompose_Forall_hyps; constructor; eauto with lia.
exists (addr_elt Γ1 (RArray j τ n) a) (to_val Γ1 w); split_ands; eauto.
+ by simplify_option_equality.
+ typed_constructor; eauto using to_val_typed, lockset_empty_valid.
+ exists w; eauto 12 using addr_elt_is_obj, addr_elt_strict, addr_elt_typed.
* intros Γ1 Δ δ1 ρ n' m _ ??? Hm ?.
rewrite assert_Forall_holds; intros (ms&->&_&Hms).
apply cmap_valid_memenv_valid in Hm.
assert (∃ a, (Γ1,Δ,ρ.*2) ⊢ e : inl (TType (τ.[n]))%T ∧
⟦ e ⟧ Γ1 ρ ∅ = Some (inl (Ptr a)) ∧ addr_strict Γ1 a ∧
γ ≠ ∅) as (a&He&?&?&?).
{ unfold imap in *; destruct vs; decompose_Forall_hyps.
match goal with
| H : ∃ a, _ |- _ => destruct H as (?&?&?&?&_&_&?&_&_&_&_&_&_&_&?)
end; simplify_option_equality; typed_inversion_all; eauto. }
assert (∃ ws,
ms = imap (λ i, cmap_singleton Γ1 (addr_elt Γ1 (RArray i τ n) a) μ) ws ∧
vs = to_val Γ1 <$> ws ∧ (Γ1,Δ) ⊢* ws : τ ∧
Forall (λ γb, tagged_perm γb = γ) (ws ≫= ctree_flatten))
as (ws&->&->&Hws&Hws').
{ cut (0 + length vs ≤ n); [|lia]; unfold imap in *.
clear Hn Hn' He; revert Hms; generalize 0 as j; revert vs.
induction ms as [|m ms IH]; intros [|v vs] j ??; decompose_Forall_hyps.
{ eexists []; simpl; eauto. }
match goal with
| H : ∃ a, _ |- _ => destruct H as (?&?&_&?&_&?&w&->&->&Hw&?&_)
end; simplify_option_equality.
destruct (IH vs (S j)) as (ws&->&->&?&?); clear IH; auto with lia.
exists (w :: ws); split_ands; csimpl; eauto using Forall_app_2. }
assert (Forall (not ∘ Forall (∅ =) ∘ ctree_flatten) ws) as Hemp.
{ clear Hn Hms.
induction Hws as [|w ws]; constructor; decompose_Forall_hyps; eauto.
eapply ctree_Forall_not, Forall_impl; naive_solver. }
assert ((Γ1,Δ) ⊢* to_val Γ1 <$> ws : τ).
{ eapply Forall_fmap; eauto using Forall_impl, to_val_typed. }
assert ((Γ1,Δ) ⊢ a : TType (τ.[n])) by eauto 10
using lval_typed_inv, Ptr_typed_inv, expr_eval_typed, cmap_empty_valid.
exists a (VArray τ (to_val Γ1 <$> ws));
split_ands; eauto using lockset_empty_valid.
rewrite fmap_length in Hn.
erewrite <-cmap_singleton_array_union by eauto.
exists (MArray τ ws); eauto 10 using lval_typed_inv, expr_eval_typed,
cmap_empty_valid, (addr_ref_byte_is_obj_parent _ _ (RArray 0 τ n)).
Qed.
Global Instance:
Proper ((⊆{Γ,δ}) ==> (⊆{Γ,δ}))
assert_lift.
Proof.
solve ltac:(eauto using Forall_tail). Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}))
assert_lift.
Proof.
solve ltac:(eauto using Forall_tail). Qed.
Lemma assert_lift_impl Γ δ
P Q : ((
P →
Q)↑)%
A ≡{Γ,δ} (
P↑ →
Q↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_and Γ δ
P Q : ((
P ∧
Q)↑)%
A ≡{Γ,δ} (
P↑ ∧
Q↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_or Γ δ
P Q : ((
P ∨
Q)↑)%
A ≡{Γ,δ} (
P↑ ∨
Q↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_not Γ δ
P : ((¬
P)↑)%
A ≡{Γ,δ} (¬
P↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_forall Γ δ {
A} (
P :
A →
assert K) :
((∀
x,
P x)↑)%
A ≡{Γ,δ} (∀
x,
P x↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_exists Γ δ {
A} (
P :
A →
assert K) :
((∃
x,
P x)↑)%
A ≡{Γ,δ} (∃
x,
P x↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_sep Γ δ
P Q : ((
P ★
Q)↑)%
A ≡{Γ,δ} (
P↑ ★
Q↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_wand Γ δ
P Q : ((
P -★
Q)↑)%
A ≡{Γ,δ} (
P↑ -★
Q↑)%
A.
Proof.
solve eauto. Qed.
Lemma assert_lift_expr Γ δ
e v : ((
e ⇓
v)↑)%
A ≡{Γ,δ} (
e↑ ⇓
v)%
A.
Proof.
split.
* intros Γ' Δ δ' ρ n m ?????? (τlr&?&?); exists τlr.
by rewrite expr_eval_lift, expr_typed_lift, <-fmap_tail.
* intros Γ' Δ δ' ρ n m ?????? (τlr&?&?); exists τlr.
by rewrite fmap_tail, <-expr_eval_lift, <-expr_typed_lift.
Qed.
Lemma assert_lift_expr_ Γ δ
e : ((
e ⇓ -)↑)%
A ≡{Γ,δ} (
e↑ ⇓ -)%
A.
Proof.
by rewrite assert_lift_exists; setoid_rewrite (assert_lift_expr Γ δ).
Qed.
Lemma assert_lift_singleton Γ δ
e1 e2 μ γ τ :
((
e1 ↦{μ,γ}
e2 : τ)↑)%
A ≡{Γ,δ} ((
e1↑) ↦{μ,γ} (
e2↑) : τ)%
A.
Proof.
split; repeat intro.
* do 2 red. by setoid_rewrite expr_eval_lift;
setoid_rewrite expr_typed_lift; rewrite <-fmap_tail.
* do 4 red. by rewrite fmap_tail; setoid_rewrite <-expr_eval_lift;
setoid_rewrite <-expr_typed_lift.
Qed.
Lemma assert_lift_singleton_ Γ δ
e1 μ γ τ :
((
e1 ↦{μ,γ} - : τ)↑)%
A ≡{Γ,δ} ((
e1↑) ↦{μ,γ} - : τ)%
A.
Proof.
by rewrite assert_lift_exists; setoid_rewrite (assert_lift_singleton Γ δ).
Qed.
Global Instance assert_lift_stack_indep:
StackIndep P →
StackIndep (
P↑).
Proof.
intros P ? Γ δ; by rewrite !stack_indep. Qed.
Global Instance assert_True_stack_indep :
StackIndep True.
Proof.
solve eauto. Qed.
Global Instance assert_False_stack_indep :
StackIndep False.
Proof.
solve eauto. Qed.
Global Instance assert_Prop_stack_indep P :
StackIndep (⌜
P ⌝).
Proof.
solve eauto. Qed.
Global Instance assert_impl_stack_indep :
StackIndep P →
StackIndep Q →
StackIndep (
P →
Q).
Proof.
by intros P Q ?? Γ δ; rewrite assert_lift_impl, !stack_indep. Qed.
Global Instance assert_and_stack_indep :
StackIndep P →
StackIndep Q →
StackIndep (
P ∧
Q).
Proof.
solve eauto. Qed.
Global Instance assert_or_stack_indep :
StackIndep P →
StackIndep Q →
StackIndep (
P ∨
Q).
Proof.
solve eauto. Qed.
Global Instance assert_forall_stack_indep A :
(∀
x :
A,
StackIndep (
P x)) →
StackIndep (
assert_forall P).
Proof.
solve eauto. Qed.
Global Instance assert_exist_stack_indep A :
(∀
x :
A,
StackIndep (
P x)) →
StackIndep (
assert_exist P).
Proof.
solve eauto. Qed.
Global Instance assert_sep_stack_indep :
StackIndep P →
StackIndep Q →
StackIndep (
P ★
Q).
Proof.
by intros P Q HP HQ Γ δ; rewrite assert_lift_sep, !stack_indep. Qed.
Global Instance assert_wand_stack_indep :
StackIndep P →
StackIndep Q →
StackIndep (
P -★
Q).
Proof.
by intros P Q ?? Γ δ; rewrite assert_lift_wand, !stack_indep. Qed.
Global Instance assert_expr_stack_indep e v :
vars e = ∅ →
StackIndep (
e ⇓
v).
Proof.
intros ? Γ δ. by rewrite assert_lift_expr, assert_expr_lift. Qed.
Global Instance assert_singleton_stack_indep e1 e2 μ γ τ :
vars e1 = ∅ →
vars e2 = ∅ →
StackIndep (
e1 ↦{μ,γ}
e2 : τ).
Proof.
by intros ?? Γ δ; rewrite assert_lift_singleton,
assert_singleton_lift_l, assert_singleton_lift_r by done.
Qed.
Lemma stack_indep_spec P Γ Δ δ ρ1 ρ2
n m :
StackIndep P → ✓ Γ → ✓{Γ,Δ} δ → ✓{Γ,Δ}
m → ✓{Δ}* ρ1 → ✓{Δ}* ρ2 →
assert_holds P Γ Δ δ ρ1
n m →
assert_holds P Γ Δ δ ρ2
n m.
Proof.
intros HP ??? Hρ1 Hρ2 ?; assert (assert_holds P Γ Δ δ [] n m).
* induction Hρ1 as [|[o τ] ρ ?? IH]; auto.
eapply IH, (proj2 (HP _ _) Γ Δ δ (_ :: _)); simpl; eauto.
* induction Hρ2 as [|[o τ] ρ ?? IH]; auto.
eapply (proj1 (HP _ _)), IH; simpl; eauto.
Qed.
Lemma assert_unlock_spec P Γ Δ δ ρ
n m :
assert_holds (
P ◊) Γ Δ δ ρ
n m =
assert_holds P Γ Δ δ ρ
n (
mem_unlock_all m).
Proof.
done. Qed.
Global Instance:
Proper ((⊆{Γ,δ}) ==> (⊆{Γ,δ}))
assert_unlock.
Proof.
solve ltac:(eauto using mem_unlock_all_valid). Qed.
Global Instance:
Proper ((≡{Γ,δ}) ==> (≡{Γ,δ}))
assert_unlock.
Proof.
solve ltac:(eauto using mem_unlock_all_valid). Qed.
Lemma assert_unlock_unlock Γ δ
P : (
P ◊ ◊)%
A ≡{Γ,δ} (
P ◊)%
A.
Proof.
split; intros Γ' Δ ρ m ????; simpl;
by rewrite (mem_unlock_all_spec (mem_unlock_all _)),
!mem_locks_unlock_all, mem_unlock_empty.
Qed.
Lemma assert_unlock_impl Γ δ
P Q : ((
P →
Q) ◊)%
A ≡{Γ,δ} (
P ◊ →
Q ◊)%
A.
Proof.
split; [solve ltac:(eauto using mem_unlock_all_valid)|].
solve ltac:(eauto using cmap_valid_weaken_squeeze, mem_unlock_memenv_of).
Qed.
Lemma assert_unlock_and Γ δ
P Q : ((
P ∧
Q) ◊)%
A ≡{Γ,δ} (
P ◊ ∧
Q ◊)%
A.
Proof.
solve eauto. Qed.
Lemma assert_unlock_or Γ δ
P Q : ((
P ∨
Q) ◊)%
A ≡{Γ,δ} (
P ◊ ∨
Q ◊)%
A.
Proof.
solve eauto. Qed.
Lemma assert_unlock_forall Γ δ {
A} (
P :
A →
assert K) :
((∀
x,
P x) ◊)%
A ≡{Γ,δ} (∀
x, (
P x) ◊)%
A.
Proof.
solve eauto. Qed.
Lemma assert_unlock_exists Γ δ {
A} (
P :
A →
assert K) :
((∃
x,
P x) ◊)%
A ≡{Γ,δ} (∃
x, (
P x) ◊)%
A.
Proof.
solve eauto. Qed.
Lemma assert_unlock_sep Γ δ
P Q : (
P ◊ ★
Q ◊)%
A ⊆{Γ,δ} ((
P ★
Q) ◊)%
A.
Proof.
intros Γ1 Δ δ1 ρ n m ?????? (m1&m2&->&?&?&?).
exists (mem_unlock_all m1) (mem_unlock_all m2); split_ands; auto.
* by rewrite mem_unlock_all_union by solve_sep_disjoint.
* by rewrite <-!mem_unlock_all_disjoint_le.
Qed.
Lemma assert_unlock_sep_alt Γ δ
P P'
Q Q' :
P ⊆{Γ,δ} (
P' ◊)%
A →
Q ⊆{Γ,δ} (
Q' ◊)%
A → (
P ★
Q)%
A ⊆{Γ,δ} ((
P' ★
Q') ◊)%
A.
Proof.
intros HP HQ. by rewrite HP, HQ, assert_unlock_sep. Qed.
Lemma assert_unlock_singleton Γ δ
e1 e2 μ γ τ :
perm_locked γ =
true →
(
e1 ↦{μ,γ}
e2 : τ)%
A ⊆{Γ,δ} ((
e1 ↦{μ,
perm_unlock γ}
e2 : τ) ◊)%
A.
Proof.
intros ? Γ1 Δ δ1 ρ n m ?????? (a&v&?&?&?&?&?).
exists a v; split_ands; eauto using mem_unlock_all_singleton.
Qed.
Lemma assert_unlock_singleton_ Γ δ
e1 μ γ τ :
perm_locked γ =
true →
(
e1 ↦{μ,γ} - : τ)%
A ⊆{Γ,δ} ((
e1 ↦{μ,
perm_unlock γ} - : τ) ◊)%
A.
Proof.
intros Hγ. rewrite assert_unlock_exists.
by setoid_rewrite (λ e2, assert_unlock_singleton Γ δ e1 e2 μ γ τ Hγ).
Qed.
Lemma assert_lock_singleton Γ δ
e1 e2 μ γ τ :
sep_valid γ →
Some Writable ⊆
perm_kind γ →
(
e1 ↦{μ,
perm_lock γ}
e2 : τ)%
A ⊆{Γ,δ} ((
e1 ↦{μ,γ}
e2 : τ) ◊)%
A.
Proof.
intros. by rewrite assert_unlock_singleton,
perm_unlock_lock by auto using perm_locked_lock.
Qed.
Lemma assert_lock_singleton_ Γ δ
e1 μ γ τ :
sep_valid γ →
Some Writable ⊆
perm_kind γ →
(
e1 ↦{μ,
perm_lock γ} - : τ)%
A ⊆{Γ,δ} ((
e1 ↦{μ,γ} - : τ) ◊)%
A.
Proof.
intros. by rewrite assert_unlock_singleton_,
perm_unlock_lock by auto using perm_locked_lock.
Qed.
Global Instance assert_unlock_unlock_indep P :
UnlockIndep (
P ◊).
Proof.
intros Γ δ. by rewrite assert_unlock_unlock. Qed.
Global Instance assert_True_unlock_indep :
UnlockIndep True.
Proof.
solve ltac:(eauto using mem_unlock_all_empty). Qed.
Global Instance assert_False_unlock_indep :
UnlockIndep False.
Proof.
solve ltac:(eauto using mem_unlock_all_empty). Qed.
Global Instance assert_Prop_unlock_indep :
UnlockIndep ⌜
P ⌝.
Proof.
solve ltac:(eauto using mem_unlock_all_empty). Qed.
Global Instance assert_and_unlock_indep :
UnlockIndep P →
UnlockIndep Q →
UnlockIndep (
P ∧
Q).
Proof.
solve eauto. Qed.
Global Instance assert_or_unlock_indep :
UnlockIndep P →
UnlockIndep Q →
UnlockIndep (
P ∨
Q).
Proof.
solve eauto. Qed.
Global Instance assert_forall_unlock_indep A :
(∀
x :
A,
UnlockIndep (
P x)) →
UnlockIndep (
assert_forall P).
Proof.
solve eauto. Qed.
Global Instance assert_exist_unlock_indep A :
(∀
x :
A,
UnlockIndep (
P x)) →
UnlockIndep (
assert_exist P).
Proof.
solve eauto. Qed.
Global Instance assert_lift_unlock_indep :
UnlockIndep P →
UnlockIndep (
P↑).
Proof.
solve ltac:(eauto using Forall_tail). Qed.
Global Instance assert_sep_unlock_indep P Q :
UnlockIndep P →
UnlockIndep Q →
UnlockIndep (
P ★
Q).
Proof.
intros ?? [Γ δ]; auto using assert_unlock_sep_alt. Qed.
Global Instance assert_singleton_unlock_indep e1 e2 μ γ τ :
perm_locked γ =
false →
UnlockIndep (
e1 ↦{μ,γ}
e2 : τ).
Proof.
intros ? Γ δ Γ' Δ δ' ρ n m ?????? (a&v&?&?&?&?&?).
exists a v; split_ands; eauto using mem_unlock_all_singleton_unlocked.
Qed.
End assertions.