Repository navigation
Merge export * tables without per-name collision trackers - #64722
Draft
Gavin Kline (gwkline) wants to merge 2 commits into
Draft
Gavin Kline (gwkline) wants to merge 2 commits into
Gavin Kline (gwkline) wants to merge 2 commits into
Conversation
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The optimization changes core recursive module-export resolution and warrants final human validation despite strong regression coverage.
0 open findings
What changed in this PR
Optimizes compiler resolution of export * tables while preserving collision and type-only export semantics.
Changes:
- Merges re-export tables directly with preallocated capacity.
- Defers collision tracking and diagnostic text creation.
- Adds comprehensive compiler regression coverage and baselines.
| File | Description |
|---|---|
tsc/internal/checker/checker.go |
Optimizes export-table merging and collision tracking. |
tsc/testdata/tests/cases/compiler/exportStarNameCollisions.ts |
Adds export-star collision scenarios. |
tsc/testdata/baselines/reference/compiler/exportStarNameCollisions.errors.txt |
Captures expected diagnostics. |
tsc/testdata/baselines/reference/compiler/exportStarNameCollisions.js |
Captures emit and declarations. |
tsc/testdata/baselines/reference/compiler/exportStarNameCollisions.symbols |
Captures resolved symbols. |
tsc/testdata/baselines/reference/compiler/exportStarNameCollisions.types |
Captures inferred types. |
🧠 Review effort: Balanced
💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.
Author
|
@microsoft-github-policy-service agree |
getExportsOfModuleWorker allocated an ExportCollision struct for every name contributed by every export * declaration, kept the names in a separate table before merging them, and then iterated that table once more to look for duplicates. For modules that re-export large modules this dominated the allocations of module export resolution. The merge now writes straight into the module's table, records only the first contributing declaration per name and only when a module has more than one export * declaration, and keeps the names that collided in a map that is usually empty. Modules without export * declarations no longer have their tables cloned when visited from an importer, and the names used to undo type-only marking are collected only when an 'export type *' was seen. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Covers the cases the export * merge distinguishes: colliding names from two and three declarations, the same symbol reached twice, a module's own export silencing the collision, a single export *, export type * on either side, and a chain of re-exporting modules. Baselines were generated before the merge was rewritten and are unchanged by it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Gavin Kline (gwkline)
force-pushed
the
perf/export-star-tables
branch
from
October 10, 2026 21:39
f405731 to
3414ad3
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #64719
Analysis
For each module with
export *,getExportsOfModuleWorkercloned the module's own table and every visited module's table. It merged each re-exported table into a scratch table, and allocated anExportCollisionrecord for every distinct re-exported name so it could report TS2308 later. It then walked that table again to find collisions and merged the scratch table into the result. It also copied every visited module's export names into a set that only mattered when anexport type *was present.So every
export *layer cost several allocations per re-exported name, even with a singleexport *, where nothing can collide. Barrels over large modules (generated clients, ordate-fns- and AWS-SDK-style entry points) pay this at every layer. The generator in the issue spends most of its check time here.Fix
getExportsWithExportStars). The table is pre-sized for the module's own exports plus its largest re-exported table, so barrels that re-export the same names through many modules don't over-allocate.export *. It records the first contributing declaration per name, and names that actually collide go into a map that is almost always empty.export *are no longer cloned when visited from an importer, since their tables are only read during the merge. The top-level module's table is still cloned, because it is cached and the CommonJSexport=typedef loop writes into it.typeOnlyExportStarMaponly when that map exists.ExportCollision,ExportCollisionTableandextendExportSymbolshad no other users and are removed.Semantics
Unchanged. The first contributing
export *still wins. A module's own exports still shadow re-exports without an error.defaultis skipped,export=is never reported as TS2308, and theexport type */export *override rules are the same.New test
exportStarNameCollisionscovers:export *export type *on either sideIts baselines were generated with the old code and are unchanged. No existing baseline changes.
Results
M3 Pro, medians of alternating runs:
The profiling, the patch and this description were produced with Claude Code (Claude Fable 5.1 and Claude Opus 5.5). I have read and understand the change and will handle review myself.
Copilot Checklist
I successfully ran the applicable command at the end of my session, and it completed without error:
🤖 Generated with Claude Code