diff --git a/ProofMode.md b/ProofMode.md index c8748778fa6a7e2a2e8cf814ce43b9a76516f5b3..d1445385d0c44620baa7329d64c7f2a2aefc10e4 100644 --- a/ProofMode.md +++ b/ProofMode.md @@ -225,8 +225,7 @@ _specification patterns_ to express splitting of hypotheses: all persistent hypotheses. The spatial hypotheses among `H1 ... Hn` will be consumed. Hypotheses may be prefixed with a `$`, which results in them being framed in the generated goal. -- `[-H1 ... Hn]` : negated form of the above pattern. This pattern does not - accept hypotheses prefixed with a `$`. +- `[-H1 ... Hn]` : negated form of the above pattern. - `>[H1 ... Hn]` : same as the above pattern, but can only be used if the goal is a modality, in which case the modality will be kept in the generated goal for the premise will be wrapped into the modality. diff --git a/heap_lang/lib/assert.v b/heap_lang/lib/assert.v index bae4e2c03d608dda2f547c1ed3e7e6f9e34a37db..5b454b0be362b1ef5ef5b0e67145d86999667af3 100644 --- a/heap_lang/lib/assert.v +++ b/heap_lang/lib/assert.v @@ -13,6 +13,5 @@ Lemma wp_assert `{heapG Σ} E (Φ : val → iProp Σ) e `{!Closed [] e} : WP e @ E {{ v, v = #true ∧ ▷ Φ #() }} ⊢ WP assert: e @ E {{ Φ }}. Proof. iIntros "HΦ". rewrite /assert. wp_let. wp_seq. - iApply wp_wand_r; iFrame "HΦ"; iIntros (v) "[% ?]"; subst. - wp_if. done. + iApply (wp_wand_r with "[- $HΦ]"). iIntros (v) "[% ?]"; subst. by wp_if. Qed. diff --git a/heap_lang/lib/par.v b/heap_lang/lib/par.v index 2ee00928094c6a0ea4ab30795b40a9cb7f8985f2..bae873a2327d28d564a6b690f1c3f448a1cf53f1 100644 --- a/heap_lang/lib/par.v +++ b/heap_lang/lib/par.v @@ -24,10 +24,10 @@ Lemma par_spec (Ψ1 Ψ2 : val → iProp Σ) e (f1 f2 : val) (Φ : val → iProp Proof. iIntros (?) "(#Hh&Hf1&Hf2&HΦ)". rewrite /par. wp_value. iModIntro. wp_let. wp_proj. - wp_apply (spawn_spec parN); try wp_done; try solve_ndisj; iFrame "Hf1 Hh". - iNext. iIntros (l) "Hl". wp_let. wp_proj. wp_bind (f2 _). - iApply wp_wand_l; iFrame "Hf2"; iIntros (v) "H2". wp_let. - wp_apply join_spec; iFrame "Hl". iNext. iIntros (w) "H1". + wp_apply (spawn_spec parN with "[- $Hh $Hf1]"); try wp_done; try solve_ndisj. + iIntros (l) "Hl". wp_let. wp_proj. wp_bind (f2 _). + iApply (wp_wand_r with "[- $Hf2]"); iIntros (v) "H2". wp_let. + wp_apply (join_spec with "[- $Hl]"). iIntros (w) "H1". iSpecialize ("HΦ" with "* [-]"); first by iSplitL "H1". by wp_let. Qed. @@ -37,7 +37,7 @@ Lemma wp_par (Ψ1 Ψ2 : val → iProp Σ) ∀ v1 v2, Ψ1 v1 ★ Ψ2 v2 -★ ▷ Φ (v1,v2)%V) ⊢ WP e1 || e2 {{ Φ }}. Proof. - iIntros "(#Hh&H1&H2&H)". iApply (par_spec Ψ1 Ψ2); try wp_done. - iFrame "Hh H". iSplitL "H1"; by wp_let. + iIntros "(#Hh&H1&H2&H)". iApply (par_spec Ψ1 Ψ2 with "[- $Hh $H]"); try wp_done. + iSplitL "H1"; by wp_let. Qed. End proof. diff --git a/heap_lang/lib/spawn.v b/heap_lang/lib/spawn.v index 7da9b29be7d48ee1c75f58382dc89f282493984d..9c4bb70c3aa9baf8e9213251fc55fd1ea3689106 100644 --- a/heap_lang/lib/spawn.v +++ b/heap_lang/lib/spawn.v @@ -58,7 +58,7 @@ Proof. { iNext. iExists NONEV. iFrame; eauto. } wp_apply wp_fork; simpl. iSplitR "Hf". - iModIntro. wp_seq. iModIntro. iApply "HΦ". rewrite /join_handle. eauto. - - wp_bind (f _). iApply wp_wand_l. iFrame "Hf"; iIntros (v) "Hv". + - wp_bind (f _). iApply (wp_wand_r with "[ $Hf]"); iIntros (v) "Hv". iInv N as (v') "[Hl _]" "Hclose". wp_store. iApply "Hclose". iNext. iExists (SOMEV v). iFrame. eauto. Qed. diff --git a/heap_lang/lib/spin_lock.v b/heap_lang/lib/spin_lock.v index 225a9a72823ce21226f61103d23ce0da5bc6d764..9cd0fd096b390a5a95e2ff1c7b58b5c12aa664ae 100644 --- a/heap_lang/lib/spin_lock.v +++ b/heap_lang/lib/spin_lock.v @@ -73,8 +73,8 @@ Section proof. Lemma acquire_spec γ lk R : {{{ is_lock γ lk R }}} acquire lk {{{; #(), locked γ ★ R }}}. Proof. - iIntros (Φ) "[#Hl HΦ]". iLöb as "IH". wp_rec. wp_bind (try_acquire _). - iApply try_acquire_spec. iFrame "#". iSplit. + iIntros (Φ) "[#Hl HΦ]". iLöb as "IH". wp_rec. + wp_apply (try_acquire_spec with "[- $Hl]"). iSplit. - iIntros "Hlked HR". wp_if. iModIntro. iApply "HΦ"; iFrame. - wp_if. iApply ("IH" with "[HΦ]"). auto. Qed. @@ -87,7 +87,6 @@ Section proof. rewrite /release /=. wp_let. iInv N as (b) "[Hl _]" "Hclose". wp_store. iApply "HΦ". iApply "Hclose". iNext. iExists false. by iFrame. Qed. - End proof. Definition spin_lock `{!heapG Σ, !lockG Σ} : lock Σ := diff --git a/proofmode/spec_patterns.v b/proofmode/spec_patterns.v index eb9e9dc3b0eb072ab2d64445553b7d4fbbb0dd5e..4f9cbada3d365104c34c3ad1cd5ab57fb390e2ad 100644 --- a/proofmode/spec_patterns.v +++ b/proofmode/spec_patterns.v @@ -71,7 +71,6 @@ with parse_goal (ts : list token) (g : spec_goal) parse_goal ts (SpecGoal (spec_goal_modal g) (spec_goal_negate g) (spec_goal_frame g) (s :: spec_goal_hyps g)) k | TFrame :: TName s :: ts => - guard (¬spec_goal_negate g); parse_goal ts (SpecGoal (spec_goal_modal g) (spec_goal_negate g) (s :: spec_goal_frame g) (spec_goal_hyps g)) k | TBracketR :: ts => diff --git a/proofmode/tactics.v b/proofmode/tactics.v index d4d5431ad5bf008fa40c9b0beb01e20768f75bd8..721b3f714a718e9e9cc5ec0310ad897ff94292a3 100644 --- a/proofmode/tactics.v +++ b/proofmode/tactics.v @@ -308,7 +308,8 @@ Local Tactic Notation "iSpecializePat" constr(H) constr(pat) := |(*goal*) |go H1 pats] | SGoal (SpecGoal ?m ?lr ?Hs_frame ?Hs) :: ?pats => - eapply tac_specialize_assert with _ _ _ H1 _ lr (Hs_frame ++ Hs) _ _ _ _; + let Hs' := eval cbv in (if lr then Hs else Hs_frame ++ Hs) in + eapply tac_specialize_assert with _ _ _ H1 _ lr Hs' _ _ _ _; [env_cbv; reflexivity || fail "iSpecialize:" H1 "not found" |solve_to_wand H1 |match m with @@ -1084,7 +1085,8 @@ Tactic Notation "iAssertCore" open_constr(Q) "with" constr(Hs) "as" tactic(tac) |apply _ || fail "iAssert:" Q "not persistent" |tac H] | [SGoal (SpecGoal ?m ?lr ?Hs_frame ?Hs)] => - eapply tac_assert with _ _ _ lr (Hs_frame ++ Hs) H Q _; + let Hs' := eval cbv in (if lr then Hs else Hs_frame ++ Hs) in + eapply tac_assert with _ _ _ lr Hs' H Q _; [match m with | false => apply elim_modal_dummy | true => apply _ || fail "iAssert: goal not a modality" diff --git a/tests/barrier_client.v b/tests/barrier_client.v index 2bb035c5d3023fb07e1a196880cb4257d2209844..71071bc05d5319c5e3d7440e580f613c146939e7 100644 --- a/tests/barrier_client.v +++ b/tests/barrier_client.v @@ -29,28 +29,26 @@ Section client. heap_ctx ★ recv N b (y_inv q y) ⊢ WP worker n #b #y {{ _, True }}. Proof. iIntros "[#Hh Hrecv]". wp_lam. wp_let. - wp_apply wait_spec; iFrame "Hrecv". - iNext. iDestruct 1 as (f) "[Hy #Hf]". + wp_apply (wait_spec with "[- $Hrecv]"). iDestruct 1 as (f) "[Hy #Hf]". wp_seq. wp_load. - iApply wp_wand_r; iSplitR; [iApply "Hf"|by iIntros (v) "_"]. + iApply wp_wand_r. iSplitR; [iApply "Hf"|by iIntros (v) "_"]. Qed. Lemma client_safe : heapN ⊥ N → heap_ctx ⊢ WP client {{ _, True }}. Proof. iIntros (?) "#Hh"; rewrite /client. wp_alloc y as "Hy". wp_let. - wp_apply (newbarrier_spec N (y_inv 1 y)); first done. - iFrame "Hh". iNext. iIntros (l) "[Hr Hs]". wp_let. - iApply (wp_par (λ _, True%I) (λ _, True%I)). iFrame "Hh". - iSplitL "Hy Hs". + wp_apply (newbarrier_spec N (y_inv 1 y) with "[- $Hh]"); first done. + iIntros (l) "[Hr Hs]". wp_let. + iApply (wp_par (λ _, True%I) (λ _, True%I) with "[-$Hh]"). iSplitL "Hy Hs". - (* The original thread, the sender. *) - wp_store. iApply signal_spec; iFrame "Hs"; iSplitL "Hy"; [|by eauto]. + wp_store. iApply (signal_spec with "[- $Hs]"). iSplitL "Hy"; [|by eauto]. iExists _; iSplitL; [done|]. iAlways; iIntros (n). wp_let. by wp_op. - (* The two spawned threads, the waiters. *) iSplitL; [|by iIntros (_ _) "_ !>"]. iDestruct (recv_weaken with "[] Hr") as "Hr". { iIntros "Hy". by iApply (y_inv_split with "Hy"). } iMod (recv_split with "Hr") as "[H1 H2]"; first done. - iApply (wp_par (λ _, True%I) (λ _, True%I)). iFrame "Hh". + iApply (wp_par (λ _, True%I) (λ _, True%I) with "[- $Hh]"). iSplitL "H1"; [|iSplitL "H2"; [|by iIntros (_ _) "_ !>"]]; iApply worker_safe; by iSplit. Qed. diff --git a/tests/joining_existentials.v b/tests/joining_existentials.v index cc01dd57356572e314d8f143adc5ea71b113c6ea..b2351a1ab107d335f34f2f0ab1db0a16693034e1 100644 --- a/tests/joining_existentials.v +++ b/tests/joining_existentials.v @@ -35,8 +35,8 @@ Lemma worker_spec e γ l (Φ Ψ : X → iProp Σ) `{!Closed [] e} : recv N l (barrier_res γ Φ) ★ (∀ x, {{ Φ x }} e {{ _, Ψ x }}) ⊢ WP wait #l ;; e {{ _, barrier_res γ Ψ }}. Proof. - iIntros "[Hl #He]". wp_apply wait_spec; simpl; iFrame "Hl". - iNext. iDestruct 1 as (x) "[#Hγ Hx]". + iIntros "[Hl #He]". wp_apply (wait_spec with "[- $Hl]"); simpl. + iDestruct 1 as (x) "[#Hγ Hx]". wp_seq. iApply wp_wand_l. iSplitR; [|by iApply "He"]. iIntros (v) "?"; iExists x; by iSplit. Qed. @@ -76,21 +76,21 @@ Lemma client_spec_new eM eW1 eW2 `{!Closed [] eM, !Closed [] eW1, !Closed [] eW2 Proof. iIntros (HN) "/= (#Hh&HP&#He&#He1&#He2)"; rewrite /client. iMod (own_alloc (Pending : one_shotR Σ F)) as (γ) "Hγ"; first done. - wp_apply (newbarrier_spec N (barrier_res γ Φ)); auto. - iFrame "Hh". iNext. iIntros (l) "[Hr Hs]". + wp_apply (newbarrier_spec N (barrier_res γ Φ) with "[- $Hh]"); auto. + iIntros (l) "[Hr Hs]". set (workers_post (v : val) := (barrier_res γ Ψ1 ★ barrier_res γ Ψ2)%I). - wp_let. wp_apply (wp_par (λ _, True)%I workers_post); iFrame "Hh". + wp_let. wp_apply (wp_par (λ _, True)%I workers_post with "[- $Hh]"). iSplitL "HP Hs Hγ"; [|iSplitL "Hr"]. - wp_bind eM. iApply wp_wand_l; iSplitR "HP"; [|by iApply "He"]. iIntros (v) "HP"; iDestruct "HP" as (x) "HP". wp_let. iMod (own_update with "Hγ") as "Hx". { by apply (cmra_update_exclusive (Shot x)). } - iApply signal_spec; iFrame "Hs"; iSplitR ""; last auto. + iApply (signal_spec with "[- $Hs]"). iSplitR ""; last auto. iExists x; auto. - iDestruct (recv_weaken with "[] Hr") as "Hr"; first by iApply P_res_split. iMod (recv_split with "Hr") as "[H1 H2]"; first done. wp_apply (wp_par (λ _, barrier_res γ Ψ1)%I - (λ _, barrier_res γ Ψ2)%I); iFrame "Hh". + (λ _, barrier_res γ Ψ2)%I with "[-$Hh]"). iSplitL "H1"; [|iSplitL "H2"]. + iApply worker_spec; auto. + iApply worker_spec; auto. diff --git a/tests/list_reverse.v b/tests/list_reverse.v index 2e130b39e04d139ba213a52ce656187b3374e6cb..93a83113d5ef4a5164075ff3b044344aaf65b8ad 100644 --- a/tests/list_reverse.v +++ b/tests/list_reverse.v @@ -47,7 +47,7 @@ Lemma rev_wp hd xs (Φ : val → iProp Σ) : ⊢ WP rev hd (InjL #()) {{ Φ }}. Proof. iIntros "(#Hh & Hxs & HΦ)". - iApply (rev_acc_wp hd NONEV xs []); iFrame "Hh Hxs". + iApply (rev_acc_wp hd NONEV xs [] with "[- $Hh $Hxs]"). iSplit; first done. iIntros (w). rewrite right_id_L. iApply "HΦ". Qed. End list_reverse. diff --git a/tests/one_shot.v b/tests/one_shot.v index a7e8cc36440914c1c3484c4e153456705efae443..aaeeaf2b20d2ae5b5136bfbfb8ab35b661abdd88 100644 --- a/tests/one_shot.v +++ b/tests/one_shot.v @@ -94,6 +94,6 @@ Proof. iIntros (f1 f2) "[#Hf1 #Hf2]"; iSplit. - iIntros (n) "!# _". wp_proj. iApply "Hf1". - iIntros "!# _". wp_proj. - iApply wp_wand_l; iFrame "Hf2". by iIntros (v) "#? !# _". + iApply (wp_wand_r with "[- $Hf2]"). by iIntros (v) "#? !# _". Qed. End proof. diff --git a/tests/tree_sum.v b/tests/tree_sum.v index 63cafec1f806f0f1c5386ac1f8f1abf34f0ab36d..4fec2a4f51f63caca261da7fb61f9c227a618fec 100644 --- a/tests/tree_sum.v +++ b/tests/tree_sum.v @@ -62,7 +62,7 @@ Lemma sum_wp `{!heapG Σ} v t Φ : Proof. iIntros "(#Hh & Ht & HΦ)". rewrite /sum' /=. wp_let. wp_alloc l as "Hl". wp_let. - wp_apply sum_loop_wp; iFrame "Hh Ht Hl". + wp_apply (sum_loop_wp with "[- $Hh $Ht $Hl]"). rewrite Z.add_0_r. iIntros "Hl Ht". wp_seq. wp_load. by iApply "HΦ". Qed.