Skip to content

perf: derive Repr, BEq and Hashable once per mutual block - #16339

Merged
Kha merged 9 commits into
masterfrom
derive-repr-mutual-once
Nov 7, 2026
Merged

Kha merged 9 commits into
masterfrom
derive-repr-mutual-once

Conversation

@Kha

@Kha Kha commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

This PR makes deriving Repr, BEq and Hashable on a mutual block generate their auxiliary functions once for the whole block instead of once per type, removing quadratic elaboration cost on large mutual blocks.

These handlers already receive all types of a mutual block in one call, but previously ran mkContext for each of them, and each run builds aux functions for every type in the block. They now group the requested types by mutual block (groupByMutualBlock), build one aux-function block per group, and emit an instance for each requested type. mkInstanceCmds names each instance after its own type; the other derive handlers pass a single type, so their instance names are unchanged. The @[no_expose] aux functions of a block derived together are now all named after the first type's instance.

On a 76-type mutual block deriving one class on every type:

class before after
Repr 309 s, 10.2 GB 62 s, 1.3 GB
BEq 242 s, 9.0 GB 45 s, 1.3 GB
Hashable 187 s, 9.2 GB 40 s, 1.3 GB

This PR makes `deriving Repr` on a mutual block generate the auxiliary functions once for the whole block instead of once per type, which removes quadratic elaboration cost on large mutual blocks.

`mkReprInstanceHandler` now groups the requested types by mutual block, builds one aux-function block per group and emits an instance for each requested type. `mkInstanceCmds` names each instance after its own type, which leaves instance names of the other derive handlers unchanged since they pass a single type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Kha Kha added the downstream Request a downstream-lean4 adaptation PR. label Nov 7, 2026
@downstream-lean4

Copy link
Copy Markdown

The merge base of this PR does not coincide with branch downstream-green. Please rebase this PR onto downstream-green and force-push. Alternatively, if downstream-green is further ahead than this PR, you can also merge it into this PR.

Kha and others added 2 commits November 7, 2026 18:55
This PR makes `deriving BEq` on a mutual block generate the auxiliary functions once for the whole block instead of once per type, which removes quadratic elaboration cost on large mutual blocks.

`mkBEqInstanceHandler` now groups the requested types by mutual block and runs `mkBEqInstance` once per group, which emits an instance for each requested type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This PR makes `deriving Hashable` on a mutual block generate the auxiliary functions once for the whole block instead of once per type, which removes quadratic elaboration cost on large mutual blocks.

`mkHashableHandler` now groups the requested types by mutual block, builds one aux-function block per group and emits an instance for each requested type.

Co-Authored-By: Claude Opus 5.5 <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 Nov 7, 2026
@Kha Kha changed the title perf: derive Repr once per mutual block perf: derive Repr, BEq and Hashable once per mutual block Nov 7, 2026
Kha and others added 6 commits November 7, 2026 19:36
…own name

`mkBEqInstance` now attaches `@[method_specs]` to the instance of every requested type instead of `ctx.instName`, so it no longer relies on a non-`partial` context covering a single type. The names are computed before the instances are added, since `mkInstName` picks names that are still free.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `Repr`, `BEq` and `Hashable` handlers now wrap a whole mutual-block group with `withoutExposeFromCtorsAll` instead of folding `withoutExposeFromCtors` over a separately bound continuation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The `Repr`, `BEq` and `Hashable` mutual-block tests now record the handler's trace with `#guard_msgs`, which shows the single generated block directly, instead of probing the environment for aux-function names.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The benchmark derives `Repr`, `BEq` and `Hashable` on a mutual block with a 40-constructor hub (10 in the test suite), which is quadratic if a handler generates the block's auxiliary functions once per type.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@Kha
Kha marked this pull request as ready for review November 7, 2026 20:13
@Kha
Kha requested a review from kim-em as a code owner November 7, 2026 20:13
@Kha
Kha enabled auto-merge November 7, 2026 20:13
@Kha
Kha added this pull request to the merge queue Nov 7, 2026
Merged via the queue into master with commit f063abb Nov 7, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

downstream Request a downstream-lean4 adaptation PR. 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.

1 participant