ownp.v 14.9 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 9 10 11 12 13 14 15 16 17 18

Class ownPG' (Λstate : Type) (Σ : gFunctors) := OwnPG {
  ownP_invG : invG Σ;
  ownP_inG :> inG Σ (authR (optionUR (exclR (leibnizC Λstate))));
  ownP_name : gname;
}.
Notation ownPG Λ Σ := (ownPG' (state Λ) Σ).

Instance ownPG_irisG `{ownPG' Λstate Σ} : irisG' Λstate Σ := {
  iris_invG := ownP_invG;
  state_interp σ := own ownP_name ( (Excl' (σ:leibnizC Λstate)))
}.
19
Global Opaque iris_invG.
20 21 22

Definition ownPΣ (Λstate : Type) : gFunctors :=
  #[invΣ;
23
    GFunctor (authUR (optionUR (exclR (leibnizC Λstate))))].
24 25 26 27 28 29 30 31

Class ownPPreG' (Λstate : Type) (Σ : gFunctors) : Set := IrisPreG {
  ownPPre_invG :> invPreG Σ;
  ownPPre_inG :> inG Σ (authR (optionUR (exclR (leibnizC Λstate))))
}.
Notation ownPPreG Λ Σ := (ownPPreG' (state Λ) Σ).

Instance subG_ownPΣ {Λstate Σ} : subG (ownPΣ Λstate) Σ  ownPPreG' Λstate Σ.
32
Proof. solve_inG. Qed.
33 34 35 36 37 38 39 40 41

(** Ownership *)
Definition ownP `{ownPG' Λstate Σ} (σ : Λstate) : iProp Σ :=
  own ownP_name ( (Excl' σ)).
Typeclasses Opaque ownP.
Instance: Params (@ownP) 3.


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

53
Theorem ownP_invariance Σ `{ownPPreG Λ Σ} p e σ1 t2 σ2 φ :
54
  ( `{ownPG Λ Σ},
55
    ownP σ1 ={}= WP e @ p;  {{ _, True }}  |={,}=>  σ', ownP σ'  ⌜φ σ') 
56 57 58
  rtc step ([e], σ1) (t2, σ2) 
  φ σ2.
Proof.
59
  intros Hwp Hsteps. eapply (wp_invariance Σ Λ p e σ1 t2 σ2 _)=> //.
60 61 62 63
  iIntros (?) "". iMod (own_alloc ( (Excl' (σ1 : leibnizC _))   (Excl' σ1)))
    as (γσ) "[Hσ Hσf]"; first done.
  iExists (λ σ, own γσ ( (Excl' (σ:leibnizC _)))). iFrame "Hσ".
  iMod (Hwp (OwnPG _ _ _ _ γσ) with "[Hσf]") as "[$ H]"; first by rewrite /ownP.
64
  iIntros "!> Hσ". iMod "H" as (σ2') "[Hσf %]". rewrite/ownP.
65 66 67 68 69 70 71 72
  iDestruct (own_valid_2 with "Hσ Hσf")
    as %[->%Excl_included%leibniz_equiv _]%auth_valid_discrete_2; auto.
Qed.


(** Lifting *)
Section lifting.
  Context `{ownPG Λ Σ}.
73
  Implicit Types p : bool.
74 75 76
  Implicit Types e : expr Λ.
  Implicit Types Φ : val Λ  iProp Σ.

77 78 79 80 81 82
  Lemma ownP_eq σ1 σ2 : state_interp σ1 - ownP σ2 - ⌜σ1 = σ2.
  Proof.
    iIntros "Hσ1 Hσ2"; rewrite/ownP.
    by iDestruct (own_valid_2 with "Hσ1 Hσ2")
      as %[->%Excl_included%leibniz_equiv _]%auth_valid_discrete_2.
  Qed.
83 84
  Lemma ownP_twice σ1 σ2 : ownP σ1  ownP σ2  False.
  Proof. rewrite /ownP -own_op own_valid. by iIntros (?). Qed.
85
  Global Instance ownP_timeless σ : Timeless (@ownP (state Λ) Σ _ σ).
86 87
  Proof. rewrite /ownP; apply _. Qed.

88
  Lemma ownP_lift_step p E Φ e1 :
89 90
    to_val e1 = None 
    (|={E,}=>  σ1, if p then reducible e1 σ1 else True   ownP σ1 
91
        e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs - ownP σ2
92 93
            ={,E}= WP e2 @ p; E {{ Φ }}  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
94
  Proof.
95 96 97 98 99 100 101 102
    iIntros (?) "H". iApply wp_lift_step; first done.
    iIntros (σ1) "Hσ"; iMod "H" as (σ1') "(% & >Hσf & H)".
    iDestruct (ownP_eq with "Hσ Hσf") as %->.
    iModIntro. iSplit; first done. iNext. iIntros (e2 σ2 efs Hstep).
    rewrite /ownP; iMod (own_update_2 with "Hσ Hσf") as "[Hσ Hσf]".
    { by apply auth_update, option_local_update,
        (exclusive_local_update _ (Excl σ2)). }
    iFrame "Hσ". by iApply ("H" with "[]"); eauto.
103 104
  Qed.

105 106 107 108 109 110 111 112 113
  Lemma ownP_lift_stuck E Φ e :
    (|={E,}=>  σ, ¬ progressive e σ⌝   ownP σ)
     WP e @ E ?{{ Φ }}.
  Proof.
    iIntros "H". destruct (to_val e) as [v|] eqn:EQe.
    - apply of_to_val in EQe as <-; iApply fupd_wp.
      iMod "H" as (σ1) "[#H _]"; iDestruct "H" as %Hstuck; exfalso.
      by apply Hstuck; left; rewrite to_of_val; exists v.
    - iApply wp_lift_stuck; [done|]; iIntros (σ1) "Hσ".
114 115
      iMod "H" as (σ1') "(% & >Hσf)".
      by iDestruct (ownP_eq with "Hσ Hσf") as %->.
116 117
  Qed.

118 119 120
  Lemma ownP_lift_pure_step p E Φ e1 :
    to_val e1 = None 
    ( σ1, if p then reducible e1 σ1 else True) 
121 122
    ( σ1 e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs  σ1 = σ2) 
    (  e2 efs σ, prim_step e1 σ e2 σ efs 
123 124
      WP e2 @ p; E {{ Φ }}  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
125
  Proof.
126
    iIntros (? Hsafe Hstep) "H"; iApply wp_lift_step; first done.
127
    iIntros (σ1) "Hσ". iMod (fupd_intro_mask' E ) as "Hclose"; first set_solver.
128
    iModIntro; iSplit; [by destruct p|]; iNext; iIntros (e2 σ2 efs ?).
129
    destruct (Hstep σ1 e2 σ2 efs); auto; subst.
130
    by iMod "Hclose"; iModIntro; iFrame; iApply "H".
131 132 133
  Qed.

  (** Derived lifting lemmas. *)
134
  Lemma ownP_lift_atomic_step {p E Φ} e1 σ1 :
135 136
    to_val e1 = None 
    (if p then reducible e1 σ1 else True) 
137
    ( ownP σ1    e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs - ownP σ2 -
138 139
      default False (to_val e2) Φ  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
140
  Proof.
141 142 143
    iIntros (??) "[Hσ H]"; iApply ownP_lift_step; first done.
    iMod (fupd_intro_mask' E ) as "Hclose"; first set_solver.
    iModIntro; iExists σ1; iFrame; iSplit; first by destruct p.
144 145 146
    iNext; iIntros (e2 σ2 efs) "% Hσ".
    iDestruct ("H" $! e2 σ2 efs with "[] [Hσ]") as "[HΦ $]"; [by eauto..|].
    destruct (to_val e2) eqn:?; last by iExFalso.
147
    by iMod "Hclose"; iApply wp_value; auto using to_of_val.
148 149
  Qed.

150
  Lemma ownP_lift_atomic_det_step {p E Φ e1} σ1 v2 σ2 efs :
151 152
    to_val e1 = None 
    (if p then reducible e1 σ1 else True) 
153 154 155
    ( e2' σ2' efs', prim_step e1 σ1 e2' σ2' efs' 
                     σ2 = σ2'  to_val e2' = Some v2  efs = efs') 
     ownP σ1   (ownP σ2 -
156 157
      Φ v2  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
158
  Proof.
159 160 161
    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&->). done. by rewrite Hval; iApply "Hσ2".
162 163
  Qed.

164
  Lemma ownP_lift_atomic_det_step_no_fork {p E e1} σ1 v2 σ2 :
165 166
    to_val e1 = None 
    (if p then reducible e1 σ1 else True) 
167 168 169 170 171 172 173 174
    ( e2' σ2' efs', prim_step e1 σ1 e2' σ2' efs' 
      σ2 = σ2'  to_val e2' = Some v2  [] = efs') 
    {{{  ownP σ1 }}} e1 @ p; E {{{ RET v2; ownP σ2 }}}.
  Proof.
    intros. rewrite -(ownP_lift_atomic_det_step σ1 v2 σ2 []); [|done..].
    rewrite big_sepL_nil right_id. by apply uPred.wand_intro_r.
  Qed.

175 176 177
  Lemma ownP_lift_pure_det_step {p E Φ} e1 e2 efs :
    to_val e1 = None 
    ( σ1, if p then reducible e1 σ1 else True) 
178
    ( σ1 e2' σ2 efs', prim_step e1 σ1 e2' σ2 efs'  σ1 = σ2  e2 = e2'  efs = efs')
179 180
     (WP e2 @ p; E {{ Φ }}  [ list] ef  efs, WP ef @ p; {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
181
  Proof.
182 183
    iIntros (?? Hpuredet) "?"; iApply ownP_lift_pure_step=>//.
    by apply Hpuredet. by iNext; iIntros (e' efs' σ (_&->&->)%Hpuredet).
184
  Qed.
185 186 187

  Lemma ownP_lift_pure_det_step_no_fork `{Inhabited (state Λ)} {p E Φ} e1 e2 :
    to_val e1 = None 
188
    ( σ1, if p then reducible e1 σ1 else True) 
189 190 191 192 193
    ( σ1 e2' σ2 efs', prim_step e1 σ1 e2' σ2 efs'  σ1 = σ2  e2 = e2'  [] = efs') 
     WP e2 @ p; E {{ Φ }}  WP e1 @ p; E {{ Φ }}.
  Proof.
    intros. rewrite -(wp_lift_pure_det_step e1 e2 []) ?big_sepL_nil ?right_id; eauto.
  Qed.
194 195 196 197 198
End lifting.

Section ectx_lifting.
  Import ectx_language.
  Context {expr val ectx state} {Λ : EctxLanguage expr val ectx state}.
199
  Context `{ownPG (ectx_lang expr) Σ} {Hinh : Inhabited state}.
200
  Implicit Types p : bool.
201 202 203 204
  Implicit Types Φ : val  iProp Σ.
  Implicit Types e : expr.
  Hint Resolve head_prim_reducible head_reducible_prim_step.

205 206
  Lemma ownP_lift_head_step E Φ e1 :
    to_val e1 = None 
207 208
    (|={E,}=>  σ1, head_reducible e1 σ1   ownP σ1 
        e2 σ2 efs, head_step e1 σ1 e2 σ2 efs - ownP σ2
209 210
            ={,E}= WP e2 @ E {{ Φ }}  [ list] ef  efs, WP ef {{ _, True }})
     WP e1 @ E {{ Φ }}.
211
  Proof.
212
    iIntros (?) "H". iApply ownP_lift_step; first done.
213
    iMod "H" as (σ1 ?) "[Hσ1 Hwp]". iModIntro. iExists σ1.
214
    iSplit; first by eauto. iFrame. iNext. iIntros (e2 σ2 efs) "% ?".
215
    iApply ("Hwp" with "[]"); eauto.
216 217
  Qed.

218 219 220 221 222 223 224 225 226 227 228 229 230 231
  (* PDS: Discard *)
  Lemma ownP_strong_lift_head_step p E Φ e1 :
    to_val e1 = None 
    (|={E,}=>  σ1, if p then head_reducible e1 σ1 else True   ownP σ1 
        e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs - ownP σ2
            ={,E}= WP e2 @ p; E {{ Φ }}  [ list] ef  efs, WP ef @ p; {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
  Proof.
    iIntros (?) "H"; iApply ownP_lift_step; first done.
    iMod "H" as (σ1) "(%&Hσ1&Hwp)". iModIntro. iExists σ1.
    iSplit; first by destruct p; eauto. by iFrame.
  Qed.

  Lemma ownP_lift_pure_head_step E Φ e1 :
232 233 234
    ( σ1, head_reducible e1 σ1) 
    ( σ1 e2 σ2 efs, head_step e1 σ1 e2 σ2 efs  σ1 = σ2) 
    (  e2 efs σ, head_step e1 σ e2 σ efs 
235 236 237 238 239 240 241 242 243 244 245 246 247 248
      WP e2 @ E {{ Φ }}  [ list] ef  efs, WP ef {{ _, True }})
     WP e1 @ E {{ Φ }}.
  Proof using Hinh.
    iIntros (??) "H". iApply ownP_lift_pure_step;
      simpl; eauto using (reducible_not_val _ inhabitant).
    iNext. iIntros (????). iApply "H"; eauto.
  Qed.

  (* PDS: Discard. *)
  Lemma ownP_strong_lift_pure_head_step p E Φ e1 :
    to_val e1 = None 
    ( σ1, if p then head_reducible e1 σ1 else True) 
    ( σ1 e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs  σ1 = σ2) 
    (  e2 efs σ, prim_step e1 σ e2 σ efs 
249 250
      WP e2 @ p; E {{ Φ }}  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
251
  Proof using Hinh.
252 253
    iIntros (???) "H". iApply ownP_lift_pure_step; eauto.
    by destruct p; eauto.
254 255
  Qed.

256
  Lemma ownP_lift_atomic_head_step {E Φ} e1 σ1 :
257 258 259
    head_reducible e1 σ1 
     ownP σ1   ( e2 σ2 efs,
    head_step e1 σ1 e2 σ2 efs - ownP σ2 -
260 261 262 263 264 265 266 267 268 269 270 271 272 273
      default False (to_val e2) Φ  [ list] ef  efs, WP ef {{ _, True }})
     WP e1 @ E {{ Φ }}.
  Proof.
    iIntros (?) "[? H]". iApply ownP_lift_atomic_step;
      simpl; eauto using reducible_not_val.
    iFrame. iNext. iIntros (???) "% ?". iApply ("H" with "[]"); eauto.
  Qed.

  (* PDS: Discard. *)
  Lemma ownP_strong_lift_atomic_head_step {p E Φ} e1 σ1 :
    to_val e1 = None 
    (if p then head_reducible e1 σ1 else True) 
     ownP σ1   ( e2 σ2 efs,
    prim_step e1 σ1 e2 σ2 efs - ownP σ2 -
274 275
      default False (to_val e2) Φ  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
276
  Proof.
277 278
    iIntros (??) "[? H]". iApply ownP_lift_atomic_step; eauto; try iFrame.
    by destruct p; eauto.
279 280
  Qed.

281
  Lemma ownP_lift_atomic_det_head_step {E Φ e1} σ1 v2 σ2 efs :
282 283 284
    head_reducible e1 σ1 
    ( e2' σ2' efs', head_step e1 σ1 e2' σ2' efs' 
      σ2 = σ2'  to_val e2' = Some v2  efs = efs') 
285 286 287 288 289 290 291 292 293 294 295
     ownP σ1   (ownP σ2 - Φ v2  [ list] ef  efs, WP ef {{ _, True }})
     WP e1 @ E {{ Φ }}.
  Proof.
    by eauto 10 using ownP_lift_atomic_det_step, reducible_not_val.
  Qed.

  Lemma ownP_strong_lift_atomic_det_head_step {p E Φ e1} σ1 v2 σ2 efs :
    to_val e1 = None 
    (if p then head_reducible e1 σ1 else True) 
    ( e2' σ2' efs', prim_step e1 σ1 e2' σ2' efs' 
      σ2 = σ2'  to_val e2' = Some v2  efs = efs') 
296 297
     ownP σ1   (ownP σ2 - Φ v2  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
298 299 300
  Proof.
    by destruct p; eauto 10 using ownP_lift_atomic_det_step.
  Qed.
301

302
  Lemma ownP_lift_atomic_det_head_step_no_fork {E e1} σ1 v2 σ2 :
303 304 305
    head_reducible e1 σ1 
    ( e2' σ2' efs', head_step e1 σ1 e2' σ2' efs' 
      σ2 = σ2'  to_val e2' = Some v2  [] = efs') 
306 307 308 309 310 311 312 313 314 315 316
    {{{  ownP σ1 }}} e1 @ E {{{ RET v2; ownP σ2 }}}.
  Proof.
    by eauto 10 using ownP_lift_atomic_det_step_no_fork, reducible_not_val.
  Qed.

  (* PDS: Discard. *)
  Lemma ownP_strong_lift_atomic_det_head_step_no_fork {p E e1} σ1 v2 σ2 :
    to_val e1 = None 
    (if p then head_reducible e1 σ1 else True) 
    ( e2' σ2' efs', prim_step e1 σ1 e2' σ2' efs' 
      σ2 = σ2'  to_val e2' = Some v2  [] = efs') 
317
    {{{  ownP σ1 }}} e1 @ p; E {{{ RET v2; ownP σ2 }}}.
318 319 320 321
  Proof.
    intros ???; apply ownP_lift_atomic_det_step_no_fork; eauto.
    by destruct p; eauto.
  Qed.
322

323
  Lemma ownP_lift_pure_det_head_step {E Φ} e1 e2 efs :
324 325
    ( σ1, head_reducible e1 σ1) 
    ( σ1 e2' σ2 efs', head_step e1 σ1 e2' σ2 efs'  σ1 = σ2  e2 = e2'  efs = efs') 
326 327 328 329 330 331 332 333 334 335 336 337
     (WP e2 @ E {{ Φ }}  [ list] ef  efs, WP ef {{ _, True }})
     WP e1 @ E {{ Φ }}.
  Proof using Hinh.
    intros. rewrite -[(WP e1 @ _ {{ _ }})%I]wp_lift_pure_det_step;
    eauto using (reducible_not_val _ inhabitant).
  Qed.

  (* PDS: Discard. *)
  Lemma ownP_strong_lift_pure_det_head_step {p E Φ} e1 e2 efs :
    to_val e1 = None 
    ( σ1, if p then head_reducible e1 σ1 else True) 
    ( σ1 e2' σ2 efs', prim_step e1 σ1 e2' σ2 efs'  σ1 = σ2  e2 = e2'  efs = efs') 
338 339
     (WP e2 @ p; E {{ Φ }}  [ list] ef  efs, WP ef @ p;  {{ _, True }})
     WP e1 @ p; E {{ Φ }}.
340 341 342 343
  Proof using Hinh.
    iIntros (???) "H"; iApply wp_lift_pure_det_step; eauto.
    by destruct p; eauto.
  Qed.
344

345
  Lemma ownP_lift_pure_det_head_step_no_fork {E Φ} e1 e2 :
346 347 348
    to_val e1 = None 
    ( σ1, head_reducible e1 σ1) 
    ( σ1 e2' σ2 efs', head_step e1 σ1 e2' σ2 efs'  σ1 = σ2  e2 = e2'  [] = efs') 
349 350 351 352 353 354 355 356
     WP e2 @ E {{ Φ }}  WP e1 @ E {{ Φ }}.
  Proof using Hinh. by eauto using ownP_lift_pure_det_step_no_fork. Qed.

  (* PDS: Discard. *)
  Lemma ownP_strong_lift_pure_det_head_step_no_fork {p E Φ} e1 e2 :
    to_val e1 = None 
    ( σ1, if p then head_reducible e1 σ1 else True) 
    ( σ1 e2' σ2 efs', prim_step e1 σ1 e2' σ2 efs'  σ1 = σ2  e2 = e2'  [] = efs') 
357
     WP e2 @ p; E {{ Φ }}  WP e1 @ p; E {{ Φ }}.
358 359 360 361
  Proof using Hinh.
    iIntros (???) "H". iApply ownP_lift_pure_det_step_no_fork; eauto.
    by destruct p; eauto.
  Qed.
362
End ectx_lifting.