Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Gaurav Parthasarathy
examples_rdcss_old
Commits
ec2684b0
Commit
ec2684b0
authored
Oct 05, 2016
by
Zhen Zhang
Browse files
parameric on P Q
parent
f9c76a58
Changes
2
Hide whitespace changes
Inline
Side-by-side
flat.v
View file @
ec2684b0
From
iris
.
program_logic
Require
Export
auth
weakestpre
.
From
iris
.
program_logic
Require
Export
auth
weakestpre
saved_prop
.
From
iris
.
proofmode
Require
Import
invariants
ghost_ownership
.
From
iris
.
heap_lang
Require
Export
lang
.
From
iris
.
heap_lang
Require
Import
proofmode
notation
.
...
...
@@ -45,84 +45,88 @@ Definition install : val :=
"p"
.
Definition
mk_flat
:
val
:
=
λ
:
<>
,
λ
:
"f"
,
let
:
"lk"
:
=
newlock
#()
in
let
:
"s"
:
=
new_stack
#()
in
λ
:
"f"
,
λ
:
"x"
,
let
:
"p"
:
=
install
"x"
"s"
in
loop
"f"
"p"
"s"
"lk"
.
λ
:
"x"
,
let
:
"p"
:
=
install
"x"
"s"
in
loop
"f"
"p"
"s"
"lk"
.
Global
Opaque
doOp
try_srv
install
loop
mk_flat
.
Definition
reqR
:
=
prodR
fracR
(
dec_agreeR
val
).
(* request x should be kept same *)
Definition
toks
:
Type
:
=
gname
*
gname
*
gname
*
gname
.
(* a bunch of tokens to do state transition *)
Definition
toks
:
Type
:
=
gname
*
gname
*
gname
*
gname
*
gname
.
(* a bunch of tokens to do state transition *)
Definition
tokmR
:
=
evmapR
loc
toks
.
(* tie each slot to tokens *)
Definition
reqmR
:
=
evmapR
loc
val
.
(* tie each slot to request value *)
Class
flatG
Σ
:
=
FlatG
{
req_G
:
>
inG
Σ
reqR
;
tok_G
:
>
inG
Σ
(
authR
tokmR
)
;
sp_G
:
>
savedPropG
Σ
(
cofe_funCF
val
idCF
)
}.
Definition
flat
Σ
:
gFunctors
:
=
#[
GFunctor
(
constRF
reqR
)
;
GFunctor
(
constRF
(
authR
tokmR
))
GFunctor
(
constRF
(
authR
tokmR
))
;
savedProp
Σ
(
cofe_funCF
val
idCF
)
].
Instance
subG_flat
Σ
{
Σ
}
:
subG
flat
Σ
Σ
→
flatG
Σ
.
Proof
.
intros
[?%
subG_inG
[?%
subG_inG
_
]%
subG_inv
]%
subG_inv
.
split
;
apply
_
.
Qed
.
Proof
.
intros
[?%
subG_inG
[?%
subG_inG
[?
_
]%
subG_inv
]%
subG_inv
]%
subG_inv
.
split
;
apply
_
.
Qed
.
Section
proof
.
Context
`
{!
heapG
Σ
,
!
lockG
Σ
,
!
evidenceG
loc
val
Σ
,
!
flatG
Σ
}
(
N
:
namespace
).
Context
(
R
:
iProp
Σ
)
(* private resource *)
(
P
:
val
→
iProp
Σ
)
(* common pre-cond *)
(
Q
:
val
→
val
→
iProp
Σ
)
(* common post-cond *)
`
{
∀
x
,
TimelessP
(
P
x
),
∀
x
y
,
TimelessP
(
Q
x
y
)}.
Context
(
R
:
iProp
Σ
).
Definition
init_s
(
ts
:
toks
)
:
=
let
'
(
_
,
γ
1
,
γ
3
,
_
,
_
)
:
=
ts
in
(
own
γ
1
(
Excl
())
★
own
γ
3
(
Excl
()))%
I
.
Definition
installed_s
(
ts
:
toks
)
(
f
x
:
val
)
:
=
let
'
(
γ
x
,
γ
1
,
_
,
γ
4
,
γ
q
)
:
=
ts
in
(
∃
(
P
:
val
→
iProp
Σ
)
Q
,
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
P
x
★
({{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
★
saved_prop_own
γ
q
(
Q
x
)
★
own
γ
1
(
Excl
())
★
own
γ
4
(
Excl
()))%
I
.
Definition
init_s
(
ts
:
toks
)
:
=
let
'
(
_
,
γ
1
,
γ
3
,
_
)
:
=
ts
in
(
own
γ
1
(
Excl
())
★
own
γ
3
(
Excl
()))%
I
.
Definition
installed_s
(
ts
:
toks
)
(
x
:
val
)
:
=
let
'
(
γ
x
,
γ
1
,
_
,
γ
4
)
:
=
ts
in
(
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
P
x
★
own
γ
1
(
Excl
())
★
own
γ
4
(
Excl
()))%
I
.
Definition
received_s
(
ts
:
toks
)
(
x
:
val
)
γ
r
:
=
let
'
(
γ
x
,
_
,
_
,
γ
4
)
:
=
ts
in
(
own
γ
x
((
1
/
2
/
2
)%
Qp
,
DecAgree
x
)
★
own
γ
r
(
Excl
())
★
own
γ
4
(
Excl
()))%
I
.
let
'
(
γ
x
,
_
,
_
,
γ
4
,
_
)
:
=
ts
in
(
own
γ
x
((
1
/
2
/
2
)%
Qp
,
DecAgree
x
)
★
own
γ
r
(
Excl
())
★
own
γ
4
(
Excl
()))%
I
.
Definition
finished_s
(
ts
:
toks
)
(
x
y
:
val
)
:
=
let
'
(
γ
x
,
γ
1
,
_
,
γ
4
)
:
=
ts
in
(
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
Q
x
y
★
own
γ
1
(
Excl
())
★
own
γ
4
(
Excl
()))%
I
.
let
'
(
γ
x
,
γ
1
,
_
,
γ
4
,
γ
q
)
:
=
ts
in
(
∃
Q
:
val
→
val
→
iProp
Σ
,
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
saved_prop_own
γ
q
(
Q
x
)
★
Q
x
y
★
own
γ
1
(
Excl
())
★
own
γ
4
(
Excl
()))%
I
.
Definition
evm
:
=
ev
loc
toks
.
(* p slot invariant *)
Definition
p_inv
(
γ
m
γ
r
:
gname
)
(
v
:
val
)
:
=
Definition
p_inv
(
γ
m
γ
r
:
gname
)
(
f
v
:
val
)
:
=
(
∃
(
ts
:
toks
)
(
p
:
loc
),
v
=
#
p
★
evm
γ
m
p
ts
★
(
(* INIT *)
(
∃
y
:
val
,
p
↦
{
1
/
2
}
InjRV
y
★
init_s
ts
)
∨
(* INSTALLED *)
(
∃
x
:
val
,
p
↦
{
1
/
2
}
InjLV
x
★
installed_s
ts
x
)
∨
(
∃
x
:
val
,
p
↦
{
1
/
2
}
InjLV
x
★
installed_s
ts
f
x
)
∨
(* RECEIVED *)
(
∃
x
:
val
,
p
↦
{
1
/
2
}
InjLV
x
★
received_s
ts
x
γ
r
)
∨
(* FINISHED *)
(
∃
x
y
:
val
,
p
↦
{
1
/
2
}
InjRV
y
★
finished_s
ts
x
y
)))%
I
.
Global
Instance
p_inv_timeless
γ
m
γ
r
v
:
TimelessP
(
p_inv
γ
m
γ
r
v
).
Proof
.
rewrite
/
p_inv
.
apply
uPred
.
exist_timeless
.
destruct
x
as
[[[?
?]
?]
?].
apply
_
.
Qed
.
Definition
srv_stack_inv
(
γ
s
γ
m
γ
r
:
gname
)
(
s
:
loc
)
:
=
(
∃
xs
,
is_stack'
(
p_inv
γ
m
γ
r
)
γ
s
xs
s
)%
I
.
Definition
srv_stack_inv
γ
s
γ
m
γ
r
s
f
:
=
(
∃
xs
,
is_stack'
(
p_inv
γ
m
γ
r
f
)
γ
s
xs
s
)%
I
.
Definition
srv_tokm_inv
γ
m
:
=
(
∃
m
:
tokmR
,
own
γ
m
(
●
m
)
★
[
★
map
]
p
↦
_
∈
m
,
∃
v
,
p
↦
{
1
/
2
}
v
)%
I
.
Lemma
install_push_spec
(
Φ
:
val
→
iProp
Σ
)
(
p
:
loc
)
(
γ
s
γ
m
γ
r
:
gname
)
(
ts
:
toks
)
(
s
:
loc
)
(
x
:
val
)
:
(
s
:
loc
)
(
f
x
:
val
)
:
heapN
⊥
N
→
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
★
srv_tokm_inv
γ
m
)
★
evm
γ
m
p
ts
★
installed_s
ts
x
★
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
f
★
srv_tokm_inv
γ
m
)
★
evm
γ
m
p
ts
★
installed_s
ts
f
x
★
p
↦
{
1
/
2
}
InjLV
x
★
((
∃
hd
,
evs
γ
s
hd
#
p
)
-
★
Φ
#())
⊢
WP
push
#
s
#
p
{{
Φ
}}.
Proof
.
iIntros
(
HN
)
"(#Hh & #? & Hpm & Hs & Hp & HΦ)"
.
rewrite
/
srv_stack_inv
.
iDestruct
(
push_spec
N
(
p_inv
γ
m
γ
r
)
(
fun
v
=>
(
∃
hd
,
evs
γ
s
hd
#
p
)
★
v
=
#())%
I
iDestruct
(
push_spec
N
(
p_inv
γ
m
γ
r
f
)
(
fun
v
=>
(
∃
hd
,
evs
γ
s
hd
#
p
)
★
v
=
#())%
I
with
"[-HΦ]"
)
as
"Hpush"
=>//.
-
iFrame
"Hh"
.
iSplitL
"Hp Hs Hpm"
;
last
eauto
.
iExists
ts
.
iExists
p
.
iSplit
=>//.
iFrame
"Hpm"
.
...
...
@@ -133,35 +137,37 @@ Section proof.
by
iApply
"HΦ"
.
Qed
.
Definition
installed_recp
(
ts
:
toks
)
(
x
:
val
)
:
=
let
'
(
γ
x
,
_
,
γ
3
,
_
)
:
=
ts
in
(
own
γ
3
(
Excl
())
★
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
))%
I
.
Definition
installed_recp
(
ts
:
toks
)
(
x
:
val
)
(
Q
:
val
→
val
→
iProp
Σ
)
:
=
let
'
(
γ
x
,
_
,
γ
3
,
_
,
γ
q
)
:
=
ts
in
(
own
γ
3
(
Excl
())
★
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
saved_prop_own
γ
q
(
Q
x
))%
I
.
Lemma
install_spec
(
Φ
:
val
→
iProp
Σ
)
(
x
:
val
)
(
γ
s
γ
m
γ
r
:
gname
)
(
s
:
loc
)
:
(
Φ
:
val
→
iProp
Σ
)
P
Q
(
f
x
:
val
)
(
γ
s
γ
m
γ
r
:
gname
)
(
s
:
loc
)
:
heapN
⊥
N
→
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
★
srv_tokm_inv
γ
m
)
★
P
x
★
(
∀
(
p
:
loc
)
(
ts
:
toks
),
installed_recp
ts
x
-
★
evm
γ
m
p
ts
-
★
(
∃
hd
,
evs
γ
s
hd
#
p
)
-
★
Φ
#
p
)
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
f
★
srv_tokm_inv
γ
m
)
★
P
x
★
({{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
★
(
∀
(
p
:
loc
)
(
ts
:
toks
),
installed_recp
ts
x
Q
-
★
evm
γ
m
p
ts
-
★
(
∃
hd
,
evs
γ
s
hd
#
p
)
-
★
Φ
#
p
)
⊢
WP
install
x
#
s
{{
Φ
}}.
Proof
.
iIntros
(
HN
)
"(#Hh & #? & Hpx & HΦ)"
.
iIntros
(
HN
)
"(#Hh & #? & Hpx &
Hf &
HΦ)"
.
wp_seq
.
wp_let
.
wp_alloc
p
as
"Hl"
.
iApply
pvs_wp
.
iVs
(
own_alloc
(
Excl
()))
as
(
γ
1
)
"Ho1"
;
first
done
.
iVs
(
own_alloc
(
Excl
()))
as
(
γ
3
)
"Ho3"
;
first
done
.
iVs
(
own_alloc
(
Excl
()))
as
(
γ
4
)
"Ho4"
;
first
done
.
iVs
(
own_alloc
(
1
%
Qp
,
DecAgree
x
))
as
(
γ
x
)
"Hx"
;
first
done
.
iInv
N
as
">[Hrs Hm]"
"Hclose"
.
iVs
(
saved_prop_alloc
(
F
:
=(
cofe_funCF
val
idCF
))
(
Q
x
)%
I
)
as
(
γ
q
)
"#?"
.
iInv
N
as
"[Hrs >Hm]"
"Hclose"
.
iDestruct
"Hm"
as
(
m
)
"[Hm HRm]"
.
destruct
(
m
!!
p
)
eqn
:
Heqn
.
-
(* old name *)
iDestruct
(
big_sepM_delete
(
fun
p
_
=>
∃
v
:
val
,
p
↦
{
1
/
2
}
v
)%
I
m
with
"HRm"
)
as
"[Hp HRm]"
=>//.
iDestruct
"Hp"
as
(?)
"Hp"
.
iExFalso
.
iApply
bogus_heap
;
last
by
iFrame
"Hh Hl Hp"
.
auto
.
-
(* fresh name *)
iDestruct
(
evmap_alloc
_
_
_
m
p
(
γ
x
,
γ
1
,
γ
3
,
γ
4
)
with
"[Hm]"
)
as
"==>[Hm1 Hm2]"
=>//.
iDestruct
(
evmap_alloc
_
_
_
m
p
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
)
with
"[Hm]"
)
as
"==>[Hm1 Hm2]"
=>//.
iDestruct
"Hl"
as
"[Hl1 Hl2]"
.
iVs
(
"Hclose"
with
"[HRm Hm1 Hl1 Hrs]"
).
+
iNext
.
iFrame
.
iExists
({[
p
:
=
(
1
%
Qp
,
DecAgree
(
γ
x
,
γ
1
,
γ
3
,
γ
4
))]}
⋅
m
).
iFrame
.
+
iNext
.
iFrame
.
iExists
({[
p
:
=
(
1
%
Qp
,
DecAgree
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
))]}
⋅
m
).
iFrame
.
rewrite
<-(
insert_singleton_op
m
)=>//.
iDestruct
(
big_sepM_insert
_
m
with
"[-]"
)
as
"H"
=>//.
iSplitL
"Hl1"
;
last
by
iAssumption
.
eauto
.
...
...
@@ -171,83 +177,84 @@ Section proof.
iVsIntro
.
wp_let
.
wp_bind
((
push
_
)
_
).
iApply
install_push_spec
=>//.
iFrame
"#"
.
rewrite
/
evm
/
installed_s
.
iFrame
"Hev1 Hx1 Hpx Ho1 Ho4 Hl2"
.
iFrame
.
iSplitL
"Hpx Hx1 Hf"
.
{
iExists
P
,
Q
.
by
iFrame
.
}
iIntros
"Hhd"
.
wp_seq
.
iVsIntro
.
iSpecialize
(
"HΦ"
$!
p
(
γ
x
,
γ
1
,
γ
3
,
γ
4
)
with
"[-Hev
2
Hhd]"
)=>//.
{
rewrite
/
installed_recp
.
iFrame
.
}
by
iApply
(
"HΦ"
with
"Hev
2
"
).
iSpecialize
(
"HΦ"
$!
p
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
)
with
"[-Hev
1
Hhd]"
)=>//.
{
rewrite
/
installed_recp
.
iFrame
.
iFrame
"#"
.
}
by
iApply
(
"HΦ"
with
"Hev
1
"
).
Qed
.
Lemma
loop_iter_list_spec
Φ
(
f
:
val
)
(
s
hd
:
loc
)
(
γ
s
γ
m
γ
r
:
gname
)
xs
:
heapN
⊥
N
→
(
∀
x
:
val
,
{{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
★
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
★
srv_tokm_inv
γ
m
)
★
own
γ
r
(
Excl
())
★
R
★
heapN
⊥
N
→
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
f
★
srv_tokm_inv
γ
m
)
★
own
γ
r
(
Excl
())
★
R
★
is_list'
γ
s
hd
xs
★
(
own
γ
r
(
Excl
())
-
★
R
-
★
Φ
#())
⊢
WP
doOp
f
{{
f'
,
WP
iter
#
hd
f'
{{
Φ
}}
}}.
Proof
.
iIntros
(
HN
)
"(#Hf & #? &
#? &
Ho2 & HR & Hlist' & HΦ)"
.
iIntros
(
HN
)
"(#Hf & #? & Ho2 & HR & Hlist' & HΦ)"
.
iApply
pvs_wp
.
iDestruct
(
dup_is_list'
with
"[Hlist']"
)
as
"==>[Hl1 Hl2]"
;
first
by
iFrame
.
iDestruct
(
dup_is_list'
with
"[Hl2]"
)
as
"==>[Hl2 Hl3]"
;
first
by
iFrame
.
iVsIntro
.
wp_seq
.
iDestruct
(
iter_spec
_
(
p_inv
γ
m
γ
r
)
(
fun
v
=>
v
=
#()
★
own
γ
r
(
Excl
())
★
R
)%
I
γ
s
s
((
∀
x
:
val
,
{{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
★
is_list'
γ
s
hd
xs
★
own
γ
r
(
Excl
())
★
R
)%
I
(
srv_tokm_inv
γ
m
)
xs
hd
iDestruct
(
iter_spec
_
(
p_inv
γ
m
γ
r
f
)
(
fun
v
=>
v
=
#()
★
own
γ
r
(
Excl
())
★
R
)%
I
γ
s
s
(
is_list'
γ
s
hd
xs
★
own
γ
r
(
Excl
())
★
R
)%
I
(
srv_tokm_inv
γ
m
)
xs
hd
(
doOp'
f
)
(
doOp'
f
)
with
"[-Hl1 HΦ]"
)
as
"Hiter"
=>//.
-
rewrite
/
f_spec
.
iIntros
(
Φ
'
p
_
Hin
)
"(#Hh & #? & (
#Hf &
Hls & Ho2 & HR) & HΦ')"
.
wp_let
.
wp_bind
(!
_
)%
E
.
iInv
N
as
"
>
[Hs Hm]"
"Hclose"
.
iDestruct
"Hs"
as
(
xs'
hd'
)
"[Hhd [Hxs HRs]]"
.
iIntros
(
Φ
'
p
_
Hin
)
"(#Hh & #? & (Hls & Ho2 & HR) & HΦ')"
.
wp_let
.
wp_bind
(!
_
)%
E
.
iInv
N
as
"[Hs
>
Hm]"
"Hclose"
.
iDestruct
"Hs"
as
(
xs'
hd'
)
"[
>
Hhd [
>
Hxs HRs]]"
.
iDestruct
(
dup_is_list'
with
"[Hls]"
)
as
"==>[Hls1 Hls2]"
;
first
by
iFrame
.
iDestruct
"HRs"
as
(
m
)
"[Hom HRs]"
.
iDestruct
(
access
with
"[Hom HRs Hls1]"
)
as
(
hd''
[
q
x
])
"[Hrest [Hhd'' [% Hom]]]"
=>//
;
first
by
iFrame
.
iDestruct
"Hhd''"
as
"(% & H & Hphd)"
.
inversion
H2
.
subst
.
iDestruct
"H"
as
(
ts
p''
)
"[% [Hev [Hp | [Hp | [Hp | Hp]]]]]"
;
subst
.
+
iDestruct
"Hp"
as
(
y
)
"(Hp & Hs)"
.
iDestruct
"HRs"
as
(
m
)
"[>Hom HRs]"
.
(* acccess *)
iDestruct
(
access
with
"[Hom HRs Hls1]"
)
as
(
hd''
?)
"(Hrest & HRx & % & Hom)"
=>//
;
first
iFrame
.
iDestruct
"HRx"
as
(
v'
)
"[>% [Hpinv' >Hhd'']]"
.
inversion
H1
.
subst
.
iDestruct
"Hpinv'"
as
(
ts
p''
)
"[>% [>Hevm [Hp | [Hp | [Hp | Hp]]]]]"
;
subst
.
+
iDestruct
"Hp"
as
(
y
)
"(>Hp & Hs)"
.
wp_load
.
iVs
(
"Hclose"
with
"[-HΦ' Ho2 HR Hls2]"
).
{
iNext
.
iFrame
.
iExists
xs'
,
hd'
.
iFrame
"Hhd Hxs"
.
iExists
m
.
iFrame
"Hom"
.
iDestruct
(
big_sepM_delete
_
m
with
"[Hrest H
p
hd Hev Hp Hs]"
)
as
"?"
=>//.
iFrame
"Hom"
.
iDestruct
(
big_sepM_delete
_
m
with
"[Hrest Hhd
''
Hev
m
Hp Hs]"
)
as
"?"
=>//.
iFrame
.
iExists
#
p''
.
iSplitR
;
first
done
.
iExists
ts
,
p''
.
iSplitR
;
first
done
.
iFrame
.
iLeft
.
iExists
y
.
iFrame
.
}
iVsIntro
.
wp_match
.
iApply
"HΦ'"
.
by
iFrame
.
+
iDestruct
"Hp"
as
(
x'
)
"(Hp & Hs)"
.
wp_load
.
destruct
ts
as
[[[
γ
x
γ
1
]
γ
3
]
γ
4
].
iDestruct
"Hs"
as
"(Hx & Hpx & Ho1 & Ho4)"
.
iDestruct
(
dup_ev
with
"Hev"
)
as
"==>[Hev1 Hev2]"
.
wp_load
.
destruct
ts
as
[[[
[
γ
x
γ
1
]
γ
3
]
γ
4
]
γ
q
]
.
iDestruct
"Hs"
as
(
P
Q
)
"(Hx & Hpx &
Hf & HoQ&
Ho1 & Ho4)"
.
iDestruct
(
dup_ev
with
"Hev
m
"
)
as
"==>[Hev
m
1 Hev
m
2]"
.
iAssert
(|=
r
=>
own
γ
x
(((
1
/
2
/
2
)%
Qp
,
DecAgree
x'
)
⋅
((
1
/
2
/
2
)%
Qp
,
DecAgree
x'
)))%
I
with
"[Hx]"
as
"==>[Hx1 Hx2]"
.
{
iDestruct
(
own_update
with
"Hx"
)
as
"?"
;
last
by
iAssumption
.
rewrite
-{
1
}(
Qp_div_2
(
1
/
2
)%
Qp
).
by
apply
pair_l_frac_op'
.
}
iVs
(
"Hclose"
with
"[-Hls2 Ho1 Hx2 HR Hev
2
Hpx HΦ']"
).
iVs
(
"Hclose"
with
"[-
Hf
Hls2 Ho1 Hx2 HR Hev
m2 HoQ
Hpx HΦ']"
).
{
iNext
.
iFrame
.
iExists
xs'
,
hd'
.
iFrame
"Hhd Hxs"
.
iExists
m
.
iFrame
"Hom"
.
iDestruct
(
big_sepM_delete
_
m
with
"[-]"
)
as
"?"
=>//.
simpl
.
iFrame
.
iExists
#
p''
.
iSplitR
;
auto
.
rewrite
/
allocated
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
),
p''
.
iSplitR
;
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
),
p''
.
iSplitR
;
auto
.
iFrame
.
iRight
.
iRight
.
iLeft
.
iExists
x'
.
iFrame
.
}
iVsIntro
.
wp_match
.
wp_bind
(
f
_
).
iApply
wp_wand_r
.
iSplitL
"Hpx HR"
.
wp_bind
(
f
_
).
iApply
wp_wand_r
.
iSplitL
"Hpx
Hf
HR"
.
{
iApply
"Hf"
.
iFrame
.
}
iIntros
(
v
)
"[HR HQ]"
.
wp_value
.
iVsIntro
.
iInv
N
as
"
>
[Hs Hm]"
"Hclose"
.
iDestruct
"Hs"
as
(
xs''
hd'''
)
"[Hhd [Hxs HRs]]"
.
iDestruct
"HRs"
as
(
m'
)
"[Hom HRs]"
.
wp_value
.
iVsIntro
.
iInv
N
as
"[Hs
>
Hm]"
"Hclose"
.
iDestruct
"Hs"
as
(
xs''
hd'''
)
"[
>
Hhd [
>
Hxs HRs]]"
.
iDestruct
"HRs"
as
(
m'
)
"[
>
Hom HRs]"
.
iDestruct
(
dup_is_list'
with
"[Hls2]"
)
as
"==>[Hls2 Hls3]"
;
first
by
iFrame
.
iDestruct
(
access
with
"[Hom HRs Hls2]"
)
as
(
hd''''
[?
?])
"[Hrest [Hhd'' [% Hom]]]"
=>//
;
first
by
iFrame
.
iDestruct
"Hhd''"
as
"(% & H & Hphd)"
.
inversion
H4
.
subst
.
iDestruct
"H"
as
([[[
γ
x'
γ
1
'
]
γ
3
'
]
γ
4
'
]
p''''
)
"[% [Hev Hps]]"
.
inversion
H5
.
subst
.
destruct
(
decide
(
γ
1
=
γ
1
'
∧
γ
x
=
γ
x'
∧
γ
3
=
γ
3
'
∧
γ
4
=
γ
4
'
))
as
[[?
[?
[?
?]]]|
Hneq
]
;
subst
.
iDestruct
(
access
with
"[Hom HRs Hls2]"
)
as
(
hd''''
q
)
"(Hrest & HRx & % & Hom)"
=>//
;
first
iFrame
.
iDestruct
"HRx"
as
(
v''
)
"[>% [Hpinv' >Hhd'']]"
.
inversion
H2
.
subst
.
iDestruct
"Hpinv'"
as
([[[[
γ
x'
γ
1
'
]
γ
3
'
]
γ
4
'
]
γ
q'
]
p''''
)
"[>% [>Hevm Hps]]"
.
inversion
H3
.
subst
.
destruct
(
decide
(
γ
1
=
γ
1
'
∧
γ
x
=
γ
x'
∧
γ
3
=
γ
3
'
∧
γ
4
=
γ
4
'
∧
γ
q
=
γ
q'
))
as
[[?
[?
[?
[?
?]]]]|
Hneq
]
;
subst
.
{
iDestruct
"Hps"
as
"[Hp | [Hp | [Hp | Hp]]]"
.
*
iDestruct
"Hp"
as
(?)
"(_ & Ho1' & _)"
.
*
iDestruct
"Hp"
as
(?)
"(_ &
>
Ho1' & _)"
.
iApply
excl_falso
.
iFrame
.
*
iDestruct
"Hp"
as
(?)
"(_ & _ & _ & Ho1' & _)"
.
*
iDestruct
"Hp"
as
(?)
"[>? Hs]"
.
iDestruct
"Hs"
as
(?
?)
"(_ & _ & _ &
_ & >
Ho1' & _)"
.
iApply
excl_falso
.
iFrame
.
*
iDestruct
"Hp"
as
(
x5
)
"(Hp & Hx & Ho2 & Ho4)"
.
*
iDestruct
"Hp"
as
(
x5
)
"
>
(Hp & Hx & Ho2 & Ho4)"
.
iDestruct
"Hm"
as
(
m2
)
"[Hom2 HRm]"
.
destruct
(
m2
!!
p''''
)
eqn
:
Heqn
.
{
...
...
@@ -266,55 +273,59 @@ Section proof.
iExists
m'
.
iFrame
.
iDestruct
(
big_sepM_delete
_
m'
with
"[-]"
)
as
"?"
=>//.
{
simpl
.
iFrame
.
iExists
#
p''''
.
iSplitR
;
first
auto
.
iExists
(
γ
x'
,
γ
1
'
,
γ
3
'
,
γ
4
'
),
p''''
.
iSplitR
;
first
auto
.
iFrame
"Hev"
.
iRight
.
iRight
.
iSplitR
;
first
auto
.
iExists
(
γ
x'
,
γ
1
'
,
γ
3
'
,
γ
4
'
,
γ
q'
),
p''''
.
iSplitR
;
first
auto
.
iFrame
"Hev
m
"
.
iRight
.
iRight
.
iRight
.
iExists
x5
,
v
.
iFrame
.
iExists
Q
.
iFrame
.
}
}
iApply
"HΦ'"
.
by
iFrame
.
}
{
iExFalso
.
iApply
(
map_agree_none'
_
_
_
m2
)=>//.
iFrame
.
}
*
iDestruct
"Hp"
as
(?
?)
"(_ & _ & _ & Ho1' & _)"
.
*
iDestruct
"Hp"
as
(?
?)
"[? Hs]"
.
iDestruct
"Hs"
as
(?)
"(_ & _ & _ &
>
Ho1' & _)"
.
iApply
excl_falso
.
iFrame
.
}
{
iDestruct
(
ev_agree
with
"[Hev
2
Hev]"
)
as
"==>[_ [_ %]]"
;
first
iFrame
.
inversion
H
6
.
subst
.
by
contradiction
Hneq
.
}
+
destruct
ts
as
[[[
γ
x
γ
1
]
γ
3
]
γ
4
].
iDestruct
"Hp"
as
(
y
)
"(_ & _ & Ho2' & _)"
.
{
iDestruct
(
ev_agree
with
"[Hev
m
Hev
m2
]"
)
as
"==>[_ [_ %]]"
;
first
iFrame
.
inversion
H
4
.
subst
.
by
contradiction
Hneq
.
}
+
destruct
ts
as
[[[
[
γ
x
γ
1
]
γ
3
]
γ
4
]
γ
q
]
.
iDestruct
"Hp"
as
(
y
)
"(_ & _ &
>
Ho2' & _)"
.
iApply
excl_falso
.
iFrame
.
+
destruct
ts
as
[[[
γ
x
γ
1
]
γ
3
]
γ
4
].
iDestruct
"Hp"
as
(
x'
y
)
"(Hp & Hx & HQxy & Ho1 & Ho4)"
.
+
destruct
ts
as
[[[[
γ
x
γ
1
]
γ
3
]
γ
4
]
γ
q
].
iDestruct
"Hp"
as
(
x'
y
)
"[Hp Hs]"
.
iDestruct
"Hs"
as
(
Q
)
"(>Hx & HoQ & HQxy & >Ho1 & >Ho4)"
.
wp_load
.
iVs
(
"Hclose"
with
"[-HΦ' HR Ho2 Hls2]"
).
{
iNext
.
iFrame
.
iExists
xs'
,
hd'
.
iFrame
"Hhd Hxs"
.
iExists
m
.
iFrame
"Hom"
.
iDestruct
(
big_sepM_delete
_
m
with
"[-]"
)
as
"?"
=>//.
iFrame
.
iExists
#
p''
.
iSplitR
;
first
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
),
p''
.
iSplitR
;
auto
.
iFrame
.
iRight
.
iRight
.
iRight
.
iExists
x'
,
y
.
iFrame
.
}
iFrame
.
iExists
#
p''
.
iSplitR
;
first
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
),
p''
.
iSplitR
;
auto
.
iFrame
.
iRight
.
iRight
.
iRight
.
iExists
x'
,
y
.
iFrame
.
iExists
Q
.
iFrame
.
}
iVsIntro
.
wp_match
.
iApply
"HΦ'"
.
by
iFrame
.
-
apply
to_of_val
.
-
rewrite
/
srv_stack_inv
.
iFrame
"#"
.
iFrame
.
iIntros
"
[_
(? & ? & ?)
]
"
.
by
iFrame
.
-
rewrite
/
srv_stack_inv
.
iFrame
"#"
.
iFrame
.
iIntros
"(? & ? & ?)"
.
by
iFrame
.
-
iApply
wp_wand_r
.
iSplitL
"Hiter"
;
first
done
.
iIntros
(?)
"[% [Ho2 HR]]"
.
subst
.
iApply
(
"HΦ"
with
"Ho2 HR"
).
Qed
.
Definition
own_
γ
3
(
ts
:
toks
)
:
=
let
'
(
_
,
_
,
γ
3
,
_
)
:
=
ts
in
own
γ
3
(
Excl
()).
Definition
own_
γ
3
(
ts
:
toks
)
:
=
let
'
(
_
,
_
,
γ
3
,
_
,
_
)
:
=
ts
in
own
γ
3
(
Excl
()).
Definition
finished_recp
(
ts
:
toks
)
(
x
y
:
val
)
:
=
let
'
(
γ
x
,
_
,
_
,
_
)
:
=
ts
in
(
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
Q
x
y
)%
I
.
let
'
(
γ
x
,
_
,
_
,
_
,
γ
q
)
:
=
ts
in
(
∃
Q
,
own
γ
x
((
1
/
2
)%
Qp
,
DecAgree
x
)
★
saved_prop_own
γ
q
(
Q
x
)
★
Q
x
y
)%
I
.
Lemma
try_srv_spec
Φ
(
s
:
loc
)
(
lk
:
val
)
(
f
:
val
)
(
γ
s
γ
r
γ
m
γ
lk
:
gname
)
:
heapN
⊥
N
→
(
∀
x
:
val
,
{{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
★
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
★
srv_tokm_inv
γ
m
)
★
heapN
⊥
N
→
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
f
★
srv_tokm_inv
γ
m
)
★
is_lock
N
γ
lk
lk
(
own
γ
r
(
Excl
())
★
R
)
★
Φ
#()
⊢
WP
try_srv
lk
#
s
f
{{
Φ
}}.
Proof
.
iIntros
(?)
"(#? & #? & #? &
#? &
HΦ)"
.
iIntros
(?)
"(#? & #? & #? & HΦ)"
.
wp_seq
.
wp_let
.
wp_let
.
wp_bind
(
try_acquire
_
).
iApply
try_acquire_spec
.
iFrame
"#"
.
iSplit
;
last
by
wp_if
.
(* acquired the lock *)
iIntros
"Hlocked [Ho2 HR]"
.
wp_if
.
wp_bind
(!
_
)%
E
.
iInv
N
as
"
>
[H Hm]"
"Hclose"
.
iDestruct
"H"
as
(
xs'
hd'
)
"[Hs [Hxs HRs]]"
.
iInv
N
as
"[H
>
Hm]"
"Hclose"
.
iDestruct
"H"
as
(
xs'
hd'
)
"[
>
Hs [
>
Hxs HRs]]"
.
wp_load
.
iDestruct
(
dup_is_list'
with
"[Hxs]"
)
as
"==>[Hxs1 Hxs2]"
;
first
by
iFrame
.
iVs
(
"Hclose"
with
"[Hs Hxs1 HRs Hm]"
).
{
iNext
.
iFrame
.
iExists
xs'
,
hd'
.
by
iFrame
.
}
...
...
@@ -332,39 +343,38 @@ Section proof.
Lemma
loop_spec
Φ
(
p
s
:
loc
)
(
lk
:
val
)
(
f
:
val
)
(
γ
s
γ
r
γ
m
γ
lk
:
gname
)
(
ts
:
toks
)
:
heapN
⊥
N
→
(
∀
x
:
val
,
{{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
★
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
★
srv_tokm_inv
γ
m
)
★
heapN
⊥
N
→
heap_ctx
★
inv
N
(
srv_stack_inv
γ
s
γ
m
γ
r
s
f
★
srv_tokm_inv
γ
m
)
★
is_lock
N
γ
lk
lk
(
own
γ
r
(
Excl
())
★
R
)
★
own_
γ
3
ts
★
evm
γ
m
p
ts
★
(
∃
hd
,
evs
γ
s
hd
#
p
)
★
(
∀
x
y
,
finished_recp
ts
x
y
-
★
Φ
y
)
⊢
WP
loop
f
#
p
#
s
lk
{{
Φ
}}.
Proof
.
iIntros
(
HN
)
"(
#Hf &
#Hh & #? & #? & Ho3 & Hev & Hhd & HΦ)"
.
iIntros
(
HN
)
"(#Hh & #? & #? & Ho3 & Hev & Hhd & HΦ)"
.
iL
ö
b
as
"IH"
.
wp_rec
.
repeat
wp_let
.
wp_bind
(!
_
)%
E
.
iInv
N
as
"
>
[Hinv ?]"
"Hclose"
.
iDestruct
"Hinv"
as
(
xs
hd
)
"[Hs [Hxs HRs]]"
.
iDestruct
"HRs"
as
(
m
)
"[Hom HRs]"
.
wp_bind
(!
_
)%
E
.
iInv
N
as
"[Hinv
>
?]"
"Hclose"
.
iDestruct
"Hinv"
as
(
xs
hd
)
"[
>
Hs [
>
Hxs HRs]]"
.
iDestruct
"HRs"
as
(
m
)
"[
>
Hom HRs]"
.
iDestruct
"Hhd"
as
(
hdp
?)
"Hhd"
.
destruct
(
m
!!
hdp
)
eqn
:
Heqn
.
-
iDestruct
(
big_sepM_delete
_
m
with
"HRs"
)
as
"[Hp Hrs]"
=>//.
iDestruct
"Hp"
as
(?)
"[% [Hpr ?]]"
;
subst
.
iDestruct
"Hpr"
as
(
ts'
p'
)
"(% & Hp' & Hp)"
.
-
iDestruct
(
big_sepM_delete
_later
_
m
with
"HRs"
)
as
"[Hp Hrs]"
=>//.
iDestruct
"Hp"
as
(?)
"[
>
% [Hpr ?]]"
;
subst
.
iDestruct
"Hpr"
as
(
ts'
p'
)
"(
>
% &
>
Hp' & Hp)"
.
subst
.
iDestruct
(
map_agree_eq'
_
_
γ
s
m
with
"[Hom Hhd]"
)
as
"(Hom & Hhd & %)"
=>//.
{
iFrame
.
rewrite
/
ev
.
eauto
.
}
inversion
H
2
.
subst
.
inversion
H
0
.
subst
.
iDestruct
(
ev_agree
with
"[Hev Hp']"
)
as
"==>[Hγs2 [Hγs %]]"
;
first
iFrame
.
subst
.
destruct
ts
as
[[[
γ
x
γ
1
]
γ
3
]
γ
4
].
destruct
ts
as
[[[
[
γ
x
γ
1
]
γ
3
]
γ
4
]
γ
q
]
.
iDestruct
"Hp"
as
"[Hp | [Hp | [ Hp | Hp]]]"
.
+
iDestruct
"Hp"
as
(?)
"(_ & _ & Ho3')"
.
+
iDestruct
"Hp"
as
(?)
"(_ & _ &
>
Ho3')"
.
iApply
excl_falso
.
iFrame
.
+
iDestruct
"Hp"
as
(
x
)
"(Hp & H
x & Ho1 & Ho4
)"
.
+
iDestruct
"Hp"
as
(
x
)
"(
>
Hp & H
s'
)"
.
wp_load
.
iVs
(
"Hclose"
with
"[-Hγs2 Ho3 HΦ Hhd]"
).
{
iNext
.
iFrame
.
iExists
xs
,
hd
.
iFrame
.
iExists
m
.
iFrame
.
iDestruct
(
big_sepM_delete
_
m
with
"[-]"
)
as
"?"
=>//.
iFrame
.
iExists
#
p'
.
iSplitR
;
first
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
),
p'
.
iFrame
.
iExists
#
p'
.
iSplitR
;
first
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
),
p'
.
iSplitR
;
first
auto
.
iFrame
.
iRight
.
iLeft
.
iExists
x
.
iFrame
.
}
iRight
.
iLeft
.
iExists
x
.
iFrame
.
}
iVsIntro
.
wp_match
.
wp_bind
(
try_srv
_
_
_
).
iApply
try_srv_spec
=>//.
iFrame
"#"
.
wp_seq
.
...
...
@@ -375,36 +385,35 @@ Section proof.
iVs
(
"Hclose"
with
"[-Hγs Ho3 HΦ Hhd]"
).
{
iNext
.
iFrame
.
iExists
xs
,
hd
.
iFrame
.
iExists
m
.
iFrame
.
iDestruct
(
big_sepM_delete
_
m
with
"[-]"
)
as
"?"
=>//.
iFrame
.
iExists
#
p'
.
iSplitR
;
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
),
p'
.
iFrame
.
iExists
#
p'
.
iSplitR
;
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
),
p'
.
iSplitR
;
first
auto
.
iFrame
.
iRight
.
iRight
.
iLeft
.
iExists
x
.
iFrame
.
}
iRight
.
iRight
.
iLeft
.
iExists
x
.
iFrame
.
}
iVsIntro
.
wp_match
.
wp_bind
(
try_srv
_
_
_
).
iApply
try_srv_spec
=>//.
iFrame
"#"
.
wp_seq
.
iAssert
(
∃
hd
,
evs
γ
s
hd
#
p'
)%
I
with
"[Hhd]"
as
"Hhd"
;
eauto
.
by
iApply
(
"IH"
with
"Ho3 Hγs Hhd"
).
+
iDestruct
"Hp"
as
(
x
y
)
"(Hp & Hx & HQ & Ho1 & Ho4)"
.
wp_load
.
iVs
(
"Hclose"
with
"[-Hγs Ho4 HΦ Hx HQ]"
).
+
iDestruct
"Hp"
as
(
x
y
)
"[>Hp Hs']"
.
iDestruct
"Hs'"
as
(
Q
)
"(>Hx & HoQ & HQ & >Ho1 & >Ho4)"
.
wp_load
.
iVs
(
"Hclose"
with
"[-Hγs Ho4 HΦ Hx HoQ HQ]"
).
{
iNext
.
iFrame
.
iExists
xs
,
hd
.
iFrame
.
iExists
m
.
iFrame
.
iDestruct
(
big_sepM_delete
_
m
with
"[-]"
)
as
"?"
=>//.
iFrame
.
iExists
#
p'
.
iSplitR
;
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
),
p'
.
iFrame
.
iExists
#
p'
.
iSplitR
;
auto
.
iExists
(
γ
x
,
γ
1
,
γ
3
,
γ
4
,
γ
q
),
p'
.
iSplitR
;
first
auto
.
iFrame
.
iLeft
.
iExists
y
.
iFrame
.
}
iVsIntro
.
wp_match
.
iApply
(
"HΦ"
with
"[-]"
).
iFrame
.
iExists
Q
.
iFrame
.
-
iExFalso
.
iApply
(
map_agree_none'
_
_
_
m
)=>//.
iFrame
"Hom"
.
rewrite
/
ev
.
eauto
.
Qed
.
Definition
is_
flatte
r
(
f
l
:
val
)
:
=
(
∀
f
:
val
,
WP
fl
f
{{
f'
,
□
(
(
∀
x
:
val
,
{{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
→
(
∀
x
:
val
,
{{
P
x
}}
f'
x
{{
v
,
Q
x
v
}}))
}})
%
I
.
Definition
flatte
n
(
f
'
f
:
val
)
:
=
(
∀
P
Q
,
(
∀
x
:
val
,
{{
R
★
P
x
}}
f
x
{{
v
,
R
★
Q
x
v
}})
→
(
∀
x
:
val
,
{{
P
x
}}
f'
x
{{
v
,
▷
Q
x
v
}}))%
I
.
Lemma
mk_flat_spec
:
Lemma
mk_flat_spec
(
f
:
val
)
:
∀
(
Φ
:
val
→
iProp
Σ
),
heapN
⊥
N
→
heap_ctx
★
R
★
(
∀
f
l
,
is_
flatte
r
f
l
-
★
Φ
f
l
)
⊢
WP
mk_flat
#()
{{
Φ
}}.
heap_ctx
★
R
★
(
∀
f
'
,
□
flatte
n
f'
f
-
★
Φ
f
'
)
⊢
WP
mk_flat
f
{{
Φ
}}.
Proof
.
iIntros
(
Φ
HN
)
"(#Hh & HR & HΦ)"
.
iVs
(
own_alloc
(
Excl
()))
as
(
γ
r
)
"Ho2"
;
first
done
.
...
...
@@ -415,22 +424,25 @@ Section proof.
iApply
(
newlock_spec
_
(
own
γ
r
(
Excl
())
★
R
))%
I
=>//.
iFrame
"Hh Ho2 HR"
.
iIntros
(
lk
γ
lk
)
"#Hlk"
.
wp_let
.
wp_bind
(
new_stack
_
).
iApply
(
new_stack_spec'
_
(
p_inv
γ
m
γ
r
))=>//.
iApply
(
new_stack_spec'
_
(
p_inv
γ
m
γ
r
f
))=>//.
iFrame
"Hh Hm"
.
iIntros
(
γ
s
)
"#Hss"
.
wp_let
.
iVsIntro
.
iApply
"HΦ"
.
rewrite
/
is_
flatte
r
.
iIntros
(
f
).
wp_let
.
iVsIntro
.
iAlways
.
iIntros
"#Hf"
.
wp_let
.
iVsIntro
.
iApply
"HΦ"
.
rewrite
/
flatte
n
.
iAlways
.
iIntros
(
P
Q
)
"#Hf"
.
iIntros
(
x
)
"!# Hp"
.
wp_let
.
wp_bind
((
install
_
)
_
).
iApply
install_spec
=>//.
iFrame
"#"
.
iFrame
"Hp"
.
iIntros
(
p
[[[
γ
x
γ
1
]
γ
3
]
γ
4
])
"[Ho3 Hx] Hev Hhd"
.
iApply
(
install_spec
_
P
Q
)=>//.
iFrame
"#"
.
iFrame
"Hp"
.
iSplitR
;
first
iApply
"Hf"
.
iIntros
(
p
[[[[
γ
x
γ
1
]
γ
3
]
γ
4
]
γ
q
])
"(Ho3 & Hx & HoQ) Hev Hhd"
.
wp_let
.
iApply
loop_spec
=>//.
iFrame
"#"
.
iFrame
.
iIntros
(?
?)
"[Hx' HQ]"
.
destruct
(
decide
(
x
=
a
))
as
[->|
Hneq
]
;
first
done
.
{
iExFalso
.
iCombine
"Hx"
"Hx'"
as
"Hx"
.
iIntros
(?
?)
"Hs"
.
iDestruct
"Hs"
as
(
Q'
)
"(Hx' & HoQ' & HQ')"
.
destruct
(
decide
(
x
=
a
))
as
[->|
Hneq
].
-
iDestruct
(
saved_prop_agree
with
"[HoQ HoQ']"
)
as
"Heq"
;
first
by
iFrame
.
iNext
.
admit
.
(* iRewrite "Heq" in "HQ'". *)
-
iExFalso
.
iCombine
"Hx"
"Hx'"
as
"Hx"
.
iDestruct
(
own_valid
with
"Hx"
)
as
%[
_
H1
].
rewrite
pair_op
//=
dec_agree_ne
in
H1
=>//.
}