Skip to content

feat: port HeapLang heap tactics#521

Open
kdvkrs wants to merge 3 commits into
leanprover-community:masterfrom
kdvkrs:feat/heaplang-heap-tactics
Open

feat: port HeapLang heap tactics#521
kdvkrs wants to merge 3 commits into
leanprover-community:masterfrom
kdvkrs:feat/heaplang-heap-tactics

Conversation

@kdvkrs

@kdvkrs kdvkrs commented Jul 16, 2026

Copy link
Copy Markdown

Description

Stacked on #516, the comments below pertain to this PR.

Partially addresses #480

This PR ports the heap-operation half of iris_heap_lang/proofmode.v: symbolic-execution tactics for the primitive heap operations, resolving points-to hypotheses from the spatial context. It involves two commits.

  • The first commit adds the tactics: wp_load, wp_store, wp_xchg, wp_faa, wp_free, wp_alloc, and wp_cmpxchg/wp_cmpxchg_suc/wp_cmpxchg_fail. Their signatures mirror the Rocq counterparts (wp_alloc l as H, wp_cmpxchg as H1 | H2). As in Rocq, every heap tactic first normalizes pure redexes.

    • The heap tactics build on shared machinery: runTacticHeapWp (prologue: wp_pures, WP-goal parsing, HeapLangGS extraction, one-later strip), lookupPointsTo (the envs_lookup analogue), and finishHeapOp (epilogue: refill the evaluation context, finish the continuation). The per-tactic bodies reduce to: match redex, look up, [possibly update], finish, assign.
    • Ownership discipline is enforced at lookup time: the expected fraction is a parameter baked into the split certificate's type. Writing operations pass DFrac.own 1 as their tac_wp_* lemmas demand full ownership syntactically while the reading operations (wp_load, wp_cmpxchg_fail) pass a metavariable that records whatever fraction is found. This allows a dedicated error message for the tactics that do not need full-ownership points-tos.
    • set_option trace.wp_heap true traces the tactic invocations (trace.wp_heap.redex / trace.wp_heap.lookup).
    • Tests cover the happy path per tactic, harder positives (points-to selection among candidates, -stripping, fractional load, redexes inside evaluation contexts), and #guard_msgs negatives locking the error messages.
  • The second commit migrates the HeapLang libraries (Spawn, SpinLock, LandinsKnot, Quicksort) to the new tactics.

Remarks

  • wp_apply / wp_smart_apply are planned for a follow-up PR.
  • wp_allocN needs array definitions in derived_laws.v.

The later-stripping is confined to a single call site in runTacticHeapWp, should the step handling of wp ever change shape upstream.

This is my first foray into Lean metaprogramming, so I would greatly appreciate feedback on Qq usage and helper factoring in particular.

AI disclosure: I used Claude Code (Opus 4.8 + Fable 5) to help navigate the codebase, get me started on metaprogramming, and write test boilerplate. All design decisions, the code, and the proofs were reviewed and are owned by me.

Checklist

  • My code follows the mathlib naming and code style conventions
  • I have added my name to the authors section of any appropriate files

kdvkrs added 3 commits July 16, 2026 17:10
Port the wp_pure wrapper tactic family from iris_heap_lang/proofmode.v:
wp_lam, wp_let, wp_seq, wp_closure, wp_if, wp_if_true, wp_if_false,
wp_proj, wp_inj, wp_pair, wp_unop, wp_binop, wp_op, wp_case, and wp_match.

The Lean implementation follows the Rocq implementation with these tactics being
thin wrappers around wp_pure.

Raise the precedence of wp_pure's focus argument to hl_exp:10 mirroring wp_bind. At default precedence, e.g. `wp_pure <pat>; wp_lam` misparses the focus pattern instead of sequencing.

Import PrimitiveLaws from HeapLang/ProofMode, since the wp_rec macro
expands to an application of the wp_rec lemma defined there.

Add a test section per tactic covering at least one successful and one failing case
Port the heap-operation half of iris_heap_lang/proofmode.v: wp_load,
wp_store, wp_xchg, wp_faa, wp_free, wp_alloc, and wp_cmpxchg{,_suc,_fail}.
Tactic signatures mirror Rocq (`wp_alloc l as H`, `wp_cmpxchg as H1 | H2`),
and every heap tactic first normalizes pure redexes (the `wp_pures;`
prefix in the Rocq notations).

The elaborators share three pieces of machinery:
- runTacticHeapWp (prologue): runs wp_pures, parses the WP goal, extracts
  the HeapLangGS instance, and strips one later off the hypotheses.
- lookupPointsTo: locates `l ↦{dq} some v` in the spatial context; the
  expected fraction is baked into the split certificate's type — writes
  pass the literal `DFrac.own 1`, reads a metavariable recording the
  fraction found.
- finishHeapOp (epilogue): fills the result value back into the
  evaluation context and finishes the continuation.

`set_option trace.wp_heap true` traces an invocation end to end.

Tests cover the happy paths, harder positives, and #guard_msgs negatives
locking the error messages and the writes' full-ownership discipline.
Replace the manual heap-op sequences in Spawn, SpinLock, LandinsKnot,
and Quicksort — wp_bind + iapply wp_<op> and their glue (rfl side goals,
imodintro, wp_finish, the wp_wand postcondition adaptor and compareSafe
simp battery around cmpXchg) — with the corresponding heap tactics.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant