Skip to content

Fix #25728: remove wasteful transform(call) in PostTyper Inlined handler#25729

Draft
soronpo wants to merge 1 commit intoscala:mainfrom
soronpo:fix/posttyper-inlined-exponential-compile-time
Draft

Fix #25728: remove wasteful transform(call) in PostTyper Inlined handler#25729
soronpo wants to merge 1 commit intoscala:mainfrom
soronpo:fix/posttyper-inlined-exponential-compile-time

Conversation

@soronpo
Copy link
Copy Markdown
Contributor

@soronpo soronpo commented Apr 8, 2026

Fixes #25728

PostTyper's Inlined handler called withMode(Mode.NoInline)(transform(call)) on every Inlined node, but the result was immediately discarded — the next line computes callTrace via inlineCallTrace (a minimal Ident) and uses that instead.

When transparent inline operations are chained (e.g., a + a + a + ...), each Inlined node's call field contains the full expansion of all previous operations (because inline parameters carry the entire previous tree). The call tree size grows exponentially with chain length. Since transform(call) recursively traverses this entire tree — encountering nested Inlined nodes that each trigger their own transform(call) — the total work grows exponentially, causing compile times to double with each additional operation.

Measured PostTyper times for the reproducer (Scala 3.7.1, before fix):

Chained additions PostTyper time
5 85ms
8 397ms
10 1.0s
12 4.0s
15 ~90s

The fix removes the transform(call) line entirely. The side-effecting check (CrossVersionChecks.checkRef) is already performed on the preceding line and does not require full tree transformation. The expansion's contents are validated by transform(expansion).

How much have you relied on LLM-based tools in this contribution?

Extensively. Claude Code (Claude Opus) was used to investigate the root cause (instrumenting PostTyper, analyzing tree structures, measuring compile times), create the minimal reproducer, and draft this PR. The human contributor directed the investigation, validated findings against the DFHDL project (where this bug caused 33s compile times for 8 chained additions), and reviewed all changes.

How was the solution tested?

  • A tests/pos regression test (i25728/) is included: a multi-file test with a transparent inline macro and 20 chained operations that would previously time out or take minutes to compile.
  • The fix was validated in the DFHDL project via an equivalent compiler plugin workaround (FlattenInlinedPhase.minimizeCall), which reduced 8-addition chains from 33s to 2s and enabled 20+ additions (previously impossible) to compile in 7s.
  • CI results from this draft PR will confirm whether any existing tests rely on the removed transform(call) side effects.

Additional notes

This is a draft PR to gauge CI reaction. If transform(call) turns out to have necessary side effects beyond CrossVersionChecks.checkRef (e.g., registerNeedsInlining on identifiers within the call tree), a more targeted fix could limit the transformation depth instead of removing it entirely.

… handler

PostTyper's Inlined handler called `withMode(Mode.NoInline)(transform(call))`
on every Inlined node, but the result was immediately discarded — the next
line computes `callTrace` via `inlineCallTrace` (a minimal Ident) and uses
that instead.

When transparent inline operations are chained (e.g., `a + a + a + ...`),
each Inlined node's `call` field contains the full expansion of all previous
operations (because inline parameters carry the entire previous tree). The
`call` tree size grows exponentially with chain length. Since `transform(call)`
recursively traverses this entire tree — encountering nested Inlined nodes
that each trigger their own `transform(call)` — the total work grows
exponentially, causing compile times to double with each additional operation.

The side-effecting check on the call (`CrossVersionChecks.checkRef`) is
already performed on the line above and does not require full tree
transformation. The expansion's contents are checked by `transform(expansion)`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

PostTyper: exponential compile time with chained transparent inline macro operations

1 participant