Skip to content

fix: tail-recursive BitVec.ofBoolListLE/ofBoolListBE to avoid stack overflow#13576

Draft
kim-em wants to merge 3 commits intoleanprover:masterfrom
kim-em:scott-fix-ofBoolListLE-stack-overflow
Draft

fix: tail-recursive BitVec.ofBoolListLE/ofBoolListBE to avoid stack overflow#13576
kim-em wants to merge 3 commits intoleanprover:masterfrom
kim-em:scott-fix-ofBoolListLE-stack-overflow

Conversation

@kim-em
Copy link
Copy Markdown
Collaborator

@kim-em kim-em commented Apr 29, 2026

This PR adds tail-recursive replacements for BitVec.ofBoolListLE and BitVec.ofBoolListBE, registered via @[csimp], to avoid stack overflow on lists with ~1M elements.

The reference definitions in Init.Data.BitVec.Basic recurse via concat, which is clean for proofs but allocates O(n) stack frames. The new implementations in Init.Data.BitVec.Impl pack bits in 64-bit chunks (packChunk, collectChunks) and combine them via a balanced tree merge (mergePass, treeMerge), giving O(n log n) work and O(1) stack usage.

Correctness is established via a list-level spec function flattenList giving the intended Nat semantics of (value, width) pairs, with flattenList_append, flattenList_mergePassList (key bit-packing identity), and a chunk-local testBit_flattenList_collectChunks_aux. The two @[csimp] theorems chain through BitVec.eq_of_getLsbD_eq and the existing getLsbD_ofBoolListLE/getLsbD_ofBoolListBE characterizations.

🤖 Prepared with Claude Code

…ck overflow

This PR adds tail-recursive replacements for `BitVec.ofBoolListLE` and
`BitVec.ofBoolListBE`, registered via `@[csimp]`, to avoid stack overflow
on lists with ~1M elements.

The reference definitions in `Init.Data.BitVec.Basic` recurse via `concat`,
which is clean for proofs but allocates O(n) stack frames. The new
implementations in `Init.Data.BitVec.Impl` pack bits in 64-bit chunks
(`packChunk`, `collectChunks`) and combine them via a balanced tree merge
(`mergePass`, `treeMerge`), giving O(n log n) work and O(1) stack usage.

Correctness is established via a list-level spec function `flattenList`
giving the intended Nat semantics of `(value, width)` pairs, with
`flattenList_append`, `flattenList_mergePassList` (key bit-packing
identity), and a chunk-local `testBit_flattenList_collectChunks_aux`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN label Apr 29, 2026
@mathlib-lean-pr-testing
Copy link
Copy Markdown

Mathlib CI status (docs):

  • ❗ Mathlib CI can not be attempted yet, as the nightly-testing-2026-04-29 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-mathlib, Mathlib CI should run now. You can force Mathlib CI using the force-mathlib-ci label. (2026-04-29 14:47:34)

@leanprover-bot
Copy link
Copy Markdown
Collaborator

Reference manual CI status:

  • ❗ Reference manual CI can not be attempted yet, as the nightly-testing-2026-04-29 tag does not exist there yet. We will retry when you push more commits. If you rebase your branch onto nightly-with-manual, reference manual CI should run now. You can force reference manual CI using the force-manual-ci label. (2026-04-29 14:47:35)

kim-em and others added 2 commits April 30, 2026 10:01
….Internal`

Codex review feedback applied:
- Mark `packChunk`, `collectChunks`, `mergePass`, `treeMerge` as `private` —
  these have unreachable-fuel branches that make them bad public contracts.
- Mark proof-only scaffolding (`flattenList`, `totalWidth`, `WellFormedList`,
  `mergePassList`) as `private` to avoid exposing them as API.
- Extract `half_le_pow_of_le_double` (the `arr.size ≤ 2^(k+1) → (arr.size+1)/2 ≤ 2^k`
  bound used in the `treeMerge` halving step) into a standalone lemma. This
  isolates the omega/`Int.pow_succ` workaround to one place and turns
  `treeMerge_go_eq_flattenList`'s arithmetic step into a one-liner.

Public surface is now just `ofBoolListLEImpl`, `ofBoolListBEImpl`, and the two
`@[csimp]` theorems.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the file-wide `public section` with `public` modifiers on just the
two `ofBoolListLEImpl`/`ofBoolListBEImpl` defs and the two `@[csimp]` theorems.
Everything else (the chunked-encoding helpers `packChunk`, `collectChunks`,
`mergePass`, `treeMerge`, the proof-only `flattenList`/`totalWidth`/
`WellFormedList`/`mergePassList`, and all auxiliary lemmas) is now file-local.

Also drop redundant imports `Init.Data.Nat.Lemmas` (transitive via
`Init.Data.Array.Lemmas`) and `Init.Data.List.Lemmas` (transitive via
`Init.Data.List.Nat.TakeDrop`).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

toolchain-available A toolchain is available for this PR, at leanprover/lean4-pr-releases:pr-release-NNNN

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants