diff --git a/CHANGELOG.md b/CHANGELOG.md index ceefd450274d1a8a95d95197423253f399bc32e5..4edacb751ea954631b5b481f693b48e535dfd7a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -73,9 +73,8 @@ lemma. * Make the `inG` instances for `libG` fields local, so they are only used inside the library that defines the `libG`. -* Prepare for supporting later credits, by adding a resource `£ n` describing - ownership of `n` credits that can be eliminated at fancy updates. - Note that HeapLang has not yet been equipped with support for later credits. +* Add infrastructure for supporting later credits, by adding a resource `£ n` + describing ownership of `n` credits that can be eliminated at fancy updates. + To retain backwards compatibility with the interaction laws of fancy updates with the plainly modality (`BiFUpdPlainly`), which are incompatible with later credits, the logic has a new parameter of type `has_lc`, which is @@ -129,14 +128,18 @@ lemma. number of steps taken so far. This number is tied to ghost state in the state interpretation, which is exposed, updated, and used with new lemmas `wp_lb_init`, `wp_lb_update`, and `wp_step_fupdN_lb`. (by Jonas Kastberg Hinrichsen) -* In line with the support for later credits (see `base_logic`), `heapGS_gen` - now takes an additional `has_lc` parameter, and `heapGS` is a short-hand for - `heapGS_gen HasLc`. The adequacy statements for HeapLang have been changed - accordingly: +* Make pattern argument of `wp_pure` tactic optional (defaults to wildcard + pattern, matching all redexes). +* In line with the support for later credits (see `base_logic`), the tactic + `wp_pure` now takes an optional parameter `credit:"H"` which generates a + hypothesis `H` for a single later credit `£ 1` that can be eliminated using + `lc_fupd_elim_later`. + The typeclass `heapGS_gen` now takes an additional `has_lc` parameter, and + `heapGS` is a short-hand for `heapGS_gen HasLc`. The adequacy statements for + HeapLang have been changed accordingly: + `heap_adequacy` provides `heapGS`, thus enabling the use of later credits. This precludes usage of the laws in `BiFUpdPlainly` in the HeapLang instance of Iris. + `heap_total` provides `heapGS_gen HasNoLc`. - Currently, the primitive laws for HeapLang do not yet provide later credits. The following `sed` script helps adjust your code to the renaming (on macOS, replace `sed` by `gsed`, installed via e.g. `brew install gnu-sed`). diff --git a/docs/heap_lang.md b/docs/heap_lang.md index 7cbfd5e4e1030191d19e91ff5ad6987f77762519..23a2f04acae94b7ab15f498bac473228abe03242 100644 --- a/docs/heap_lang.md +++ b/docs/heap_lang.md @@ -55,9 +55,12 @@ that the current goal is of the shape `WP e @ E {{ Q }}`. Tactics to take one or more pure program steps: -- `wp_pure`: Perform one pure reduction step. Pure steps are defined by the - `PureExec` typeclass and include beta reduction, projections, constructors, as - well as unary and binary arithmetic operators. +- `wp_pure pat credit:"H"`: Perform one pure reduction step. `pat` optionally + defines the pattern that the redex has to match; it defaults to `_` (any + redex). The `credit:` argument is optional, too; when present, a later credit + will be generated in a fresh hypothesis named `"H"`. + Pure steps are defined by the `PureExec` typeclass and include beta reduction, + projections, constructors, as well as unary and binary arithmetic operators. - `wp_pures`: Perform as many pure reduction steps as possible. This tactic will **not** reduce lambdas/recs that are hidden behind a definition. If the computation reaches a value, the `WP` will be entirely removed and the diff --git a/iris_heap_lang/proofmode.v b/iris_heap_lang/proofmode.v index 49f45e643586c793e87563127c134d671c23b3d9..6a8fd1de71f1300e7987a56cc1e45a6a188ae7c3 100644 --- a/iris_heap_lang/proofmode.v +++ b/iris_heap_lang/proofmode.v @@ -53,6 +53,26 @@ Proof. rewrite -total_lifting.twp_pure_step //. Qed. +Lemma tac_wp_pure_credit `{!heapGS_gen hlc Σ} Δ Δ' s E j K e1 e2 ϕ Φ : + PureExec ϕ 1 e1 e2 → + ϕ → + MaybeIntoLaterNEnvs 1 Δ Δ' → + match envs_app false (Esnoc Enil j (£ 1)) Δ' with + | Some Δ'' => + envs_entails Δ'' (WP fill K e2 @ s; E {{ Φ }}) + | None => False + end → + envs_entails Δ (WP (fill K e1) @ s; E {{ Φ }}). +Proof. + rewrite envs_entails_unseal=> ??? HΔ. + pose proof @pure_exec_fill. + rewrite -lifting.wp_pure_step_later; last done. + rewrite into_laterN_env_sound /=. apply later_mono. + destruct (envs_app _ _ _) as [Δ''|] eqn:HΔ'; [ | contradiction ]. + rewrite envs_app_sound //; simpl. + rewrite right_id. apply wand_intro_r. by rewrite wand_elim_l. +Qed. + Lemma tac_wp_value_nofupd `{!heapGS_gen hlc Σ} Δ s E Φ v : envs_entails Δ (Φ v) → envs_entails Δ (WP (Val v) @ s; E {{ Φ }}). Proof. rewrite envs_entails_unseal=> ->. by apply wp_value. Qed. @@ -133,6 +153,36 @@ Tactic Notation "wp_pure" open_constr(efoc) := || fail "wp_pure: cannot find" efoc "in" e "or" efoc "is not a redex" | _ => fail "wp_pure: not a 'wp'" end. +Tactic Notation "wp_pure" := + wp_pure _. + +Tactic Notation "wp_pure" open_constr(efoc) "credit:" constr(H) := + iStartProof; + let Htmp := iFresh in + let finish _ := + pm_reduce; + (iDestructHyp Htmp as H || fail 2 "wp_pure:" H "is not fresh"); + wp_finish + in + lazymatch goal with + | |- envs_entails _ (wp ?s ?E ?e ?Q) => + let e := eval simpl in e in + reshape_expr e ltac:(fun K e' => + unify e' efoc; + eapply (tac_wp_pure_credit _ _ _ _ Htmp K e'); + [iSolveTC (* PureExec *) + |try solve_vals_compare_safe (* The pure condition for PureExec -- + handles trivial goals, including [vals_compare_safe] *) + |iSolveTC (* IntoLaters *) + |finish () (* new goal *) + ]) + || fail "wp_pure: cannot find" efoc "in" e "or" efoc "is not a redex" + | |- envs_entails _ (twp ?s ?E ?e ?Q) => + fail "wp_pure: credit generation is not supported for a TWP" + | _ => fail "wp_pure: not a 'wp'" + end. +Tactic Notation "wp_pure" "credit:" constr(H) := + wp_pure _ credit: H. (* TODO: do this in one go, without [repeat]. *) Ltac wp_pures := diff --git a/tests/heap_lang.ref b/tests/heap_lang.ref index 2ca1c26e84f2b2fdee24b0bd5de1776c38a44b5e..f85b167b4a75467c954fcb064dcc818cd93f1355 100644 --- a/tests/heap_lang.ref +++ b/tests/heap_lang.ref @@ -179,6 +179,21 @@ Tactic failure: wp_pure: cannot find ?y in (Var "x") or (@iris_invGS HasLc heap_lang Σ (@heapGS_irisGS HasLc Σ heapGS0)))) (@top coPset coPset_top) (@top coPset coPset_top) (@bi_pure (uPredI (iResUR Σ)) True)) +"test_wp_pure_credit_succeed" + : string +1 goal + + Σ : gFunctors + heapGS0 : heapGS Σ + P : iProp Σ + ============================ + "Hcred" : £ 1 + --------------------------------------∗ + |={⊤}=> ▷ P ={∅}=∗ P +"test_wp_pure_credit_fail" + : string +The command has indeed failed with message: +Tactic failure: wp_pure: "Hcred" is not fresh. 1 goal Σ : gFunctors diff --git a/tests/heap_lang.v b/tests/heap_lang.v index 2bb43ba85990ec66f626bcf1ac13f33250789719..023fbf3f74ad5e08ab1c46b2c3b62c65ff966a19 100644 --- a/tests/heap_lang.v +++ b/tests/heap_lang.v @@ -16,7 +16,7 @@ Section tests. ⌜(10 = 4 + 6)%nat⌠-∗ WP let: "x" := ref #1 in "x" <- !"x";; !"x" {{ v, ⌜v = #1⌠}}. Proof. - iIntros "?". wp_alloc l. repeat (wp_pure _) || wp_load || wp_store. + iIntros "?". wp_alloc l. repeat wp_pure || wp_load || wp_store. match goal with | |- context [ (10 = 4 + 6)%nat ] => done end. @@ -44,8 +44,8 @@ Section tests. Lemma heap_e2_spec E : ⊢ WP heap_e2 @ E [{ v, ⌜v = #2⌠}]. Proof. iIntros "". rewrite /heap_e2. - wp_alloc l as "Hl". Show. wp_alloc l'. - wp_pures. wp_bind (!_)%E. wp_load. Show. (* No fupd was added *) + wp_alloc l as "Hl". Show. wp_alloc l'. do 2 wp_pure. + wp_bind (!_)%E. wp_load. Show. (* No fupd was added *) wp_store. wp_load. done. Qed. @@ -336,6 +336,23 @@ Section tests. Show. Unset Printing All. Abort. + + Check "test_wp_pure_credit_succeed". + Lemma test_wp_pure_credit_succeed P : + ⊢ WP #42 + #420 {{ v, ▷ P ={∅}=∗ P }}. + Proof. + wp_pure credit:"Hcred". Show. + iIntros "!> HP". iMod (lc_fupd_elim_later with "Hcred HP"). auto. + Qed. + + Check "test_wp_pure_credit_fail". + Lemma test_wp_pure_credit_fail : + ⊢ True -∗ WP #42 + #420 {{ v, True }}. + Proof. + iIntros "Hcred". + Fail wp_pure credit:"Hcred". + Abort. + End tests. Section mapsto_tests.