From 5b4cd1961fa044e3ffe2f13c884712408d6fa59b Mon Sep 17 00:00:00 2001 From: David Swasey <swasey@mpi-sws.org> Date: Tue, 6 Dec 2016 23:30:26 +0100 Subject: [PATCH] Add progress bit to wp (and slightly generalize wp_step, wp_safe). --- naming.txt | 2 +- theories/heap_lang/adequacy.v | 2 +- theories/heap_lang/lifting.v | 2 +- theories/heap_lang/proofmode.v | 16 +- theories/heap_lang/tactics.v | 13 +- theories/program_logic/adequacy.v | 62 +++--- theories/program_logic/ectx_language.v | 10 + theories/program_logic/ectx_lifting.v | 80 +++++--- theories/program_logic/hoare.v | 118 +++++++----- theories/program_logic/language.v | 4 + theories/program_logic/lifting.v | 55 ++++-- theories/program_logic/ownp.v | 134 +++++++------ theories/program_logic/weakestpre.v | 251 +++++++++++++++++-------- theories/tests/heap_lang.v | 2 +- theories/tests/ipm_paper.v | 2 +- 15 files changed, 482 insertions(+), 271 deletions(-) diff --git a/naming.txt b/naming.txt index 191c1664e..056cad643 100644 --- a/naming.txt +++ b/naming.txt @@ -14,7 +14,7 @@ l m : iGst = ghost state n o -p +p : progress bits q r : iRes = resources s : state (STSs) diff --git a/theories/heap_lang/adequacy.v b/theories/heap_lang/adequacy.v index fa3bc513f..a9b9a2434 100644 --- a/theories/heap_lang/adequacy.v +++ b/theories/heap_lang/adequacy.v @@ -16,7 +16,7 @@ Proof. solve_inG. Qed. Definition heap_adequacy Σ `{heapPreG Σ} e σ φ : (∀ `{heapG Σ}, WP e {{ v, ⌜φ v⌠}}%I) → - adequate e σ φ. + adequate true e σ φ. Proof. intros Hwp; eapply (wp_adequacy _ _); iIntros (?) "". iMod (own_alloc (â— to_gen_heap σ)) as (γ) "Hh". diff --git a/theories/heap_lang/lifting.v b/theories/heap_lang/lifting.v index 46c2aeb8b..7a99bec99 100644 --- a/theories/heap_lang/lifting.v +++ b/theories/heap_lang/lifting.v @@ -76,7 +76,7 @@ Lemma wp_fork E e Φ : â–· Φ (LitV LitUnit) ∗ â–· WP e {{ _, True }} ⊢ WP Fork e @ E {{ Φ }}. Proof. rewrite -(wp_lift_pure_det_head_step (Fork e) (Lit LitUnit) [e]) //=; eauto. - - by rewrite -step_fupd_intro // later_sep -(wp_value _ _ (Lit _)) // right_id. + - by rewrite -step_fupd_intro // later_sep -(wp_value _ _ _ (Lit _)) // right_id. - intros; inv_head_step; eauto. Qed. diff --git a/theories/heap_lang/proofmode.v b/theories/heap_lang/proofmode.v index 677aa6063..919fbf058 100644 --- a/theories/heap_lang/proofmode.v +++ b/theories/heap_lang/proofmode.v @@ -27,7 +27,7 @@ Ltac wp_value_head := eapply tac_wp_value; [apply _|lazy beta]. Tactic Notation "wp_pure" open_constr(efoc) := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => reshape_expr e ltac:(fun K e' => + | |- envs_entails _ (wp true ?E ?e ?Q) => reshape_expr e ltac:(fun K e' => unify e' efoc; eapply (tac_wp_pure K); [simpl; apply _ (* PureExec *) @@ -66,7 +66,7 @@ Ltac wp_bind_core K := Tactic Notation "wp_bind" open_constr(efoc) := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => reshape_expr e ltac:(fun K e' => unify e' efoc; wp_bind_core K) || fail "wp_bind: cannot find" efoc "in" e | _ => fail "wp_bind: not a 'wp'" @@ -151,7 +151,7 @@ End heap. Tactic Notation "wp_apply" open_constr(lem) := iPoseProofCore lem as false true (fun H => lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => reshape_expr e ltac:(fun K e' => wp_bind_core K; iApplyHyp H; try iNext; simpl) || lazymatch iTypeOf H with @@ -163,7 +163,7 @@ Tactic Notation "wp_apply" open_constr(lem) := Tactic Notation "wp_alloc" ident(l) "as" constr(H) := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => first [reshape_expr e ltac:(fun K e' => eapply (tac_wp_alloc _ _ _ H K); [apply _|..]) @@ -182,7 +182,7 @@ Tactic Notation "wp_alloc" ident(l) := Tactic Notation "wp_load" := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => first [reshape_expr e ltac:(fun K e' => eapply (tac_wp_load _ _ _ _ K)) |fail 1 "wp_load: cannot find 'Load' in" e]; @@ -196,7 +196,7 @@ Tactic Notation "wp_load" := Tactic Notation "wp_store" := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => first [reshape_expr e ltac:(fun K e' => eapply (tac_wp_store _ _ _ _ _ K); [apply _|..]) @@ -212,7 +212,7 @@ Tactic Notation "wp_store" := Tactic Notation "wp_cas_fail" := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => first [reshape_expr e ltac:(fun K e' => eapply (tac_wp_cas_fail _ _ _ _ K); [apply _|apply _|..]) @@ -228,7 +228,7 @@ Tactic Notation "wp_cas_fail" := Tactic Notation "wp_cas_suc" := iStartProof; lazymatch goal with - | |- envs_entails _ (wp ?E ?e ?Q) => + | |- envs_entails _ (wp true ?E ?e ?Q) => first [reshape_expr e ltac:(fun K e' => eapply (tac_wp_cas_suc _ _ _ _ _ K); [apply _|apply _|..]) diff --git a/theories/heap_lang/tactics.v b/theories/heap_lang/tactics.v index 1198fb520..6cfa3e1df 100644 --- a/theories/heap_lang/tactics.v +++ b/theories/heap_lang/tactics.v @@ -187,11 +187,10 @@ Definition is_atomic (e : expr) := | App (Rec _ _ (Lit _)) (Lit _) => true | _ => false end. -Lemma is_atomic_correct e : is_atomic e → Atomic (to_expr e). +Lemma is_atomic_correct e : is_atomic e → StronglyAtomic (to_expr e). Proof. - intros He. apply ectx_language_atomic. - - intros σ e' σ' ef Hstep; simpl in *. - apply language.val_irreducible; revert Hstep. + intros He. apply ectx_language_strongly_atomic. + - intros σ e' σ' ef Hstep; simpl in *. revert Hstep. destruct e=> //=; repeat (simplify_eq/=; case_match=>//); inversion 1; simplify_eq/=; rewrite ?to_of_val; eauto. unfold subst'; repeat (simplify_eq/=; case_match=>//); eauto. @@ -227,11 +226,11 @@ Hint Extern 10 (AsVal _) => solve_as_val : typeclass_instances. Ltac solve_atomic := match goal with - | |- Atomic ?e => - let e' := W.of_expr e in change (Atomic (W.to_expr e')); + | |- StronglyAtomic ?e => + let e' := W.of_expr e in change (StronglyAtomic (W.to_expr e')); apply W.is_atomic_correct; vm_compute; exact I end. -Hint Extern 10 (Atomic _) => solve_atomic : typeclass_instances. +Hint Extern 10 (StronglyAtomic _) => solve_atomic : typeclass_instances. (** Substitution *) Ltac simpl_subst := diff --git a/theories/program_logic/adequacy.v b/theories/program_logic/adequacy.v index 8d6f9a85b..f1ca93587 100644 --- a/theories/program_logic/adequacy.v +++ b/theories/program_logic/adequacy.v @@ -34,23 +34,24 @@ Proof. Qed. (* Program logic adequacy *) -Record adequate {Λ} (e1 : expr Λ) (σ1 : state Λ) (φ : val Λ → Prop) := { +Record adequate {Λ} (p : bool) (e1 : expr Λ) (σ1 : state Λ) (φ : val Λ → Prop) := { adequate_result t2 σ2 v2 : rtc step ([e1], σ1) (of_val v2 :: t2, σ2) → φ v2; adequate_safe t2 σ2 e2 : + p → rtc step ([e1], σ1) (t2, σ2) → - e2 ∈ t2 → (is_Some (to_val e2) ∨ reducible e2 σ2) + e2 ∈ t2 → progressive e2 σ2 }. Theorem adequate_tp_safe {Λ} (e1 : expr Λ) t2 σ1 σ2 φ : - adequate e1 σ1 φ → + adequate true e1 σ1 φ → rtc step ([e1], σ1) (t2, σ2) → Forall (λ e, is_Some (to_val e)) t2 ∨ ∃ t3 σ3, step (t2, σ2) (t3, σ3). Proof. intros Had ?. destruct (decide (Forall (λ e, is_Some (to_val e)) t2)) as [|Ht2]; [by left|]. apply (not_Forall_Exists _), Exists_exists in Ht2; destruct Ht2 as (e2&?&He2). - destruct (adequate_safe e1 σ1 φ Had t2 σ2 e2) as [?|(e3&σ3&efs&?)]; + destruct (adequate_safe true e1 σ1 φ Had t2 σ2 e2) as [?|(e3&σ3&efs&?)]; rewrite ?eq_None_not_Some; auto. { exfalso. eauto. } destruct (elem_of_list_split t2 e2) as (t2'&t2''&->); auto. @@ -58,19 +59,22 @@ Proof. Qed. Section adequacy. -Context `{irisG Λ Σ}. +Context `{irisG Λ Σ} (p : bool). Implicit Types e : expr Λ. Implicit Types P Q : iProp Σ. Implicit Types Φ : val Λ → iProp Σ. Implicit Types Φs : list (val Λ → iProp Σ). -Notation world σ := (wsat ∗ ownE ⊤ ∗ state_interp σ)%I. +Notation world' E σ := (wsat ∗ ownE E ∗ state_interp σ)%I. +Notation world σ := (world' ⊤ σ). -Notation wptp t := ([∗ list] ef ∈ t, WP ef {{ _, True }})%I. +Notation wp' E e Φ := (WP e @ p; E {{ Φ }})%I. +Notation wp e Φ := (wp' ⊤ e Φ). +Notation wptp t := ([∗ list] ef ∈ t, WP ef @ p; ⊤ {{ _, True }})%I. -Lemma wp_step e1 σ1 e2 σ2 efs Φ : +Lemma wp_step E e1 σ1 e2 σ2 efs Φ : prim_step e1 σ1 e2 σ2 efs → - world σ1 ∗ WP e1 {{ Φ }} ==∗ â–· |==> â—‡ (world σ2 ∗ WP e2 {{ Φ }} ∗ wptp efs). + world' E σ1 ∗ wp' E e1 Φ ==∗ â–· |==> â—‡ (world' E σ2 ∗ wp' E e2 Φ ∗ wptp efs). Proof. rewrite {1}wp_unfold /wp_pre. iIntros (?) "[(Hw & HE & Hσ) H]". rewrite (val_stuck e1 σ1 e2 σ2 efs) // fupd_eq /fupd_def. @@ -81,8 +85,8 @@ Qed. Lemma wptp_step e1 t1 t2 σ1 σ2 Φ : step (e1 :: t1,σ1) (t2, σ2) → - world σ1 ∗ WP e1 {{ Φ }} ∗ wptp t1 - ==∗ ∃ e2 t2', ⌜t2 = e2 :: t2'⌠∗ â–· |==> â—‡ (world σ2 ∗ WP e2 {{ Φ }} ∗ wptp t2'). + world σ1 ∗ wp e1 Φ ∗ wptp t1 + ==∗ ∃ e2 t2', ⌜t2 = e2 :: t2'⌠∗ â–· |==> â—‡ (world σ2 ∗ wp e2 Φ ∗ wptp t2'). Proof. iIntros (Hstep) "(HW & He & Ht)". destruct Hstep as [e1' σ1' e2' σ2' efs [|? t1'] t2' ?? Hstep]; simplify_eq/=. @@ -95,9 +99,9 @@ Qed. Lemma wptp_steps n e1 t1 t2 σ1 σ2 Φ : nsteps step n (e1 :: t1, σ1) (t2, σ2) → - world σ1 ∗ WP e1 {{ Φ }} ∗ wptp t1 ⊢ + world σ1 ∗ wp e1 Φ ∗ wptp t1 ⊢ Nat.iter (S n) (λ P, |==> â–· P) (∃ e2 t2', - ⌜t2 = e2 :: t2'⌠∗ world σ2 ∗ WP e2 {{ Φ }} ∗ wptp t2'). + ⌜t2 = e2 :: t2'⌠∗ world σ2 ∗ wp e2 Φ ∗ wptp t2'). Proof. revert e1 t1 t2 σ1 σ2; simpl; induction n as [|n IH]=> e1 t1 t2 σ1 σ2 /=. { inversion_clear 1; iIntros "?"; eauto 10. } @@ -121,7 +125,7 @@ Qed. Lemma wptp_result n e1 t1 v2 t2 σ1 σ2 φ : nsteps step n (e1 :: t1, σ1) (of_val v2 :: t2, σ2) → - world σ1 ∗ WP e1 {{ v, ⌜φ v⌠}} ∗ wptp t1 ⊢ â–·^(S (S n)) ⌜φ v2âŒ. + world σ1 ∗ wp e1 (λ v, ⌜φ v⌠) ∗ wptp t1 ⊢ â–·^(S (S n)) ⌜φ v2âŒ. Proof. intros. rewrite wptp_steps // laterN_later. apply: bupd_iter_laterN_mono. iDestruct 1 as (e2 t2' ?) "((Hw & HE & _) & H & _)"; simplify_eq. @@ -129,18 +133,20 @@ Proof. iMod ("H" with "[Hw HE]") as ">(_ & _ & $)"; iFrame; auto. Qed. -Lemma wp_safe e σ Φ : - world σ -∗ WP e {{ Φ }} ==∗ â–· ⌜is_Some (to_val e) ∨ reducible e σâŒ. +Lemma wp_safe E e σ Φ : + world' E σ -∗ wp' E e Φ ==∗ â–· ⌜if p then progressive e σ else TrueâŒ. Proof. rewrite wp_unfold /wp_pre. iIntros "(Hw&HE&Hσ) H". - destruct (to_val e) as [v|] eqn:?; [eauto 10|]. - rewrite fupd_eq. iMod ("H" with "Hσ [-]") as ">(?&?&%&?)"; eauto 10 with iFrame. + destruct (to_val e) as [v|] eqn:?. + { destruct p; last done. iIntros "!> !> !%". left. by exists v. } + rewrite fupd_eq. iMod ("H" with "Hσ [-]") as ">(?&?&%&?)"; first by iFrame. + destruct p; last done. iIntros "!> !> !%". by right. Qed. Lemma wptp_safe n e1 e2 t1 t2 σ1 σ2 Φ : nsteps step n (e1 :: t1, σ1) (t2, σ2) → e2 ∈ t2 → - world σ1 ∗ WP e1 {{ Φ }} ∗ wptp t1 ⊢ - â–·^(S (S n)) ⌜is_Some (to_val e2) ∨ reducible e2 σ2âŒ. + world σ1 ∗ wp e1 Φ ∗ wptp t1 ⊢ + â–·^(S (S n)) ⌜if p then progressive e2 σ2 else TrueâŒ. Proof. intros ? He2. rewrite wptp_steps // laterN_later. apply: bupd_iter_laterN_mono. iDestruct 1 as (e2' t2' ?) "(Hw & H & Htp)"; simplify_eq. @@ -151,7 +157,7 @@ Qed. Lemma wptp_invariance n e1 e2 t1 t2 σ1 σ2 φ Φ : nsteps step n (e1 :: t1, σ1) (t2, σ2) → - (state_interp σ2 ={⊤,∅}=∗ ⌜φâŒ) ∗ world σ1 ∗ WP e1 {{ Φ }} ∗ wptp t1 + (state_interp σ2 ={⊤,∅}=∗ ⌜φâŒ) ∗ world σ1 ∗ wp e1 Φ ∗ wptp t1 ⊢ â–·^(S (S n)) ⌜φâŒ. Proof. intros ?. rewrite wptp_steps // bupd_iter_frame_l laterN_later. @@ -162,12 +168,12 @@ Proof. Qed. End adequacy. -Theorem wp_adequacy Σ Λ `{invPreG Σ} e σ φ : +Theorem wp_adequacy Σ Λ `{invPreG Σ} p e σ φ : (∀ `{Hinv : invG Σ}, (|={⊤}=> ∃ stateI : state Λ → iProp Σ, let _ : irisG Λ Σ := IrisG _ _ Hinv stateI in - stateI σ ∗ WP e {{ v, ⌜φ v⌠}})%I) → - adequate e σ φ. + stateI σ ∗ WP e @ p; ⊤ {{ v, ⌜φ v⌠}})%I) → + adequate p e σ φ. Proof. intros Hwp; split. - intros t2 σ2 v2 [n ?]%rtc_nsteps. @@ -176,19 +182,19 @@ Proof. rewrite fupd_eq in Hwp; iMod (Hwp with "[$Hw $HE]") as ">(Hw & HE & Hwp)". iDestruct "Hwp" as (Istate) "[HI Hwp]". iApply (@wptp_result _ _ (IrisG _ _ Hinv Istate)); eauto with iFrame. - - intros t2 σ2 e2 [n ?]%rtc_nsteps ?. + - destruct p; last done. intros t2 σ2 e2 _ [n ?]%rtc_nsteps ?. eapply (soundness (M:=iResUR Σ) _ (S (S n))). iMod wsat_alloc as (Hinv) "[Hw HE]". rewrite fupd_eq in Hwp; iMod (Hwp with "[$Hw $HE]") as ">(Hw & HE & Hwp)". iDestruct "Hwp" as (Istate) "[HI Hwp]". - iApply (@wptp_safe _ _ (IrisG _ _ Hinv Istate)); eauto with iFrame. + iApply (@wptp_safe _ _ (IrisG _ _ Hinv Istate) true); eauto with iFrame. Qed. -Theorem wp_invariance Σ Λ `{invPreG Σ} e σ1 t2 σ2 φ : +Theorem wp_invariance Σ Λ `{invPreG Σ} p e σ1 t2 σ2 φ : (∀ `{Hinv : invG Σ}, (|={⊤}=> ∃ stateI : state Λ → iProp Σ, let _ : irisG Λ Σ := IrisG _ _ Hinv stateI in - stateI σ1 ∗ WP e {{ _, True }} ∗ (stateI σ2 ={⊤,∅}=∗ ⌜φâŒ))%I) → + stateI σ1 ∗ WP e @ p; ⊤ {{ _, True }} ∗ (stateI σ2 ={⊤,∅}=∗ ⌜φâŒ))%I) → rtc step ([e], σ1) (t2, σ2) → φ. Proof. diff --git a/theories/program_logic/ectx_language.v b/theories/program_logic/ectx_language.v index d8330354d..af8b796f9 100644 --- a/theories/program_logic/ectx_language.v +++ b/theories/program_logic/ectx_language.v @@ -127,6 +127,16 @@ Section ectx_language. rewrite fill_empty. eapply Hatomic_step. by rewrite fill_empty. Qed. + Lemma ectx_language_strongly_atomic e : + (∀ σ e' σ' efs, head_step e σ e' σ' efs → is_Some (to_val e')) → + sub_values e → + StronglyAtomic e. + Proof. + intros Hatomic_step Hatomic_fill σ e' σ' efs [K e1' e2' -> -> Hstep]. + assert (K = empty_ectx) as -> by eauto 10 using val_stuck. + rewrite fill_empty. eapply Hatomic_step. by rewrite fill_empty. + Qed. + Lemma head_reducible_prim_step e1 σ1 e2 σ2 efs : head_reducible e1 σ1 → prim_step e1 σ1 e2 σ2 efs → diff --git a/theories/program_logic/ectx_lifting.v b/theories/program_logic/ectx_lifting.v index 82275d0f3..4dca79e7f 100644 --- a/theories/program_logic/ectx_lifting.v +++ b/theories/program_logic/ectx_lifting.v @@ -12,61 +12,93 @@ Implicit Types v : val. Implicit Types e : expr. Hint Resolve head_prim_reducible head_reducible_prim_step. -Lemma wp_ectx_bind {E Φ} K e : - WP e @ E {{ v, WP fill K (of_val v) @ E {{ Φ }} }} ⊢ WP fill K e @ E {{ Φ }}. +Definition head_progressive (e : expr) (σ : state) := + is_Some(to_val e) ∨ ∃ K e', e = fill K e' ∧ head_reducible e' σ. + +Lemma progressive_head_progressive e σ : + progressive e σ → head_progressive e σ. +Proof. + case=>[?|Hred]; first by left. + right. move: Hred=> [] e' [] σ' [] efs [] K e1' e2' EQ EQ' Hstep. subst. + exists K, e1'. split; first done. by exists e2', σ', efs. +Qed. +Hint Resolve progressive_head_progressive. + +Lemma wp_ectx_bind {p E e} K Φ : + WP e @ p; E {{ v, WP fill K (of_val v) @ p; E {{ Φ }} }} ⊢ WP fill K e @ p; E {{ Φ }}. Proof. apply: weakestpre.wp_bind. Qed. -Lemma wp_ectx_bind_inv {E Φ} K e : - WP fill K e @ E {{ Φ }} ⊢ WP e @ E {{ v, WP fill K (of_val v) @ E {{ Φ }} }}. +Lemma wp_ectx_bind_inv {p E Φ} K e : + WP fill K e @ p; E {{ Φ }} ⊢ WP e @ p; E {{ v, WP fill K (of_val v) @ p; E {{ Φ }} }}. Proof. apply: weakestpre.wp_bind_inv. Qed. -Lemma wp_lift_head_step {E Φ} e1 : +Lemma wp_lift_head_step {p E Φ} e1 : to_val e1 = None → (∀ σ1, state_interp σ1 ={E,∅}=∗ ⌜head_reducible e1 σ1⌠∗ â–· ∀ e2 σ2 efs, ⌜head_step e1 σ1 e2 σ2 efs⌠={∅,E}=∗ - state_interp σ2 ∗ WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + state_interp σ2 ∗ WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros (?) "H". iApply (wp_lift_step E)=>//. iIntros (σ1) "Hσ". + iIntros (?) "H". iApply wp_lift_step=>//. iIntros (σ1) "Hσ". iMod ("H" $! σ1 with "Hσ") as "[% H]"; iModIntro. iSplit; first by eauto. iNext. iIntros (e2 σ2 efs) "%". iApply "H". by eauto. Qed. -Lemma wp_lift_pure_head_step {E E' Φ} e1 : +Lemma wp_lift_head_stuck E Φ e : + to_val e = None → + (∀ σ, state_interp σ ={E,∅}=∗ ⌜¬ head_progressive e σâŒ) + ⊢ WP e @ E ?{{ Φ }}. +Proof. + iIntros (?) "H". iApply wp_lift_stuck; first done. + iIntros (σ) "Hσ". iMod ("H" $! _ with "Hσ") as "%". iModIntro. by auto. +Qed. + +Lemma wp_lift_pure_head_step {p E E' Φ} e1 : (∀ σ1, head_reducible e1 σ1) → (∀ σ1 e2 σ2 efs, head_step e1 σ1 e2 σ2 efs → σ1 = σ2) → (|={E,E'}â–·=> ∀ e2 efs σ, ⌜head_step e1 σ e2 σ efs⌠→ - WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof using Hinh. iIntros (??) "H". iApply wp_lift_pure_step; eauto. iApply (step_fupd_wand with "H"); iIntros "H". iIntros (????). iApply "H"; eauto. Qed. -Lemma wp_lift_atomic_head_step {E Φ} e1 : +Lemma wp_lift_pure_head_stuck `{Inhabited state} E Φ e : + to_val e = None → + (∀ K e1 σ1 e2 σ2 efs, e = fill K e1 → ¬ head_step e1 σ1 e2 σ2 efs) → + WP e @ E ?{{ Φ }}%I. +Proof. + iIntros (Hnv Hnstep). iApply wp_lift_head_stuck; first done. + iIntros (σ) "_". iMod (fupd_intro_mask' E ∅) as "_"; first set_solver. + iModIntro. iPureIntro. case; first by rewrite Hnv; case. + move=>[] K [] e1 [] Hfill [] e2 [] σ2 [] efs /= Hstep. exact: Hnstep. +Qed. + +Lemma wp_lift_atomic_head_step {p E Φ} e1 : to_val e1 = None → (∀ σ1, state_interp σ1 ={E}=∗ ⌜head_reducible e1 σ1⌠∗ â–· ∀ e2 σ2 efs, ⌜head_step e1 σ1 e2 σ2 efs⌠={E}=∗ state_interp σ2 ∗ - default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. iIntros (?) "H". iApply wp_lift_atomic_step; eauto. iIntros (σ1) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "[% H]"; iModIntro. iSplit; first by eauto. iNext. iIntros (e2 σ2 efs) "%". iApply "H"; auto. Qed. -Lemma wp_lift_atomic_head_step_no_fork {E Φ} e1 : +Lemma wp_lift_atomic_head_step_no_fork {p E Φ} e1 : to_val e1 = None → (∀ σ1, state_interp σ1 ={E}=∗ ⌜head_reducible e1 σ1⌠∗ â–· ∀ e2 σ2 efs, ⌜head_step e1 σ1 e2 σ2 efs⌠={E}=∗ ⌜efs = []⌠∗ state_interp σ2 ∗ default False (to_val e2) Φ) - ⊢ WP e1 @ E {{ Φ }}. + ⊢ WP e1 @ p; E {{ Φ }}. Proof. iIntros (?) "H". iApply wp_lift_atomic_head_step; eauto. iIntros (σ1) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "[$ H]"; iModIntro. @@ -74,32 +106,32 @@ Proof. iMod ("H" $! v2 σ2 efs with "[# //]") as "(% & $ & $)"; subst; auto. Qed. -Lemma wp_lift_pure_det_head_step {E E' Φ} e1 e2 efs : +Lemma wp_lift_pure_det_head_step {p E E' Φ} e1 e2 efs : (∀ σ1, head_reducible e1 σ1) → (∀ σ1 e2' σ2 efs', head_step e1 σ1 e2' σ2 efs' → σ1 = σ2 ∧ e2 = e2' ∧ efs = efs') → - (|={E,E'}â–·=> WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + (|={E,E'}â–·=> WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof using Hinh. eauto using wp_lift_pure_det_step. Qed. -Lemma wp_lift_pure_det_head_step_no_fork {E E' Φ} e1 e2 : +Lemma wp_lift_pure_det_head_step_no_fork {p E E' Φ} e1 e2 : 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') → - (|={E,E'}â–·=> WP e2 @ E {{ Φ }}) ⊢ WP e1 @ E {{ Φ }}. + (|={E,E'}â–·=> WP e2 @ p; E {{ Φ }}) ⊢ WP e1 @ p; E {{ Φ }}. Proof using Hinh. intros. rewrite -(wp_lift_pure_det_step e1 e2 []) /= ?right_id; eauto. Qed. -Lemma wp_lift_pure_det_head_step_no_fork' {E Φ} e1 e2 : +Lemma wp_lift_pure_det_head_step_no_fork' {p E Φ} e1 e2 : 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') → - â–· WP e2 @ E {{ Φ }} ⊢ WP e1 @ E {{ Φ }}. + â–· WP e2 @ p; E {{ Φ }} ⊢ WP e1 @ p; E {{ Φ }}. Proof using Hinh. - intros. rewrite -[(WP e1 @ _ {{ _ }})%I]wp_lift_pure_det_head_step_no_fork //. + intros. rewrite -[(WP e1 @ _; _ {{ _ }})%I]wp_lift_pure_det_head_step_no_fork //. rewrite -step_fupd_intro //. Qed. End wp. diff --git a/theories/program_logic/hoare.v b/theories/program_logic/hoare.v index cb110957a..b3a8a4677 100644 --- a/theories/program_logic/hoare.v +++ b/theories/program_logic/hoare.v @@ -3,24 +3,42 @@ From iris.base_logic.lib Require Export viewshifts. From iris.proofmode Require Import tactics. Set Default Proof Using "Type". -Definition ht `{irisG Λ Σ} (E : coPset) (P : iProp Σ) +Definition ht `{irisG Λ Σ} (p : bool) (E : coPset) (P : iProp Σ) (e : expr Λ) (Φ : val Λ → iProp Σ) : iProp Σ := - (â–¡ (P -∗ WP e @ E {{ Φ }}))%I. -Instance: Params (@ht) 4. + (â–¡ (P -∗ WP e @ p; E {{ Φ }}))%I. +Instance: Params (@ht) 5. -Notation "{{ P } } e @ E {{ Φ } }" := (ht E P%I e%E Φ%I) +Notation "{{ P } } e @ p ; E {{ Φ } }" := (ht p E P%I e%E Φ%I) + (at level 20, P, e, Φ at level 200, + format "{{ P } } e @ p ; E {{ Φ } }") : C_scope. +Notation "{{ P } } e @ E {{ Φ } }" := (ht true E P%I e%E Φ%I) (at level 20, P, e, Φ at level 200, format "{{ P } } e @ E {{ Φ } }") : C_scope. -Notation "{{ P } } e {{ Φ } }" := (ht ⊤ P%I e%E Φ%I) +Notation "{{ P } } e @ E ? {{ Φ } }" := (ht false E P%I e%E Φ%I) + (at level 20, P, e, Φ at level 200, + format "{{ P } } e @ E ? {{ Φ } }") : C_scope. +Notation "{{ P } } e {{ Φ } }" := (ht true ⊤ P%I e%E Φ%I) (at level 20, P, e, Φ at level 200, format "{{ P } } e {{ Φ } }") : C_scope. +Notation "{{ P } } e ? {{ Φ } }" := (ht false ⊤ P%I e%E Φ%I) + (at level 20, P, e, Φ at level 200, + format "{{ P } } e ? {{ Φ } }") : C_scope. -Notation "{{ P } } e @ E {{ v , Q } }" := (ht E P%I e%E (λ v, Q)%I) +Notation "{{ P } } e @ p ; E {{ v , Q } }" := (ht p E P%I e%E (λ v, Q)%I) + (at level 20, P, e, Q at level 200, + format "{{ P } } e @ p ; E {{ v , Q } }") : C_scope. +Notation "{{ P } } e @ E {{ v , Q } }" := (ht true E P%I e%E (λ v, Q)%I) (at level 20, P, e, Q at level 200, format "{{ P } } e @ E {{ v , Q } }") : C_scope. -Notation "{{ P } } e {{ v , Q } }" := (ht ⊤ P%I e%E (λ v, Q)%I) +Notation "{{ P } } e @ E ? {{ v , Q } }" := (ht false E P%I e%E (λ v, Q)%I) + (at level 20, P, e, Q at level 200, + format "{{ P } } e @ E ? {{ v , Q } }") : C_scope. +Notation "{{ P } } e {{ v , Q } }" := (ht true ⊤ P%I e%E (λ v, Q)%I) (at level 20, P, e, Q at level 200, format "{{ P } } e {{ v , Q } }") : C_scope. +Notation "{{ P } } e ? {{ v , Q } }" := (ht false ⊤ P%I e%E (λ v, Q)%I) + (at level 20, P, e, Q at level 200, + format "{{ P } } e ? {{ v , Q } }") : C_scope. Section hoare. Context `{irisG Λ Σ}. @@ -29,100 +47,106 @@ Implicit Types Φ Ψ : val Λ → iProp Σ. Implicit Types v : val Λ. Import uPred. -Global Instance ht_ne E n : - Proper (dist n ==> eq ==> pointwise_relation _ (dist n) ==> dist n) (ht E). +Global Instance ht_ne p E n : + Proper (dist n ==> eq ==> pointwise_relation _ (dist n) ==> dist n) (ht p E). Proof. solve_proper. Qed. -Global Instance ht_proper E : - Proper ((≡) ==> eq ==> pointwise_relation _ (≡) ==> (≡)) (ht E). +Global Instance ht_proper p E : + Proper ((≡) ==> eq ==> pointwise_relation _ (≡) ==> (≡)) (ht p E). Proof. solve_proper. Qed. -Lemma ht_mono E P P' Φ Φ' e : - (P ⊢ P') → (∀ v, Φ' v ⊢ Φ v) → {{ P' }} e @ E {{ Φ' }} ⊢ {{ P }} e @ E {{ Φ }}. +Lemma ht_mono p E P P' Φ Φ' e : + (P ⊢ P') → (∀ v, Φ' v ⊢ Φ v) → {{ P' }} e @ p; E {{ Φ' }} ⊢ {{ P }} e @ p; E {{ Φ }}. Proof. by intros; apply persistently_mono, wand_mono, wp_mono. Qed. -Global Instance ht_mono' E : - Proper (flip (⊢) ==> eq ==> pointwise_relation _ (⊢) ==> (⊢)) (ht E). +Global Instance ht_mono' p E : + Proper (flip (⊢) ==> eq ==> pointwise_relation _ (⊢) ==> (⊢)) (ht p E). Proof. solve_proper. Qed. -Lemma ht_alt E P Φ e : (P ⊢ WP e @ E {{ Φ }}) → {{ P }} e @ E {{ Φ }}. +Lemma ht_alt p E P Φ e : (P ⊢ WP e @ p; E {{ Φ }}) → {{ P }} e @ p; E {{ Φ }}. Proof. iIntros (Hwp) "!# HP". by iApply Hwp. Qed. -Lemma ht_val E v : {{ True }} of_val v @ E {{ v', ⌜v = v'⌠}}. +Lemma ht_val p E v : {{ True }} of_val v @ p; E {{ v', ⌜v = v'⌠}}. Proof. iIntros "!# _". by iApply wp_value'. Qed. -Lemma ht_vs E P P' Φ Φ' e : - (P ={E}=> P') ∧ {{ P' }} e @ E {{ Φ' }} ∧ (∀ v, Φ' v ={E}=> Φ v) - ⊢ {{ P }} e @ E {{ Φ }}. +Lemma ht_vs p E P P' Φ Φ' e : + (P ={E}=> P') ∧ {{ P' }} e @ p; E {{ Φ' }} ∧ (∀ v, Φ' v ={E}=> Φ v) + ⊢ {{ P }} e @ p; E {{ Φ }}. Proof. iIntros "(#Hvs & #Hwp & #HΦ) !# HP". iMod ("Hvs" with "HP") as "HP". iApply wp_fupd. iApply (wp_wand with "[HP]"); [by iApply "Hwp"|]. iIntros (v) "Hv". by iApply "HΦ". Qed. -Lemma ht_atomic E1 E2 P P' Φ Φ' e : - Atomic e → - (P ={E1,E2}=> P') ∧ {{ P' }} e @ E2 {{ Φ' }} ∧ (∀ v, Φ' v ={E2,E1}=> Φ v) - ⊢ {{ P }} e @ E1 {{ Φ }}. +Lemma ht_atomic p E1 E2 P P' Φ Φ' e : + StronglyAtomic e → + (P ={E1,E2}=> P') ∧ {{ P' }} e @ p; E2 {{ Φ' }} ∧ (∀ v, Φ' v ={E2,E1}=> Φ v) + ⊢ {{ P }} e @ p; E1 {{ Φ }}. Proof. - iIntros (?) "(#Hvs & #Hwp & #HΦ) !# HP". iApply (wp_atomic _ E2); auto. + iIntros (?) "(#Hvs & #Hwp & #HΦ) !# HP". iApply (wp_atomic _ _ E2); auto. iMod ("Hvs" with "HP") as "HP". iModIntro. iApply (wp_wand with "[HP]"); [by iApply "Hwp"|]. iIntros (v) "Hv". by iApply "HΦ". Qed. -Lemma ht_bind `{LanguageCtx Λ K} E P Φ Φ' e : - {{ P }} e @ E {{ Φ }} ∧ (∀ v, {{ Φ v }} K (of_val v) @ E {{ Φ' }}) - ⊢ {{ P }} K e @ E {{ Φ' }}. +Lemma ht_bind `{LanguageCtx Λ K} p E P Φ Φ' e : + {{ P }} e @ p; E {{ Φ }} ∧ (∀ v, {{ Φ v }} K (of_val v) @ p; E {{ Φ' }}) + ⊢ {{ P }} K e @ p; E {{ Φ' }}. Proof. iIntros "[#Hwpe #HwpK] !# HP". iApply wp_bind. iApply (wp_wand with "[HP]"); [by iApply "Hwpe"|]. iIntros (v) "Hv". by iApply "HwpK". Qed. -Lemma ht_mask_weaken E1 E2 P Φ e : - E1 ⊆ E2 → {{ P }} e @ E1 {{ Φ }} ⊢ {{ P }} e @ E2 {{ Φ }}. +Lemma ht_forget_progress E P Φ e : + {{ P }} e @ E {{ Φ }} ⊢ {{ P }} e @ E ?{{ Φ }}. +Proof. + by iIntros "#Hwp !# ?"; iApply wp_forget_progress; iApply "Hwp". +Qed. + +Lemma ht_mask_weaken p E1 E2 P Φ e : + E1 ⊆ E2 → {{ P }} e @ p; E1 {{ Φ }} ⊢ {{ P }} e @ p; E2 {{ Φ }}. Proof. - iIntros (?) "#Hwp !# HP". iApply (wp_mask_mono E1 E2); try done. + iIntros (?) "#Hwp !# HP". iApply (wp_mask_mono _ E1 E2); try done. by iApply "Hwp". Qed. -Lemma ht_frame_l E P Φ R e : - {{ P }} e @ E {{ Φ }} ⊢ {{ R ∗ P }} e @ E {{ v, R ∗ Φ v }}. +Lemma ht_frame_l p E P Φ R e : + {{ P }} e @ p; E {{ Φ }} ⊢ {{ R ∗ P }} e @ p; E {{ v, R ∗ Φ v }}. Proof. iIntros "#Hwp !# [$ HP]". by iApply "Hwp". Qed. -Lemma ht_frame_r E P Φ R e : - {{ P }} e @ E {{ Φ }} ⊢ {{ P ∗ R }} e @ E {{ v, Φ v ∗ R }}. +Lemma ht_frame_r p E P Φ R e : + {{ P }} e @ p; E {{ Φ }} ⊢ {{ P ∗ R }} e @ p; E {{ v, Φ v ∗ R }}. Proof. iIntros "#Hwp !# [HP $]". by iApply "Hwp". Qed. -Lemma ht_frame_step_l E1 E2 P R1 R2 e Φ : +Lemma ht_frame_step_l p E1 E2 P R1 R2 e Φ : to_val e = None → E2 ⊆ E1 → - (R1 ={E1,E2}=> â–· |={E2,E1}=> R2) ∧ {{ P }} e @ E2 {{ Φ }} - ⊢ {{ R1 ∗ P }} e @ E1 {{ λ v, R2 ∗ Φ v }}. + (R1 ={E1,E2}=> â–· |={E2,E1}=> R2) ∧ {{ P }} e @ p; E2 {{ Φ }} + ⊢ {{ R1 ∗ P }} e @ p; E1 {{ λ v, R2 ∗ Φ v }}. Proof. iIntros (??) "[#Hvs #Hwp] !# [HR HP]". - iApply (wp_frame_step_l E1 E2); try done. + iApply (wp_frame_step_l _ E1 E2); try done. iSplitL "HR"; [by iApply "Hvs"|by iApply "Hwp"]. Qed. -Lemma ht_frame_step_r E1 E2 P R1 R2 e Φ : +Lemma ht_frame_step_r p E1 E2 P R1 R2 e Φ : to_val e = None → E2 ⊆ E1 → - (R1 ={E1,E2}=> â–· |={E2,E1}=> R2) ∧ {{ P }} e @ E2 {{ Φ }} - ⊢ {{ P ∗ R1 }} e @ E1 {{ λ v, Φ v ∗ R2 }}. + (R1 ={E1,E2}=> â–· |={E2,E1}=> R2) ∧ {{ P }} e @ p; E2 {{ Φ }} + ⊢ {{ P ∗ R1 }} e @ p; E1 {{ λ v, Φ v ∗ R2 }}. Proof. iIntros (??) "[#Hvs #Hwp] !# [HP HR]". - iApply (wp_frame_step_r E1 E2); try done. + iApply (wp_frame_step_r _ E1 E2); try done. iSplitR "HR"; [by iApply "Hwp"|by iApply "Hvs"]. Qed. -Lemma ht_frame_step_l' E P R e Φ : +Lemma ht_frame_step_l' p E P R e Φ : to_val e = None → - {{ P }} e @ E {{ Φ }} ⊢ {{ â–· R ∗ P }} e @ E {{ v, R ∗ Φ v }}. + {{ P }} e @ p; E {{ Φ }} ⊢ {{ â–· R ∗ P }} e @ p; E {{ v, R ∗ Φ v }}. Proof. iIntros (?) "#Hwp !# [HR HP]". iApply wp_frame_step_l'; try done. iFrame "HR". by iApply "Hwp". Qed. -Lemma ht_frame_step_r' E P Φ R e : +Lemma ht_frame_step_r' p E P Φ R e : to_val e = None → - {{ P }} e @ E {{ Φ }} ⊢ {{ P ∗ â–· R }} e @ E {{ v, Φ v ∗ R }}. + {{ P }} e @ p; E {{ Φ }} ⊢ {{ P ∗ â–· R }} e @ p; E {{ v, Φ v ∗ R }}. Proof. iIntros (?) "#Hwp !# [HP HR]". iApply wp_frame_step_r'; try done. iFrame "HR". by iApply "Hwp". diff --git a/theories/program_logic/language.v b/theories/program_logic/language.v index d600c5e75..af3357fe1 100644 --- a/theories/program_logic/language.v +++ b/theories/program_logic/language.v @@ -51,6 +51,8 @@ Section language. ∃ e' σ' efs, prim_step e σ e' σ' efs. Definition irreducible (e : expr Λ) (σ : state Λ) := ∀ e' σ' efs, ¬prim_step e σ e' σ' efs. + Definition progressive (e : expr Λ) (σ : state Λ) := + is_Some (to_val e) ∨ reducible e σ. (* This (weak) form of atomicity is enough to open invariants when WP ensures safety, i.e., programs never can get stuck. We have an example in @@ -82,6 +84,8 @@ Section language. Proof. unfold reducible, irreducible. naive_solver. Qed. Lemma reducible_not_val e σ : reducible e σ → to_val e = None. Proof. intros (?&?&?&?); eauto using val_stuck. Qed. + Lemma val_irreducible e σ : is_Some (to_val e) → irreducible e σ. + Proof. intros [??] ??? ?%val_stuck. by destruct (to_val e). Qed. Global Instance of_val_inj : Inj (=) (=) (@of_val Λ). Proof. by intros v v' Hv; apply (inj Some); rewrite -!to_of_val Hv. Qed. diff --git a/theories/program_logic/lifting.v b/theories/program_logic/lifting.v index 41edd498d..c013ded44 100644 --- a/theories/program_logic/lifting.v +++ b/theories/program_logic/lifting.v @@ -11,22 +11,36 @@ Implicit Types σ : state Λ. Implicit Types P Q : iProp Σ. Implicit Types Φ : val Λ → iProp Σ. -Lemma wp_lift_step E Φ e1 : +Lemma wp_lift_step p E Φ e1 : to_val e1 = None → (∀ σ1, state_interp σ1 ={E,∅}=∗ ⌜reducible e1 σ1⌠∗ â–· ∀ e2 σ2 efs, ⌜prim_step e1 σ1 e2 σ2 efs⌠={∅,E}=∗ - state_interp σ2 ∗ WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. -Proof. by rewrite wp_unfold /wp_pre=> ->. Qed. + state_interp σ2 ∗ WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. +Proof. + rewrite wp_unfold /wp_pre=>->. iIntros "H" (σ1) "Hσ". + iMod ("H" with "Hσ") as "(%&?)". iModIntro. iSplit. by destruct p. done. +Qed. + +Lemma wp_lift_stuck E Φ e : + to_val e = None → + (∀ σ, state_interp σ ={E,∅}=∗ ⌜¬ progressive e σâŒ) + ⊢ WP e @ E ?{{ Φ }}. +Proof. + rewrite wp_unfold /wp_pre=>->. iIntros "H" (σ1) "Hσ". + iMod ("H" with "Hσ") as "Hstuck". iDestruct "Hstuck" as %Hstuck. + iModIntro. iSplit; first done. iIntros "!>" (e2 σ2 efs) "%". exfalso. + apply Hstuck. right. by exists e2, σ2, efs. +Qed. (** Derived lifting lemmas. *) -Lemma wp_lift_pure_step `{Inhabited (state Λ)} E E' Φ e1 : +Lemma wp_lift_pure_step `{Inhabited (state Λ)} p E E' Φ e1 : (∀ σ1, reducible e1 σ1) → (∀ σ1 e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs → σ1 = σ2) → (|={E,E'}â–·=> ∀ e2 efs σ, ⌜prim_step e1 σ e2 σ efs⌠→ - WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. iIntros (Hsafe Hstep) "H". iApply wp_lift_step. { eapply reducible_not_val, (Hsafe inhabitant). } @@ -37,18 +51,29 @@ Proof. iMod "Hclose" as "_". iFrame "Hσ". iMod "H". iApply "H"; auto. Qed. +Lemma wp_lift_pure_stuck `{Inhabited (state Λ)} E Φ e : + (∀ σ, ¬ progressive e σ) → + True ⊢ WP e @ E ?{{ Φ }}. +Proof. + iIntros (Hstuck) "_". iApply wp_lift_stuck. + - destruct(to_val e) as [v|] eqn:He; last done. + exfalso. apply (Hstuck inhabitant). left. by exists v. + - iIntros (σ) "_". iMod (fupd_intro_mask' E ∅) as "_". + by set_solver. by auto. +Qed. + (* Atomic steps don't need any mask-changing business here, one can use the generic lemmas here. *) -Lemma wp_lift_atomic_step {E Φ} e1 : +Lemma wp_lift_atomic_step {p E Φ} e1 : to_val e1 = None → (∀ σ1, state_interp σ1 ={E}=∗ ⌜reducible e1 σ1⌠∗ â–· ∀ e2 σ2 efs, ⌜prim_step e1 σ1 e2 σ2 efs⌠={E}=∗ state_interp σ2 ∗ - default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros (?) "H". iApply (wp_lift_step E _ e1)=>//; iIntros (σ1) "Hσ1". + iIntros (?) "H". iApply (wp_lift_step p E _ e1)=>//; iIntros (σ1) "Hσ1". iMod ("H" $! σ1 with "Hσ1") as "[$ H]". iMod (fupd_intro_mask' E ∅) as "Hclose"; first set_solver. iModIntro; iNext; iIntros (e2 σ2 efs) "%". iMod "Hclose" as "_". @@ -57,13 +82,13 @@ Proof. by iApply wp_value. Qed. -Lemma wp_lift_pure_det_step `{Inhabited (state Λ)} {E E' Φ} e1 e2 efs : +Lemma wp_lift_pure_det_step `{Inhabited (state Λ)} {p E E' Φ} e1 e2 efs : (∀ σ1, reducible e1 σ1) → (∀ σ1 e2' σ2 efs', prim_step e1 σ1 e2' σ2 efs' → σ1 = σ2 ∧ e2 = e2' ∧ efs = efs')→ - (|={E,E'}â–·=> WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + (|={E,E'}â–·=> WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros (? Hpuredet) "H". iApply (wp_lift_pure_step E); try done. + iIntros (? Hpuredet) "H". iApply (wp_lift_pure_step p E); try done. { by intros; eapply Hpuredet. } iApply (step_fupd_wand with "H"); iIntros "H". by iIntros (e' efs' σ (_&->&->)%Hpuredet). diff --git a/theories/program_logic/ownp.v b/theories/program_logic/ownp.v index 1c3a8d3e3..dc9bd83a2 100644 --- a/theories/program_logic/ownp.v +++ b/theories/program_logic/ownp.v @@ -39,9 +39,9 @@ Instance: Params (@ownP) 3. (* Adequacy *) -Theorem ownP_adequacy Σ `{ownPPreG Λ Σ} e σ φ : - (∀ `{ownPG Λ Σ}, ownP σ ⊢ WP e {{ v, ⌜φ v⌠}}) → - adequate e σ φ. +Theorem ownP_adequacy Σ `{ownPPreG Λ Σ} p e σ φ : + (∀ `{ownPG Λ Σ}, ownP σ ⊢ WP e @ p; ⊤ {{ v, ⌜φ v⌠}}) → + adequate p e σ φ. Proof. intros Hwp. apply (wp_adequacy Σ _). iIntros (?) "". iMod (own_alloc (â— (Excl' (σ : leibnizC _)) â‹… â—¯ (Excl' σ))) @@ -50,13 +50,13 @@ Proof. iApply (Hwp (OwnPG _ _ _ _ γσ)). by rewrite /ownP. Qed. -Theorem ownP_invariance Σ `{ownPPreG Λ Σ} e σ1 t2 σ2 φ : +Theorem ownP_invariance Σ `{ownPPreG Λ Σ} p e σ1 t2 σ2 φ : (∀ `{ownPG Λ Σ}, - ownP σ1 ={⊤}=∗ WP e {{ _, True }} ∗ |={⊤,∅}=> ∃ σ', ownP σ' ∧ ⌜φ σ'âŒ) → + ownP σ1 ={⊤}=∗ WP e @ p; ⊤ {{ _, True }} ∗ |={⊤,∅}=> ∃ σ', ownP σ' ∧ ⌜φ σ'âŒ) → rtc step ([e], σ1) (t2, σ2) → φ σ2. Proof. - intros Hwp Hsteps. eapply (wp_invariance Σ Λ e σ1 t2 σ2 _)=> //. + intros Hwp Hsteps. eapply (wp_invariance Σ Λ p e σ1 t2 σ2 _)=> //. iIntros (?) "". iMod (own_alloc (â— (Excl' (σ1 : leibnizC _)) â‹… â—¯ (Excl' σ1))) as (γσ) "[Hσ Hσf]"; first done. iExists (λ σ, own γσ (â— (Excl' (σ:leibnizC _)))). iFrame "Hσ". @@ -78,11 +78,11 @@ Section lifting. Global Instance ownP_timeless σ : Timeless (@ownP (state Λ) Σ _ σ). Proof. rewrite /ownP; apply _. Qed. - Lemma ownP_lift_step E Φ e1 : + Lemma ownP_lift_step p E Φ e1 : (|={E,∅}=> ∃ σ1, ⌜reducible e1 σ1⌠∗ â–· ownP σ1 ∗ â–· ∀ e2 σ2 efs, ⌜prim_step e1 σ1 e2 σ2 efs⌠-∗ ownP σ2 - ={∅,E}=∗ WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + ={∅,E}=∗ WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. iIntros "H". destruct (to_val e1) as [v|] eqn:EQe1. - apply of_to_val in EQe1 as <-. iApply fupd_wp. @@ -99,12 +99,26 @@ Section lifting. iFrame "Hσ". iApply ("H" with "[]"); eauto. Qed. - Lemma ownP_lift_pure_step `{Inhabited (state Λ)} E Φ e1 : + 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σ". + iMod "H" as (σ1') "(% & >Hσf)"; rewrite /ownP. + by iDestruct (own_valid_2 with "Hσ Hσf") + as %[->%Excl_included%leibniz_equiv _]%auth_valid_discrete_2. + Qed. + + Lemma ownP_lift_pure_step `{Inhabited (state Λ)} p E Φ e1 : (∀ σ1, reducible e1 σ1) → (∀ σ1 e2 σ2 efs, prim_step e1 σ1 e2 σ2 efs → σ1 = σ2) → (â–· ∀ e2 efs σ, ⌜prim_step e1 σ e2 σ efs⌠→ - WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. iIntros (Hsafe Hstep) "H". iApply wp_lift_step. { eapply reducible_not_val, (Hsafe inhabitant). } @@ -115,13 +129,13 @@ Section lifting. Qed. (** Derived lifting lemmas. *) - Lemma ownP_lift_atomic_step {E Φ} e1 σ1 : + Lemma ownP_lift_atomic_step {p E Φ} e1 σ1 : reducible e1 σ1 → (â–· ownP σ1 ∗ â–· ∀ e2 σ2 efs, ⌜prim_step e1 σ1 e2 σ2 efs⌠-∗ ownP σ2 -∗ - default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros (?) "[Hσ H]". iApply (ownP_lift_step E _ e1). + iIntros (?) "[Hσ H]". iApply ownP_lift_step. iMod (fupd_intro_mask' E ∅) as "Hclose"; first set_solver. iModIntro. iExists σ1. iFrame "Hσ"; iSplit; eauto. iNext; iIntros (e2 σ2 efs) "% Hσ". @@ -130,28 +144,47 @@ Section lifting. iMod "Hclose". iApply wp_value; auto using to_of_val. done. Qed. - Lemma ownP_lift_atomic_det_step {E Φ e1} σ1 v2 σ2 efs : + Lemma ownP_lift_atomic_det_step {p E Φ e1} σ1 v2 σ2 efs : reducible e1 σ1 → (∀ e2' σ2' efs', prim_step e1 σ1 e2' σ2' efs' → σ2 = σ2' ∧ to_val e2' = Some v2 ∧ efs = efs') → â–· ownP σ1 ∗ â–· (ownP σ2 -∗ - Φ v2 ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + Φ v2 ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros (? Hdet) "[Hσ1 Hσ2]". iApply (ownP_lift_atomic_step _ σ1); try done. + 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. rewrite Hval. by iApply "Hσ2". Qed. - Lemma ownP_lift_pure_det_step `{Inhabited (state Λ)} {E Φ} e1 e2 efs : + Lemma ownP_lift_atomic_det_step_no_fork {p E e1} σ1 v2 σ2 : + reducible e1 σ1 → + (∀ 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. + + Lemma ownP_lift_pure_det_step `{Inhabited (state Λ)} {p E Φ} e1 e2 efs : (∀ σ1, reducible e1 σ1) → (∀ σ1 e2' σ2 efs', prim_step e1 σ1 e2' σ2 efs' → σ1 = σ2 ∧ e2 = e2' ∧ efs = efs')→ - â–· (WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + â–· (WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤{{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros (? Hpuredet) "?". iApply (ownP_lift_pure_step E); try done. + iIntros (? Hpuredet) "?". iApply ownP_lift_pure_step; try done. by intros; eapply Hpuredet. iNext. by iIntros (e' efs' σ (_&->&->)%Hpuredet). Qed. + + Lemma ownP_lift_pure_det_step_no_fork `{Inhabited (state Λ)} {p E Φ} e1 e2 : + to_val e1 = None → + (∀ σ1, reducible e1 σ1) → + (∀ σ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. End lifting. Section ectx_lifting. @@ -162,73 +195,66 @@ Section ectx_lifting. Implicit Types e : expr. Hint Resolve head_prim_reducible head_reducible_prim_step. - Lemma ownP_lift_head_step E Φ e1 : + Lemma ownP_lift_head_step p E Φ e1 : (|={E,∅}=> ∃ σ1, ⌜head_reducible e1 σ1⌠∗ â–· ownP σ1 ∗ â–· ∀ e2 σ2 efs, ⌜head_step e1 σ1 e2 σ2 efs⌠-∗ ownP σ2 - ={∅,E}=∗ WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + ={∅,E}=∗ WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤{{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. - iIntros "H". iApply (ownP_lift_step E); try done. + iIntros "H". iApply (ownP_lift_step p E); try done. iMod "H" as (σ1 ?) "[Hσ1 Hwp]". iModIntro. iExists σ1. iSplit; first by eauto. iFrame. iNext. iIntros (e2 σ2 efs) "% ?". iApply ("Hwp" with "[]"); eauto. Qed. - Lemma ownP_lift_pure_head_step E Φ e1 : + Lemma ownP_lift_pure_head_step p E Φ e1 : (∀ σ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⌠→ - WP e2 @ E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof using Hinh. iIntros (??) "H". iApply ownP_lift_pure_step; eauto. iNext. iIntros (????). iApply "H". eauto. Qed. - Lemma ownP_lift_atomic_head_step {E Φ} e1 σ1 : + Lemma ownP_lift_atomic_head_step {p E Φ} e1 σ1 : head_reducible e1 σ1 → â–· ownP σ1 ∗ â–· (∀ e2 σ2 efs, ⌜head_step e1 σ1 e2 σ2 efs⌠-∗ ownP σ2 -∗ - default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + default False (to_val e2) Φ ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. iIntros (?) "[? H]". iApply ownP_lift_atomic_step; eauto. iFrame. iNext. iIntros (???) "% ?". iApply ("H" with "[]"); eauto. Qed. - Lemma ownP_lift_atomic_det_head_step {E Φ e1} σ1 v2 σ2 efs : + Lemma ownP_lift_atomic_det_head_step {p E Φ e1} σ1 v2 σ2 efs : head_reducible e1 σ1 → (∀ e2' σ2' efs', head_step e1 σ1 e2' σ2' efs' → σ2 = σ2' ∧ to_val e2' = Some v2 ∧ efs = efs') → - â–· ownP σ1 ∗ â–· (ownP σ2 -∗ Φ v2 ∗ [∗ list] ef ∈ efs, WP ef {{ _, True }}) - ⊢ WP e1 @ E {{ Φ }}. + â–· ownP σ1 ∗ â–· (ownP σ2 -∗ Φ v2 ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. Proof. eauto using ownP_lift_atomic_det_step. Qed. - Lemma ownP_lift_atomic_det_head_step_no_fork {E e1} σ1 v2 σ2 : + Lemma ownP_lift_atomic_det_head_step_no_fork {p E e1} σ1 v2 σ2 : head_reducible e1 σ1 → (∀ e2' σ2' efs', head_step e1 σ1 e2' σ2' efs' → σ2 = σ2' ∧ to_val e2' = Some v2 ∧ [] = efs') → - {{{ â–· ownP σ1 }}} e1 @ E {{{ RET v2; ownP σ2 }}}. - Proof. - intros. rewrite -(ownP_lift_atomic_det_head_step σ1 v2 σ2 []); [|done..]. - rewrite /= right_id. by apply uPred.wand_intro_r. - Qed. + {{{ â–· ownP σ1 }}} e1 @ p; E {{{ RET v2; ownP σ2 }}}. + Proof. eauto using ownP_lift_atomic_det_step_no_fork. Qed. - Lemma ownP_lift_pure_det_head_step {E Φ} e1 e2 efs : + Lemma ownP_lift_pure_det_head_step {p E Φ} e1 e2 efs : (∀ σ1, head_reducible e1 σ1) → (∀ σ1 e2' σ2 efs', head_step e1 σ1 e2' σ2 efs' → σ1 = σ2 ∧ e2 = e2' ∧ efs = efs') → - â–· (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. - Qed. + â–· (WP e2 @ p; E {{ Φ }} ∗ [∗ list] ef ∈ efs, WP ef @ p; ⊤ {{ _, True }}) + ⊢ WP e1 @ p; E {{ Φ }}. + Proof using Hinh. eauto using ownP_lift_pure_det_step. Qed. - Lemma ownP_lift_pure_det_head_step_no_fork {E Φ} e1 e2 : + Lemma ownP_lift_pure_det_head_step_no_fork {p E Φ} e1 e2 : 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') → - â–· WP e2 @ E {{ Φ }} ⊢ WP e1 @ E {{ Φ }}. - Proof using Hinh. - intros. rewrite -(wp_lift_pure_det_step e1 e2 []) /= ?right_id; eauto. - Qed. + â–· WP e2 @ p; E {{ Φ }} ⊢ WP e1 @ p; E {{ Φ }}. + Proof using Hinh. eauto using ownP_lift_pure_det_step_no_fork. Qed. End ectx_lifting. diff --git a/theories/program_logic/weakestpre.v b/theories/program_logic/weakestpre.v index 32b98d8ff..b205ee399 100644 --- a/theories/program_logic/weakestpre.v +++ b/theories/program_logic/weakestpre.v @@ -12,84 +12,156 @@ Class irisG' (Λstate : Type) (Σ : gFunctors) := IrisG { Notation irisG Λ Σ := (irisG' (state Λ) Σ). Definition wp_pre `{irisG Λ Σ} - (wp : coPset -c> expr Λ -c> (val Λ -c> iProp Σ) -c> iProp Σ) : - coPset -c> expr Λ -c> (val Λ -c> iProp Σ) -c> iProp Σ := λ E e1 Φ, + (wp : bool -c> coPset -c> expr Λ -c> (val Λ -c> iProp Σ) -c> iProp Σ) : + bool -c> coPset -c> expr Λ -c> (val Λ -c> iProp Σ) -c> iProp Σ := λ p E e1 Φ, match to_val e1 with | Some v => |={E}=> Φ v | None => ∀ σ1, - state_interp σ1 ={E,∅}=∗ ⌜reducible e1 σ1⌠∗ + state_interp σ1 ={E,∅}=∗ ⌜if p then reducible e1 σ1 else True⌠∗ â–· ∀ e2 σ2 efs, ⌜prim_step e1 σ1 e2 σ2 efs⌠={∅,E}=∗ - state_interp σ2 ∗ wp E e2 Φ ∗ - [∗ list] ef ∈ efs, wp ⊤ ef (λ _, True) + state_interp σ2 ∗ wp p E e2 Φ ∗ + [∗ list] ef ∈ efs, wp p ⊤ ef (λ _, True) end%I. Local Instance wp_pre_contractive `{irisG Λ Σ} : Contractive wp_pre. Proof. - rewrite /wp_pre=> n wp wp' Hwp E e1 Φ. + rewrite /wp_pre=> n wp wp' Hwp p E e1 Φ. repeat (f_contractive || f_equiv); apply Hwp. Qed. Definition wp_def `{irisG Λ Σ} : - coPset → expr Λ → (val Λ → iProp Σ) → iProp Σ := fixpoint wp_pre. + bool → coPset → expr Λ → (val Λ → iProp Σ) → iProp Σ := fixpoint wp_pre. Definition wp_aux : seal (@wp_def). by eexists. Qed. Definition wp := unseal wp_aux. Definition wp_eq : @wp = @wp_def := seal_eq wp_aux. -Arguments wp {_ _ _} _ _%E _. -Instance: Params (@wp) 5. +Arguments wp {_ _ _} _ _ _%E _. +Instance: Params (@wp) 6. -Notation "'WP' e @ E {{ Φ } }" := (wp E e%E Φ) +Notation "'WP' e @ p ; E {{ Φ } }" := (wp p E e%E Φ) + (at level 20, e, Φ at level 200, + format "'[' 'WP' e '/' @ p ; E {{ Φ } } ']'") : uPred_scope. +Notation "'WP' e @ E {{ Φ } }" := (wp true E e%E Φ) (at level 20, e, Φ at level 200, format "'[' 'WP' e '/' @ E {{ Φ } } ']'") : uPred_scope. -Notation "'WP' e {{ Φ } }" := (wp ⊤ e%E Φ) +Notation "'WP' e @ E ? {{ Φ } }" := (wp false E e%E Φ) + (at level 20, e, Φ at level 200, + format "'[' 'WP' e '/' @ E ? {{ Φ } } ']'") : uPred_scope. +Notation "'WP' e {{ Φ } }" := (wp true ⊤ e%E Φ) (at level 20, e, Φ at level 200, format "'[' 'WP' e '/' {{ Φ } } ']'") : uPred_scope. +Notation "'WP' e ? {{ Φ } }" := (wp false ⊤ e%E Φ) + (at level 20, e, Φ at level 200, + format "'[' 'WP' e '/' ? {{ Φ } } ']'") : uPred_scope. -Notation "'WP' e @ E {{ v , Q } }" := (wp E e%E (λ v, Q)) +Notation "'WP' e @ p ; E {{ v , Q } }" := (wp p E e%E (λ v, Q)) + (at level 20, e, Q at level 200, + format "'[' 'WP' e '/' @ p ; E {{ v , Q } } ']'") : uPred_scope. +Notation "'WP' e @ E {{ v , Q } }" := (wp true E e%E (λ v, Q)) (at level 20, e, Q at level 200, format "'[' 'WP' e '/' @ E {{ v , Q } } ']'") : uPred_scope. -Notation "'WP' e {{ v , Q } }" := (wp ⊤ e%E (λ v, Q)) +Notation "'WP' e @ E ? {{ v , Q } }" := (wp false E e%E (λ v, Q)) + (at level 20, e, Q at level 200, + format "'[' 'WP' e '/' @ E ? {{ v , Q } } ']'") : uPred_scope. +Notation "'WP' e {{ v , Q } }" := (wp true ⊤ e%E (λ v, Q)) (at level 20, e, Q at level 200, format "'[' 'WP' e '/' {{ v , Q } } ']'") : uPred_scope. +Notation "'WP' e ? {{ v , Q } }" := (wp false ⊤ e%E (λ v, Q)) + (at level 20, e, Q at level 200, + format "'[' 'WP' e '/' ? {{ v , Q } } ']'") : uPred_scope. (* Texan triples *) +Notation "'{{{' P } } } e @ p ; E {{{ x .. y , 'RET' pat ; Q } } }" := + (â–¡ ∀ Φ, + P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e @ p; E {{ Φ }})%I + (at level 20, x closed binder, y closed binder, + format "{{{ P } } } e @ p ; E {{{ x .. y , RET pat ; Q } } }") : uPred_scope. Notation "'{{{' P } } } e @ E {{{ x .. y , 'RET' pat ; Q } } }" := (â–¡ ∀ Φ, P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e @ E {{ Φ }})%I (at level 20, x closed binder, y closed binder, format "{{{ P } } } e @ E {{{ x .. y , RET pat ; Q } } }") : uPred_scope. +Notation "'{{{' P } } } e @ E ? {{{ x .. y , 'RET' pat ; Q } } }" := + (â–¡ ∀ Φ, + P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e @ E ?{{ Φ }})%I + (at level 20, x closed binder, y closed binder, + format "{{{ P } } } e @ E ? {{{ x .. y , RET pat ; Q } } }") : uPred_scope. Notation "'{{{' P } } } e {{{ x .. y , 'RET' pat ; Q } } }" := (â–¡ ∀ Φ, P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e {{ Φ }})%I (at level 20, x closed binder, y closed binder, format "{{{ P } } } e {{{ x .. y , RET pat ; Q } } }") : uPred_scope. +Notation "'{{{' P } } } e ? {{{ x .. y , 'RET' pat ; Q } } }" := + (â–¡ ∀ Φ, + P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e ?{{ Φ }})%I + (at level 20, x closed binder, y closed binder, + format "{{{ P } } } e ? {{{ x .. y , RET pat ; Q } } }") : uPred_scope. +Notation "'{{{' P } } } e @ p ; E {{{ 'RET' pat ; Q } } }" := + (â–¡ ∀ Φ, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e @ p; E {{ Φ }})%I + (at level 20, + format "{{{ P } } } e @ p ; E {{{ RET pat ; Q } } }") : uPred_scope. Notation "'{{{' P } } } e @ E {{{ 'RET' pat ; Q } } }" := (â–¡ ∀ Φ, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e @ E {{ Φ }})%I (at level 20, format "{{{ P } } } e @ E {{{ RET pat ; Q } } }") : uPred_scope. +Notation "'{{{' P } } } e @ E ? {{{ 'RET' pat ; Q } } }" := + (â–¡ ∀ Φ, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e @ E ?{{ Φ }})%I + (at level 20, + format "{{{ P } } } e @ E ? {{{ RET pat ; Q } } }") : uPred_scope. Notation "'{{{' P } } } e {{{ 'RET' pat ; Q } } }" := (â–¡ ∀ Φ, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e {{ Φ }})%I (at level 20, format "{{{ P } } } e {{{ RET pat ; Q } } }") : uPred_scope. +Notation "'{{{' P } } } e ? {{{ 'RET' pat ; Q } } }" := + (â–¡ ∀ Φ, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e ?{{ Φ }})%I + (at level 20, + format "{{{ P } } } e ? {{{ RET pat ; Q } } }") : uPred_scope. +Notation "'{{{' P } } } e @ p ; E {{{ x .. y , 'RET' pat ; Q } } }" := + (∀ Φ : _ → uPred _, + P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e @ p; E {{ Φ }}) + (at level 20, x closed binder, y closed binder, + format "{{{ P } } } e @ p ; E {{{ x .. y , RET pat ; Q } } }") : C_scope. Notation "'{{{' P } } } e @ E {{{ x .. y , 'RET' pat ; Q } } }" := (∀ Φ : _ → uPred _, P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e @ E {{ Φ }}) (at level 20, x closed binder, y closed binder, format "{{{ P } } } e @ E {{{ x .. y , RET pat ; Q } } }") : C_scope. +Notation "'{{{' P } } } e @ E ? {{{ x .. y , 'RET' pat ; Q } } }" := + (∀ Φ : _ → uPred _, + P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e @ E ?{{ Φ }}) + (at level 20, x closed binder, y closed binder, + format "{{{ P } } } e @ E ? {{{ x .. y , RET pat ; Q } } }") : C_scope. Notation "'{{{' P } } } e {{{ x .. y , 'RET' pat ; Q } } }" := (∀ Φ : _ → uPred _, P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e {{ Φ }}) (at level 20, x closed binder, y closed binder, format "{{{ P } } } e {{{ x .. y , RET pat ; Q } } }") : C_scope. +Notation "'{{{' P } } } e ? {{{ x .. y , 'RET' pat ; Q } } }" := + (∀ Φ : _ → uPred _, + P -∗ â–· (∀ x, .. (∀ y, Q -∗ Φ pat%V) .. ) -∗ WP e ?{{ Φ }}) + (at level 20, x closed binder, y closed binder, + format "{{{ P } } } e ? {{{ x .. y , RET pat ; Q } } }") : C_scope. +Notation "'{{{' P } } } e @ p ; E {{{ 'RET' pat ; Q } } }" := + (∀ Φ : _ → uPred _, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e @ p; E {{ Φ }}) + (at level 20, + format "{{{ P } } } e @ p ; E {{{ RET pat ; Q } } }") : C_scope. Notation "'{{{' P } } } e @ E {{{ 'RET' pat ; Q } } }" := (∀ Φ : _ → uPred _, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e @ E {{ Φ }}) (at level 20, format "{{{ P } } } e @ E {{{ RET pat ; Q } } }") : C_scope. +Notation "'{{{' P } } } e @ E ? {{{ 'RET' pat ; Q } } }" := + (∀ Φ : _ → uPred _, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e @ E ?{{ Φ }}) + (at level 20, + format "{{{ P } } } e @ E ? {{{ RET pat ; Q } } }") : C_scope. Notation "'{{{' P } } } e {{{ 'RET' pat ; Q } } }" := (∀ Φ : _ → uPred _, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e {{ Φ }}) (at level 20, format "{{{ P } } } e {{{ RET pat ; Q } } }") : C_scope. +Notation "'{{{' P } } } e ? {{{ 'RET' pat ; Q } } }" := + (∀ Φ : _ → uPred _, P -∗ â–· (Q -∗ Φ pat%V) -∗ WP e ?{{ Φ }}) + (at level 20, + format "{{{ P } } } e ? {{{ RET pat ; Q } } }") : C_scope. Section wp. Context `{irisG Λ Σ}. @@ -99,11 +171,11 @@ Implicit Types v : val Λ. Implicit Types e : expr Λ. (* Weakest pre *) -Lemma wp_unfold E e Φ : WP e @ E {{ Φ }} ⊣⊢ wp_pre wp E e Φ. +Lemma wp_unfold p E e Φ : WP e @ p; E {{ Φ }} ⊣⊢ wp_pre wp p E e Φ. Proof. rewrite wp_eq. apply (fixpoint_unfold wp_pre). Qed. -Global Instance wp_ne E e n : - Proper (pointwise_relation _ (dist n) ==> dist n) (@wp Λ Σ _ E e). +Global Instance wp_ne p E e n : + Proper (pointwise_relation _ (dist n) ==> dist n) (@wp Λ Σ _ p E e). Proof. revert e. induction (lt_wf n) as [n _ IH]=> e Φ Ψ HΦ. rewrite !wp_unfold /wp_pre. @@ -113,19 +185,19 @@ Proof. do 17 (f_contractive || f_equiv). apply IH; first lia. intros v. eapply dist_le; eauto with omega. Qed. -Global Instance wp_proper E e : - Proper (pointwise_relation _ (≡) ==> (≡)) (@wp Λ Σ _ E e). +Global Instance wp_proper p E e : + Proper (pointwise_relation _ (≡) ==> (≡)) (@wp Λ Σ _ p E e). Proof. by intros Φ Φ' ?; apply equiv_dist=>n; apply wp_ne=>v; apply equiv_dist. Qed. -Lemma wp_value' E Φ v : Φ v ⊢ WP of_val v @ E {{ Φ }}. +Lemma wp_value' p E Φ v : Φ v ⊢ WP of_val v @ p; E {{ Φ }}. Proof. iIntros "HΦ". rewrite wp_unfold /wp_pre to_of_val. auto. Qed. -Lemma wp_value_inv E Φ v : WP of_val v @ E {{ Φ }} ={E}=∗ Φ v. +Lemma wp_value_inv p E Φ v : WP of_val v @ p; E {{ Φ }} ={E}=∗ Φ v. Proof. by rewrite wp_unfold /wp_pre to_of_val. Qed. -Lemma wp_strong_mono E1 E2 e Φ Ψ : - E1 ⊆ E2 → (∀ v, Φ v ={E2}=∗ Ψ v) ∗ WP e @ E1 {{ Φ }} ⊢ WP e @ E2 {{ Ψ }}. +Lemma wp_strong_mono p E1 E2 e Φ Ψ : + E1 ⊆ E2 → (∀ v, Φ v ={E2}=∗ Ψ v) ∗ WP e @ p; E1 {{ Φ }} ⊢ WP e @ p; E2 {{ Ψ }}. Proof. iIntros (?) "[HΦ H]". iLöb as "IH" forall (e). rewrite !wp_unfold /wp_pre. destruct (to_val e) as [v|] eqn:?. @@ -137,128 +209,141 @@ Proof. iMod "Hclose" as "_". by iApply ("IH" with "HΦ"). Qed. -Lemma fupd_wp E e Φ : (|={E}=> WP e @ E {{ Φ }}) ⊢ WP e @ E {{ Φ }}. +Lemma wp_forget_progress E e Φ : WP e @ E {{ Φ }} ⊢ WP e @ E ?{{ Φ }}. +Proof. + iIntros "H". iLöb as "IH" forall (E e Φ). rewrite !wp_unfold /wp_pre. + destruct (to_val e) as [v|]; first iExact "H". + iIntros (σ1) "Hσ". iMod ("H" with "Hσ") as "[#Hred H]". iModIntro. + iSplit; first done. iNext. iIntros (e2 σ2 efs) "#Hstep". + iMod ("H" with "Hstep") as "($ & He2 & Hefs)". iModIntro. + iSplitL "He2"; first by iApply ("IH" with "He2"). iClear "Hred Hstep". + induction efs as [|ef efs IH]; first by iApply big_sepL_nil. + rewrite !big_sepL_cons. iDestruct "Hefs" as "(Hef & Hefs)". + iSplitL "Hef". by iApply ("IH" with "Hef"). exact: IH. +Qed. + +Lemma fupd_wp p E e Φ : (|={E}=> WP e @ p; E {{ Φ }}) ⊢ WP e @ p; E {{ Φ }}. Proof. rewrite wp_unfold /wp_pre. iIntros "H". destruct (to_val e) as [v|] eqn:?. { by iMod "H". } iIntros (σ1) "Hσ1". iMod "H". by iApply "H". Qed. -Lemma wp_fupd E e Φ : WP e @ E {{ v, |={E}=> Φ v }} ⊢ WP e @ E {{ Φ }}. -Proof. iIntros "H". iApply (wp_strong_mono E); try iFrame; auto. Qed. +Lemma wp_fupd p E e Φ : WP e @ p; E {{ v, |={E}=> Φ v }} ⊢ WP e @ p; E {{ Φ }}. +Proof. iIntros "H". iApply (wp_strong_mono p E); try iFrame; auto. Qed. -Lemma wp_atomic E1 E2 e Φ : - Atomic e → - (|={E1,E2}=> WP e @ E2 {{ v, |={E2,E1}=> Φ v }}) ⊢ WP e @ E1 {{ Φ }}. +Lemma wp_atomic p E1 E2 e Φ : + StronglyAtomic e → + (|={E1,E2}=> WP e @ p; E2 {{ v, |={E2,E1}=> Φ v }}) ⊢ WP e @ p; E1 {{ Φ }}. Proof. iIntros (Hatomic) "H". rewrite !wp_unfold /wp_pre. - destruct (to_val e) as [v|] eqn:He. + destruct (to_val e) as [v|]. { by iDestruct "H" as ">>> $". } iIntros (σ1) "Hσ". iMod "H". iMod ("H" $! σ1 with "Hσ") as "[$ H]". iModIntro. iNext. iIntros (e2 σ2 efs Hstep). - iMod ("H" with "[//]") as "(Hphy & H & $)". - rewrite !wp_unfold /wp_pre. destruct (to_val e2) as [v2|] eqn:He2. - - iDestruct "H" as ">> $". eauto with iFrame. - - iMod ("H" with "[$]") as "[H _]". - iDestruct "H" as %(? & ? & ? & ?). by edestruct (Hatomic _ _ _ _ Hstep). + destruct (Hatomic _ _ _ _ Hstep) as [v <-%of_to_val]. + iMod ("H" with "[#]") as "($ & H & $)"; first done. + iMod (wp_value_inv with "H") as ">H". by iApply wp_value'. Qed. -Lemma wp_step_fupd E1 E2 e P Φ : +Lemma wp_step_fupd p E1 E2 e P Φ : to_val e = None → E2 ⊆ E1 → - (|={E1,E2}â–·=> P) -∗ WP e @ E2 {{ v, P ={E1}=∗ Φ v }} -∗ WP e @ E1 {{ Φ }}. + (|={E1,E2}â–·=> P) -∗ WP e @ p; E2 {{ v, P ={E1}=∗ Φ v }} -∗ WP e @ p; E1 {{ Φ }}. Proof. rewrite !wp_unfold /wp_pre. iIntros (-> ?) "HR H". iIntros (σ1) "Hσ". iMod "HR". iMod ("H" with "[$]") as "[$ H]". iModIntro; iNext; iIntros (e2 σ2 efs Hstep). iMod ("H" $! e2 σ2 efs with "[% //]") as "($ & H & $)". - iMod "HR". iModIntro. iApply (wp_strong_mono E2); first done. + iMod "HR". iModIntro. iApply (wp_strong_mono p E2); first done. iSplitR "H"; last iExact "H". iIntros (v) "H". by iApply "H". Qed. -Lemma wp_bind K `{!LanguageCtx Λ K} E e Φ : - WP e @ E {{ v, WP K (of_val v) @ E {{ Φ }} }} ⊢ WP K e @ E {{ Φ }}. +Lemma wp_bind K `{!LanguageCtx Λ K} p E e Φ : + WP e @ p; E {{ v, WP K (of_val v) @ p; E {{ Φ }} }} ⊢ WP K e @ p; E {{ Φ }}. Proof. iIntros "H". iLöb as "IH" forall (E e Φ). rewrite wp_unfold /wp_pre. destruct (to_val e) as [v|] eqn:He. { apply of_to_val in He as <-. by iApply fupd_wp. } rewrite wp_unfold /wp_pre fill_not_val //. iIntros (σ1) "Hσ". iMod ("H" with "[$]") as "[% H]". iModIntro; iSplit. - { iPureIntro. unfold reducible in *. naive_solver eauto using fill_step. } + { iPureIntro. destruct p; last done. + unfold reducible in *. naive_solver eauto using fill_step. } iNext; iIntros (e2 σ2 efs Hstep). destruct (fill_step_inv e σ1 e2 σ2 efs) as (e2'&->&?); auto. iMod ("H" $! e2' σ2 efs with "[//]") as "($ & H & $)". by iApply "IH". Qed. -Lemma wp_bind_inv K `{!LanguageCtx Λ K} E e Φ : - WP K e @ E {{ Φ }} ⊢ WP e @ E {{ v, WP K (of_val v) @ E {{ Φ }} }}. +Lemma wp_bind_inv K `{!LanguageCtx Λ K} p E e Φ : + WP K e @ p; E {{ Φ }} ⊢ WP e @ p; E {{ v, WP K (of_val v) @ p; E {{ Φ }} }}. Proof. iIntros "H". iLöb as "IH" forall (E e Φ). rewrite !wp_unfold /wp_pre. destruct (to_val e) as [v|] eqn:He. { apply of_to_val in He as <-. by rewrite !wp_unfold /wp_pre. } rewrite fill_not_val //. iIntros (σ1) "Hσ". iMod ("H" with "[$]") as "[% H]". iModIntro; iSplit. - { eauto using reducible_fill. } + { destruct p; eauto using reducible_fill. } iNext; iIntros (e2 σ2 efs Hstep). iMod ("H" $! (K e2) σ2 efs with "[]") as "($ & H & $)"; eauto using fill_step. by iApply "IH". Qed. (** * Derived rules *) -Lemma wp_mono E e Φ Ψ : (∀ v, Φ v ⊢ Ψ v) → WP e @ E {{ Φ }} ⊢ WP e @ E {{ Ψ }}. +Lemma wp_mono p E e Φ Ψ : (∀ v, Φ v ⊢ Ψ v) → WP e @ p; E {{ Φ }} ⊢ WP e @ p; E {{ Ψ }}. Proof. - iIntros (HΦ) "H"; iApply (wp_strong_mono E E); auto. + iIntros (HΦ) "H"; iApply (wp_strong_mono p E E); auto. iIntros "{$H}" (v) "?". by iApply HΦ. Qed. -Lemma wp_mask_mono E1 E2 e Φ : E1 ⊆ E2 → WP e @ E1 {{ Φ }} ⊢ WP e @ E2 {{ Φ }}. -Proof. iIntros (?) "H"; iApply (wp_strong_mono E1 E2); auto. iFrame; eauto. Qed. -Global Instance wp_mono' E e : - Proper (pointwise_relation _ (⊢) ==> (⊢)) (@wp Λ Σ _ E e). +Lemma wp_mask_mono p E1 E2 e Φ : E1 ⊆ E2 → WP e @ p; E1 {{ Φ }} ⊢ WP e @ p; E2 {{ Φ }}. +Proof. iIntros (?) "H"; iApply (wp_strong_mono p E1 E2); auto. iFrame; eauto. Qed. +Global Instance wp_mono' p E e : + Proper (pointwise_relation _ (⊢) ==> (⊢)) (@wp Λ Σ _ p E e). Proof. by intros Φ Φ' ?; apply wp_mono. Qed. -Lemma wp_value E Φ e v `{!IntoVal e v} : Φ v ⊢ WP e @ E {{ Φ }}. +Lemma wp_value p E Φ e v `{!IntoVal e v} : Φ v ⊢ WP e @ p; E {{ Φ }}. Proof. intros; rewrite -(of_to_val e v) //; by apply wp_value'. Qed. -Lemma wp_value_fupd' E Φ v : (|={E}=> Φ v) ⊢ WP of_val v @ E {{ Φ }}. +Lemma wp_value_fupd' p E Φ v : (|={E}=> Φ v) ⊢ WP of_val v @ p; E {{ Φ }}. Proof. intros. by rewrite -wp_fupd -wp_value'. Qed. -Lemma wp_value_fupd E Φ e v `{!IntoVal e v} : (|={E}=> Φ v) ⊢ WP e @ E {{ Φ }}. +Lemma wp_value_fupd p E Φ e v `{!IntoVal e v} : + (|={E}=> Φ v) ⊢ WP e @ p; E {{ Φ }}. Proof. intros. rewrite -wp_fupd -wp_value //. Qed. -Lemma wp_frame_l E e Φ R : R ∗ WP e @ E {{ Φ }} ⊢ WP e @ E {{ v, R ∗ Φ v }}. -Proof. iIntros "[??]". iApply (wp_strong_mono E E _ Φ); try iFrame; eauto. Qed. -Lemma wp_frame_r E e Φ R : WP e @ E {{ Φ }} ∗ R ⊢ WP e @ E {{ v, Φ v ∗ R }}. -Proof. iIntros "[??]". iApply (wp_strong_mono E E _ Φ); try iFrame; eauto. Qed. +Lemma wp_frame_l p E e Φ R : R ∗ WP e @ p; E {{ Φ }} ⊢ WP e @ p; E {{ v, R ∗ Φ v }}. +Proof. iIntros "[??]". iApply (wp_strong_mono p E E _ Φ); try iFrame; eauto. Qed. +Lemma wp_frame_r p E e Φ R : WP e @ p; E {{ Φ }} ∗ R ⊢ WP e @ p; E {{ v, Φ v ∗ R }}. +Proof. iIntros "[??]". iApply (wp_strong_mono p E E _ Φ); try iFrame; eauto. Qed. -Lemma wp_frame_step_l E1 E2 e Φ R : +Lemma wp_frame_step_l p E1 E2 e Φ R : to_val e = None → E2 ⊆ E1 → - (|={E1,E2}â–·=> R) ∗ WP e @ E2 {{ Φ }} ⊢ WP e @ E1 {{ v, R ∗ Φ v }}. + (|={E1,E2}â–·=> R) ∗ WP e @ p; E2 {{ Φ }} ⊢ WP e @ p; E1 {{ v, R ∗ Φ v }}. Proof. iIntros (??) "[Hu Hwp]". iApply (wp_step_fupd with "Hu"); try done. iApply (wp_mono with "Hwp"). by iIntros (?) "$$". Qed. -Lemma wp_frame_step_r E1 E2 e Φ R : +Lemma wp_frame_step_r p E1 E2 e Φ R : to_val e = None → E2 ⊆ E1 → - WP e @ E2 {{ Φ }} ∗ (|={E1,E2}â–·=> R) ⊢ WP e @ E1 {{ v, Φ v ∗ R }}. + WP e @ p; E2 {{ Φ }} ∗ (|={E1,E2}â–·=> R) ⊢ WP e @ p; E1 {{ v, Φ v ∗ R }}. Proof. - rewrite [(WP _ @ _ {{ _ }} ∗ _)%I]comm; setoid_rewrite (comm _ _ R). + rewrite [(WP _ @ _; _ {{ _ }} ∗ _)%I]comm; setoid_rewrite (comm _ _ R). apply wp_frame_step_l. Qed. -Lemma wp_frame_step_l' E e Φ R : - to_val e = None → â–· R ∗ WP e @ E {{ Φ }} ⊢ WP e @ E {{ v, R ∗ Φ v }}. -Proof. iIntros (?) "[??]". iApply (wp_frame_step_l E E); try iFrame; eauto. Qed. -Lemma wp_frame_step_r' E e Φ R : - to_val e = None → WP e @ E {{ Φ }} ∗ â–· R ⊢ WP e @ E {{ v, Φ v ∗ R }}. -Proof. iIntros (?) "[??]". iApply (wp_frame_step_r E E); try iFrame; eauto. Qed. +Lemma wp_frame_step_l' p E e Φ R : + to_val e = None → â–· R ∗ WP e @ p; E {{ Φ }} ⊢ WP e @ p; E {{ v, R ∗ Φ v }}. +Proof. iIntros (?) "[??]". iApply (wp_frame_step_l p E E); try iFrame; eauto. Qed. +Lemma wp_frame_step_r' p E e Φ R : + to_val e = None → WP e @ p; E {{ Φ }} ∗ â–· R ⊢ WP e @ p; E {{ v, Φ v ∗ R }}. +Proof. iIntros (?) "[??]". iApply (wp_frame_step_r p E E); try iFrame; eauto. Qed. -Lemma wp_wand E e Φ Ψ : - WP e @ E {{ Φ }} -∗ (∀ v, Φ v -∗ Ψ v) -∗ WP e @ E {{ Ψ }}. +Lemma wp_wand p E e Φ Ψ : + WP e @ p; E {{ Φ }} -∗ (∀ v, Φ v -∗ Ψ v) -∗ WP e @ p; E {{ Ψ }}. Proof. - iIntros "Hwp H". iApply (wp_strong_mono E); auto. + iIntros "Hwp H". iApply (wp_strong_mono p E); auto. iIntros "{$Hwp}" (?) "?". by iApply "H". Qed. -Lemma wp_wand_l E e Φ Ψ : - (∀ v, Φ v -∗ Ψ v) ∗ WP e @ E {{ Φ }} ⊢ WP e @ E {{ Ψ }}. +Lemma wp_wand_l p E e Φ Ψ : + (∀ v, Φ v -∗ Ψ v) ∗ WP e @ p; E {{ Φ }} ⊢ WP e @ p; E {{ Ψ }}. Proof. iIntros "[H Hwp]". iApply (wp_wand with "Hwp H"). Qed. -Lemma wp_wand_r E e Φ Ψ : - WP e @ E {{ Φ }} ∗ (∀ v, Φ v -∗ Ψ v) ⊢ WP e @ E {{ Ψ }}. +Lemma wp_wand_r p E e Φ Ψ : + WP e @ p; E {{ Φ }} ∗ (∀ v, Φ v -∗ Ψ v) ⊢ WP e @ p; E {{ Ψ }}. Proof. iIntros "[Hwp H]". iApply (wp_wand with "Hwp H"). Qed. End wp. @@ -268,25 +353,25 @@ Section proofmode_classes. Implicit Types P Q : iProp Σ. Implicit Types Φ : val Λ → iProp Σ. - Global Instance frame_wp p E e R Φ Ψ : - (∀ v, Frame p R (Φ v) (Ψ v)) → Frame p R (WP e @ E {{ Φ }}) (WP e @ E {{ Ψ }}). + Global Instance frame_wp p p' E e R Φ Ψ : + (∀ v, Frame p' R (Φ v) (Ψ v)) → Frame p' R (WP e @ p; E {{ Φ }}) (WP e @ p; E {{ Ψ }}). Proof. rewrite /Frame=> HR. rewrite wp_frame_l. apply wp_mono, HR. Qed. - Global Instance is_except_0_wp E e Φ : IsExcept0 (WP e @ E {{ Φ }}). + Global Instance is_except_0_wp p E e Φ : IsExcept0 (WP e @ p; E {{ Φ }}). Proof. by rewrite /IsExcept0 -{2}fupd_wp -except_0_fupd -fupd_intro. Qed. - Global Instance elim_modal_bupd_wp E e P Φ : - ElimModal (|==> P) P (WP e @ E {{ Φ }}) (WP e @ E {{ Φ }}). + Global Instance elim_modal_bupd_wp p E e P Φ : + ElimModal (|==> P) P (WP e @ p; E {{ Φ }}) (WP e @ p; E {{ Φ }}). Proof. by rewrite /ElimModal (bupd_fupd E) fupd_frame_r wand_elim_r fupd_wp. Qed. - Global Instance elim_modal_fupd_wp E e P Φ : - ElimModal (|={E}=> P) P (WP e @ E {{ Φ }}) (WP e @ E {{ Φ }}). + Global Instance elim_modal_fupd_wp p E e P Φ : + ElimModal (|={E}=> P) P (WP e @ p; E {{ Φ }}) (WP e @ p; E {{ Φ }}). Proof. by rewrite /ElimModal fupd_frame_r wand_elim_r fupd_wp. Qed. (* lower precedence, if possible, it should persistently pick elim_upd_fupd_wp *) Global Instance elim_modal_fupd_wp_atomic E1 E2 e P Φ : - Atomic e → + StronglyAtomic e → ElimModal (|={E1,E2}=> P) P - (WP e @ E1 {{ Φ }}) (WP e @ E2 {{ v, |={E2,E1}=> Φ v }})%I | 100. + (WP e @ p; E1 {{ Φ }}) (WP e @ p; E2 {{ v, |={E2,E1}=> Φ v }})%I | 100. Proof. intros. by rewrite /ElimModal fupd_frame_r wand_elim_r wp_atomic. Qed. End proofmode_classes. diff --git a/theories/tests/heap_lang.v b/theories/tests/heap_lang.v index 51681a365..598ec5610 100644 --- a/theories/tests/heap_lang.v +++ b/theories/tests/heap_lang.v @@ -86,5 +86,5 @@ Section LiftingTests. Proof. iIntros "". wp_apply Pred_spec. wp_let. by wp_apply Pred_spec. Qed. End LiftingTests. -Lemma heap_e_adequate σ : adequate heap_e σ (= #2). +Lemma heap_e_adequate σ : adequate true heap_e σ (= #2). Proof. eapply (heap_adequacy heapΣ)=> ?. by apply heap_e_spec. Qed. diff --git a/theories/tests/ipm_paper.v b/theories/tests/ipm_paper.v index 6834c5c5e..0922cd5bb 100644 --- a/theories/tests/ipm_paper.v +++ b/theories/tests/ipm_paper.v @@ -101,7 +101,7 @@ update modalities (which we did not cover in the paper). Normally we use these mask changing update modalities directly in our proofs, but in this file we use the first prove the rule as a lemma, and then use that. *) Lemma wp_inv_open `{irisG Λ Σ} N E P e Φ : - nclose N ⊆ E → Atomic e → + nclose N ⊆ E → StronglyAtomic e → inv N P ∗ (â–· P -∗ WP e @ E ∖ ↑N {{ v, â–· P ∗ Φ v }}) ⊢ WP e @ E {{ Φ }}. Proof. iIntros (??) "[#Hinv Hwp]". -- GitLab