ownp.v 13.2 KB
Newer Older
1 2 3 4 5
From iris.program_logic Require Export weakestpre.
From iris.program_logic Require Import lifting adequacy.
From iris.program_logic Require ectx_language.
From iris.algebra Require Import auth.
From iris.proofmode Require Import tactics classes.
6
Set Default Proof Using "Type".
7

8
Class ownPG' (Λstate Λobservation : Type) (Σ : gFunctors) := OwnPG {
9
  ownP_invG : invG Σ;
10 11
  ownP_inG :> inG Σ (authR (optionUR (exclR (leibnizC Λstate))));
  ownP_name : gname;
12
}.
13
Notation ownPG Λ Σ := (ownPG' (state Λ) (observation Λ) Σ).
14

15
Instance ownPG_irisG `{ownPG' Λstate Λobservation Σ} : irisG' Λstate Λobservation Σ := {
16
  iris_invG := ownP_invG;
17 18
  state_interp σ κs _ := (own ownP_name ( (Excl' (σ:leibnizC Λstate))))%I;
  fork_post := True%I;
19
}.
20
Global Opaque iris_invG.
21

22
Definition ownPΣ (Λstate : Type) : gFunctors :=
23
  #[invΣ;
24
    GFunctor (authR (optionUR (exclR (leibnizC Λstate))))].
25

26
Class ownPPreG' (Λstate : Type) (Σ : gFunctors) : Set := IrisPreG {
27
  ownPPre_invG :> invPreG Σ;
28
  ownPPre_state_inG :> inG Σ (authR (optionUR (exclR (leibnizC Λstate))))
29
}.
30
Notation ownPPreG Λ Σ := (ownPPreG' (state Λ) Σ).
31

32
Instance subG_ownPΣ {Λstate Σ} : subG (ownPΣ Λstate) Σ  ownPPreG' Λstate Σ.
33
Proof. solve_inG. Qed.
34 35

(** Ownership *)
36 37
Definition ownP `{ownPG' Λstate Λobservation Σ} (σ : Λstate) : iProp Σ :=
  own ownP_name ( (Excl' (σ:leibnizC Λstate))).
38

39 40
Typeclasses Opaque ownP.
Instance: Params (@ownP) 3.
41 42

(* Adequacy *)
43
Theorem ownP_adequacy Σ `{ownPPreG Λ Σ} s e σ φ :
44
  ( `{ownPG Λ Σ}, ownP σ  WP e @ s;  {{ v, ⌜φ v }}) 
45
  adequate s e σ (λ v _, φ v).
46 47
Proof.
  intros Hwp. apply (wp_adequacy Σ _).
48 49
  iIntros (? κs).
  iMod (own_alloc ( (Excl' (σ : leibnizC _))   (Excl' σ)))
50
    as (γσ) "[Hσ Hσf]"; first done.
51
  iModIntro. iExists (λ σ κs,
52 53 54
                      own γσ ( (Excl' (σ:leibnizC _))))%I.
  iFrame "Hσ".
  iApply (Hwp (OwnPG _ _ _ _ _ γσ)). rewrite /ownP. iFrame.
55 56
Qed.

57
Theorem ownP_invariance Σ `{ownPPreG Λ Σ} s e σ1 t2 σ2 φ :
58 59 60
  ( `{ownPG Λ Σ},
      ownP σ1 ={}= WP e @ s;  {{ _, True }} 
      |={,}=>  σ', ownP σ'  ⌜φ σ') 
61
  rtc erased_step ([e], σ1) (t2, σ2) 
62 63
  φ σ2.
Proof.
64
  intros Hwp Hsteps. eapply (wp_invariance Σ Λ s e σ1 t2 σ2 _)=> //.
65
  iIntros (? κs κs').
66
  iMod (own_alloc ( (Excl' (σ1 : leibnizC _))   (Excl' σ1)))
67
    as (γσ) "[Hσ Hσf]"; first done.
68
  iExists (λ σ κs' _, own γσ ( (Excl' (σ:leibnizC _))))%I, True%I.
69 70 71
  iFrame "Hσ".
  iMod (Hwp (OwnPG _ _ _ _ _ γσ) with "[Hσf]") as "[$ H]";
    first by rewrite /ownP; iFrame.
72 73 74
  iIntros "!> Hσ". iMod "H" as (σ2') "[Hσf %]". rewrite /ownP.
  iDestruct (own_valid_2 with "Hσ Hσf")
    as %[Hp%Excl_included _]%auth_valid_discrete_2; simplify_eq; auto.
75 76 77 78 79 80
Qed.


(** Lifting *)
Section lifting.
  Context `{ownPG Λ Σ}.
81
  Implicit Types s : stuckness.
82 83 84
  Implicit Types e : expr Λ.
  Implicit Types Φ : val Λ  iProp Σ.

85
  Lemma ownP_eq σ1 σ2 κs n : state_interp σ1 κs n - ownP σ2 - ⌜σ1 = σ2.
86
  Proof.
87
    iIntros "Hσ● Hσ◯". rewrite /ownP.
88 89
    iDestruct (own_valid_2 with "Hσ● Hσ◯") as %[Hps _]%auth_valid_discrete_2.
    by pose proof (leibniz_equiv _ _ (Excl_included _ _ Hps)) as ->.
90
  Qed.
91 92 93 94
  Lemma ownP_state_twice σ1 σ2 : ownP σ1  ownP σ2  False.
  Proof. rewrite /ownP -own_op own_valid. by iIntros (?). Qed.
  Global Instance ownP_timeless σ : Timeless (@ownP (state Λ) (observation Λ) Σ _ σ).
  Proof. rewrite /ownP; apply _. Qed.
95

96
  Lemma ownP_lift_step s E Φ e1 :
97 98 99 100
    (|={E,}=>  σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None 
       ownP σ1 
        κ e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs -
      ownP σ2
101 102
            ={,E}= WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
103 104 105
  Proof.
    iIntros "H". destruct (to_val e1) as [v|] eqn:EQe1.
    - apply of_to_val in EQe1 as <-. iApply fupd_wp.
106
      iMod "H" as (σ1) "[Hred _]"; iDestruct "Hred" as %Hred.
107
      destruct s; last done. apply reducible_not_val in Hred.
108
      move: Hred; by rewrite to_of_val.
109
    - iApply wp_lift_step; [done|]; iIntros (σ1 κ κs n) "Hσκs".
110 111
      iMod "H" as (σ1' ?) "[>Hσf H]".
      iDestruct (ownP_eq with "Hσκs Hσf") as %<-.
112
      iModIntro; iSplit; [by destruct s|]; iNext; iIntros (e2 σ2 efs Hstep).
113
      iDestruct "Hσκs" as "Hσ". rewrite /ownP.
114
      iMod (own_update_2 with "Hσ Hσf") as "[Hσ Hσf]".
Ralf Jung's avatar
Ralf Jung committed
115
      { apply auth_update. apply: option_local_update.
116
         by apply: (exclusive_local_update _ (Excl σ2)). }
117
      iFrame "Hσ". iApply ("H" with "[]"); eauto with iFrame.
118 119
  Qed.

120
  Lemma ownP_lift_stuck E Φ e :
121
    (|={E,}=>  σ, stuck e σ⌝   (ownP σ))
122 123 124
     WP e @ E ?{{ Φ }}.
  Proof.
    iIntros "H". destruct (to_val e) as [v|] eqn:EQe.
125
    - apply of_to_val in EQe as <-. iApply fupd_wp.
126
      iMod "H" as (σ1) "[H _]". iDestruct "H" as %[Hnv _]. exfalso.
127
      by rewrite to_of_val in Hnv.
128
    - iApply wp_lift_stuck; [done|]. iIntros (σ1 κs n) "Hσ".
129 130
      iMod "H" as (σ1') "(% & >Hσf)".
      by iDestruct (ownP_eq with "Hσ Hσf") as %->.
131 132
  Qed.

133
  Lemma ownP_lift_pure_step `{Inhabited (state Λ)} s E Φ e1 :
134
    ( σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) 
135
    ( σ1 κ e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs  κ = []  σ1 = σ2) 
136
    (  κ e2 efs σ, prim_step e1 σ κ e2 σ efs 
137 138
      WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
139
  Proof.
140 141 142
    iIntros (Hsafe Hstep) "H"; iApply wp_lift_step.
    { specialize (Hsafe inhabitant). destruct s; last done.
      by eapply reducible_not_val. }
143
    iIntros (σ1 κ κs n) "Hσ". iMod (fupd_intro_mask' E ) as "Hclose"; first set_solver.
144
    iModIntro; iSplit; [by destruct s|]; iNext; iIntros (e2 σ2 efs ?).
145
    destruct (Hstep σ1 κ e2 σ2 efs); auto; subst.
146
    by iMod "Hclose"; iModIntro; iFrame; iApply "H".
147 148 149
  Qed.

  (** Derived lifting lemmas. *)
150
  Lemma ownP_lift_atomic_step {s E Φ} e1 σ1 :
151
    (if s is NotStuck then reducible e1 σ1 else to_val e1 = None) 
152 153 154
    ( (ownP σ1) 
         κ e2 σ2 efs, prim_step e1 σ1 κ e2 σ2 efs -
         ownP σ2 -
Ralf Jung's avatar
Ralf Jung committed
155
      from_option Φ False (to_val e2)  [ list] ef  efs, WP ef @ s;  {{ _, True }})
156
     WP e1 @ s; E {{ Φ }}.
157
  Proof.
158
    iIntros (?) "[Hσ H]"; iApply ownP_lift_step.
159
    iMod (fupd_intro_mask' E ) as "Hclose"; first set_solver.
160 161 162
    iModIntro; iExists σ1; iFrame; iSplit; first by destruct s.
    iNext; iIntros (κ e2 σ2 efs ?) "Hσ".
    iDestruct ("H" $! κ e2 σ2 efs with "[] [Hσ]") as "[HΦ $]"; [by eauto..|].
163
    destruct (to_val e2) eqn:?; last by iExFalso.
164
    iMod "Hclose"; iApply wp_value; last done. by apply of_to_val.
165 166
  Qed.

167
  Lemma ownP_lift_atomic_det_step {s E Φ e1} σ1 v2 σ2 efs :
168
    (if s is NotStuck then reducible e1 σ1 else to_val e1 = None) 
169
    ( κ' e2' σ2' efs', prim_step e1 σ1 κ' e2' σ2' efs' 
170 171
                     σ2 = σ2'  to_val e2' = Some v2  efs = efs') 
     (ownP σ1)   (ownP σ2 -
172 173 174
      Φ v2  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
  Proof.
175 176 177 178
    iIntros (? Hdet) "[Hσ1 Hσ2]"; iApply ownP_lift_atomic_step; try done.
    iFrame; iNext; iIntros (κ' e2' σ2' efs' ?) "Hσ2'".
    edestruct (Hdet κ') as (->&Hval&->); first done. rewrite Hval.
    iApply ("Hσ2" with "Hσ2'").
179 180
  Qed.

181
  Lemma ownP_lift_atomic_det_step_no_fork {s E e1} σ1 v2 σ2 :
182
    (if s is NotStuck then reducible e1 σ1 else to_val e1 = None) 
183
    ( κ' e2' σ2' efs', prim_step e1 σ1 κ' e2' σ2' efs' 
184 185
      σ2 = σ2'  to_val e2' = Some v2  [] = efs') 
    {{{  (ownP σ1) }}} e1 @ s; E {{{ RET v2; ownP σ2 }}}.
186
  Proof.
187
    intros. rewrite -(ownP_lift_atomic_det_step σ1 v2 σ2 []); [|done..].
188
    rewrite big_sepL_nil right_id. apply bi.wand_intro_r. iIntros "[Hs Hs']".
189
    iSplitL "Hs"; first by iFrame. iModIntro. iIntros "Hσ2". iApply "Hs'". iFrame.
190 191
  Qed.

192
  Lemma ownP_lift_pure_det_step `{Inhabited (state Λ)} {s E Φ} e1 e2 efs :
193
    ( σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) 
194
    ( σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs'  κ = []  σ1 = σ2  e2 = e2'  efs = efs')
195 196
     (WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s; {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
197
  Proof.
198
    iIntros (? Hpuredet) "?"; iApply ownP_lift_pure_step=>//.
199
    naive_solver. by iNext; iIntros (κ e' efs' σ (->&_&->&->)%Hpuredet).
200 201 202
  Qed.

  Lemma ownP_lift_pure_det_step_no_fork `{Inhabited (state Λ)} {s E Φ} e1 e2 :
203
    ( σ1, if s is NotStuck then reducible e1 σ1 else to_val e1 = None) 
204
    ( σ1 κ e2' σ2 efs', prim_step e1 σ1 κ e2' σ2 efs'  κ = []  σ1 = σ2  e2 = e2'  [] = efs') 
205
     WP e2 @ s; E {{ Φ }}  WP e1 @ s; E {{ Φ }}.
206
  Proof.
207
    intros. rewrite -(wp_lift_pure_det_step e1 e2 []) // ?big_sepL_nil ?right_id; eauto.
208 209 210 211 212
  Qed.
End lifting.

Section ectx_lifting.
  Import ectx_language.
213
  Context {Λ : ectxLanguage} `{ownPG Λ Σ} {Hinh : Inhabited (state Λ)}.
214
  Implicit Types s : stuckness.
215 216
  Implicit Types Φ : val Λ  iProp Σ.
  Implicit Types e : expr Λ.
217
  Hint Resolve head_prim_reducible head_reducible_prim_step.
218
  Hint Resolve (reducible_not_val _ inhabitant).
219
  Hint Resolve head_stuck_stuck.
220

221
  Lemma ownP_lift_head_step s E Φ e1 :
222 223 224
    (|={E,}=>  σ1, head_reducible e1 σ1   (ownP σ1) 
              κ e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs -
            ownP σ2
225 226
            ={,E}= WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
227
  Proof.
228
    iIntros "H". iApply ownP_lift_step.
229
    iMod "H" as (σ1 ?) "[>Hσ1 Hwp]". iModIntro. iExists σ1. iSplit.
230
    { destruct s; try by eauto using reducible_not_val. }
231
    iFrame. iNext. iIntros (κ e2 σ2 efs ?) "Hσ2".
232
    iApply ("Hwp" with "[] Hσ2"); eauto.
233 234
  Qed.

235
  Lemma ownP_lift_head_stuck E Φ e :
236
    sub_redexes_are_values e 
237
    (|={E,}=>  σ, head_stuck e σ⌝   (ownP σ))
238 239
     WP e @ E ?{{ Φ }}.
  Proof.
240 241
    iIntros (?) "H". iApply ownP_lift_stuck. iMod "H" as (σ) "[% >Hσ]".
    iExists σ. iModIntro. by auto with iFrame.
242 243 244
  Qed.

  Lemma ownP_lift_pure_head_step s E Φ e1 :
245
    ( σ1, head_reducible e1 σ1) 
246
    ( σ1 κ e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs  κ = []  σ1 = σ2) 
247
    (  κ e2 efs σ, head_step e1 σ κ e2 σ efs 
248 249
      WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
250
  Proof using Hinh.
251
    iIntros (??) "H".  iApply ownP_lift_pure_step; eauto.
252
    { by destruct s; auto. }
253
    iNext. iIntros (?????). iApply "H"; eauto.
254 255
  Qed.

256
  Lemma ownP_lift_atomic_head_step {s E Φ} e1 σ1 :
257
    head_reducible e1 σ1 
258 259
     (ownP σ1)   ( κ e2 σ2 efs,
    head_step e1 σ1 κ e2 σ2 efs - ownP σ2 -
Ralf Jung's avatar
Ralf Jung committed
260
      from_option Φ False (to_val e2)  [ list] ef  efs, WP ef @ s;  {{ _, True }})
261
     WP e1 @ s; E {{ Φ }}.
262
  Proof.
263
    iIntros (?) "[Hst H]". iApply ownP_lift_atomic_step; eauto.
264
    { by destruct s; eauto using reducible_not_val. }
265
    iSplitL "Hst"; first done.
266
    iNext. iIntros (???? ?) "Hσ". iApply ("H" with "[] Hσ"); eauto.
267 268
  Qed.

269
  Lemma ownP_lift_atomic_det_head_step {s E Φ e1} σ1 v2 σ2 efs :
270
    head_reducible e1 σ1 
271
    ( κ' e2' σ2' efs', head_step e1 σ1 κ' e2' σ2' efs' 
272 273 274
      σ2 = σ2'  to_val e2' = Some v2  efs = efs') 
     (ownP σ1)   (ownP σ2 -
                      Φ v2  [ list] ef  efs, WP ef @ s;  {{ _, True }})
275 276
     WP e1 @ s; E {{ Φ }}.
  Proof.
277 278 279
    intros Hr Hs.
    destruct s; apply ownP_lift_atomic_det_step; eauto using reducible_not_val;
    intros; eapply Hs; eauto 10.
280
  Qed.
281

282
  Lemma ownP_lift_atomic_det_head_step_no_fork {s E e1} σ1 κ v2 σ2 :
283
    head_reducible e1 σ1 
284 285
    ( κ' e2' σ2' efs', head_step e1 σ1 κ' e2' σ2' efs' 
      κ = κ'  σ2 = σ2'  to_val e2' = Some v2  [] = efs') 
286
    {{{  (ownP σ1) }}} e1 @ s; E {{{ RET v2; ownP σ2 }}}.
287
  Proof.
288
    intros ???; apply ownP_lift_atomic_det_step_no_fork; last naive_solver.
289
    by destruct s; eauto using reducible_not_val.
290 291
  Qed.

292
  Lemma ownP_lift_pure_det_head_step {s E Φ} e1 e2 efs :
293
    ( σ1, head_reducible e1 σ1) 
294
    ( σ1 κ e2' σ2 efs', head_step e1 σ1 κ e2' σ2 efs'  κ = []  σ1 = σ2  e2 = e2'  efs = efs') 
295 296
     (WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
Ralf Jung's avatar
Ralf Jung committed
297
  Proof using Hinh.
298
    iIntros (??) "H"; iApply wp_lift_pure_det_step; try by eauto.
299
    by destruct s; eauto using reducible_not_val.
Ralf Jung's avatar
Ralf Jung committed
300
  Qed.
301

302
  Lemma ownP_lift_pure_det_head_step_no_fork {s E Φ} e1 e2 :
303
    ( σ1, head_reducible e1 σ1) 
304
    ( σ1 κ e2' σ2 efs', head_step e1 σ1 κ e2' σ2 efs'  κ = []  σ1 = σ2  e2 = e2'  [] = efs') 
305
     WP e2 @ s; E {{ Φ }}  WP e1 @ s; E {{ Φ }}.
306
  Proof using Hinh.
307 308
    iIntros (??) "H". iApply ownP_lift_pure_det_step_no_fork; eauto.
    by destruct s; eauto using reducible_not_val.
309 310
  Qed.
End ectx_lifting.