ownp.v 12.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 :
Ralf Jung's avatar
Ralf Jung committed
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  κ = []  σ2 = σ1) 
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 :
Ralf Jung's avatar
Ralf Jung committed
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 :
Ralf Jung's avatar
Ralf Jung committed
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
                     σ2' = σ2  to_val e2' = Some v2  efs' = efs) 
171
     (ownP σ1)   (ownP σ2 -
172 173 174
      Φ v2  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
  Proof.
175 176
    iIntros (? Hdet) "[Hσ1 Hσ2]"; iApply ownP_lift_atomic_step; try done.
    iFrame; iNext; iIntros (κ' e2' σ2' efs' ?) "Hσ2'".
177
    edestruct (Hdet κ') as (<-&Hval&<-); first done. rewrite Hval.
178
    iApply ("Hσ2" with "Hσ2'").
179 180
  Qed.

181
  Lemma ownP_lift_atomic_det_step_no_fork {s E e1} σ1 v2 σ2 :
Ralf Jung's avatar
Ralf Jung committed
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
      σ2' = σ2  to_val e2' = Some v2  efs' = []) 
185
    {{{  (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_no_fork `{Inhabited (state Λ)} {s E Φ} e1 e2 :
Ralf Jung's avatar
Ralf Jung committed
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'  κ = []  σ2 = σ1  e2' = e2  efs' = []) 
195
     WP e2 @ s; E {{ Φ }}  WP e1 @ s; E {{ Φ }}.
196
  Proof.
197
    intros. rewrite -(wp_lift_pure_det_step_no_fork e1 e2) //; eauto.
198 199 200 201 202
  Qed.
End lifting.

Section ectx_lifting.
  Import ectx_language.
203
  Context {Λ : ectxLanguage} `{ownPG Λ Σ} {Hinh : Inhabited (state Λ)}.
204
  Implicit Types s : stuckness.
205 206
  Implicit Types Φ : val Λ  iProp Σ.
  Implicit Types e : expr Λ.
207
  Hint Resolve head_prim_reducible head_reducible_prim_step.
208
  Hint Resolve (reducible_not_val _ inhabitant).
209
  Hint Resolve head_stuck_stuck.
210

211
  Lemma ownP_lift_head_step s E Φ e1 :
212 213 214
    (|={E,}=>  σ1, head_reducible e1 σ1   (ownP σ1) 
              κ e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs -
            ownP σ2
215 216
            ={,E}= WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
217
  Proof.
218
    iIntros "H". iApply ownP_lift_step.
219
    iMod "H" as (σ1 ?) "[>Hσ1 Hwp]". iModIntro. iExists σ1. iSplit.
220
    { destruct s; try by eauto using reducible_not_val. }
221
    iFrame. iNext. iIntros (κ e2 σ2 efs ?) "Hσ2".
222
    iApply ("Hwp" with "[] Hσ2"); eauto.
223 224
  Qed.

225
  Lemma ownP_lift_head_stuck E Φ e :
226
    sub_redexes_are_values e 
227
    (|={E,}=>  σ, head_stuck e σ⌝   (ownP σ))
228 229
     WP e @ E ?{{ Φ }}.
  Proof.
230 231
    iIntros (?) "H". iApply ownP_lift_stuck. iMod "H" as (σ) "[% >Hσ]".
    iExists σ. iModIntro. by auto with iFrame.
232 233 234
  Qed.

  Lemma ownP_lift_pure_head_step s E Φ e1 :
235
    ( σ1, head_reducible e1 σ1) 
236
    ( σ1 κ e2 σ2 efs, head_step e1 σ1 κ e2 σ2 efs  κ = []  σ2 = σ1) 
237
    (  κ e2 efs σ, head_step e1 σ κ e2 σ efs 
238 239
      WP e2 @ s; E {{ Φ }}  [ list] ef  efs, WP ef @ s;  {{ _, True }})
     WP e1 @ s; E {{ Φ }}.
240
  Proof using Hinh.
241
    iIntros (??) "H".  iApply ownP_lift_pure_step; eauto.
242
    { by destruct s; auto. }
243
    iNext. iIntros (?????). iApply "H"; eauto.
244 245
  Qed.

246
  Lemma ownP_lift_atomic_head_step {s E Φ} e1 σ1 :
247
    head_reducible e1 σ1 
248 249
     (ownP σ1)   ( κ e2 σ2 efs,
    head_step e1 σ1 κ e2 σ2 efs - ownP σ2 -
Ralf Jung's avatar
Ralf Jung committed
250
      from_option Φ False (to_val e2)  [ list] ef  efs, WP ef @ s;  {{ _, True }})
251
     WP e1 @ s; E {{ Φ }}.
252
  Proof.
253
    iIntros (?) "[Hst H]". iApply ownP_lift_atomic_step; eauto.
254
    { by destruct s; eauto using reducible_not_val. }
255
    iSplitL "Hst"; first done.
256
    iNext. iIntros (???? ?) "Hσ". iApply ("H" with "[] Hσ"); eauto.
257 258
  Qed.

259
  Lemma ownP_lift_atomic_det_head_step {s E Φ e1} σ1 v2 σ2 efs :
260
    head_reducible e1 σ1 
261
    ( κ' e2' σ2' efs', head_step e1 σ1 κ' e2' σ2' efs' 
262
      σ2' = σ2  to_val e2' = Some v2  efs' = efs) 
263 264
     (ownP σ1)   (ownP σ2 -
                      Φ v2  [ list] ef  efs, WP ef @ s;  {{ _, True }})
265 266
     WP e1 @ s; E {{ Φ }}.
  Proof.
267 268 269
    intros Hr Hs.
    destruct s; apply ownP_lift_atomic_det_step; eauto using reducible_not_val;
    intros; eapply Hs; eauto 10.
270
  Qed.
271

272
  Lemma ownP_lift_atomic_det_head_step_no_fork {s E e1} σ1 κ v2 σ2 :
273
    head_reducible e1 σ1 
274
    ( κ' e2' σ2' efs', head_step e1 σ1 κ' e2' σ2' efs' 
275
      κ' = κ  σ2' = σ2  to_val e2' = Some v2  efs' = []) 
276
    {{{  (ownP σ1) }}} e1 @ s; E {{{ RET v2; ownP σ2 }}}.
277
  Proof.
278
    intros ???; apply ownP_lift_atomic_det_step_no_fork; last naive_solver.
279
    by destruct s; eauto using reducible_not_val.
280 281
  Qed.

282
  Lemma ownP_lift_pure_det_head_step_no_fork {s E Φ} e1 e2 :
283
    ( σ1, head_reducible e1 σ1) 
284
    ( σ1 κ e2' σ2 efs', head_step e1 σ1 κ e2' σ2 efs'  κ = []  σ2 = σ1  e2' = e2  efs' = []) 
285
     WP e2 @ s; E {{ Φ }}  WP e1 @ s; E {{ Φ }}.
286
  Proof using Hinh.
287
    iIntros (??) "H"; iApply wp_lift_pure_det_step_no_fork; try by eauto.
288
    by destruct s; eauto using reducible_not_val.
289 290
  Qed.
End ectx_lifting.