Skip to content

Use trie for removeStringLiteralsMatchedByTemplateLiterals - #3331

Open
Sebastian "Sebbie" Silbermann (eps1lon) wants to merge 1 commit into
microsoft:mainfrom
eps1lon:sebbie/ftl/batched-removal
Open

Use trie for removeStringLiteralsMatchedByTemplateLiterals#3331
Sebastian "Sebbie" Silbermann (eps1lon) wants to merge 1 commit into
microsoft:mainfrom
eps1lon:sebbie/ftl/batched-removal

Conversation

@eps1lon

@eps1lon Sebastian "Sebbie" Silbermann (eps1lon) commented Apr 2, 2026

Copy link
Copy Markdown
Contributor

Fixes microsoft/TypeScript#63342

Port of microsoft/TypeScript#63343
Fixes microsoft/TypeScript#63342

Actual implementation is vibe-coded with Claude Opus 4.6 (1M context)

@eps1lon
Sebastian "Sebbie" Silbermann (eps1lon) marked this pull request as ready for review April 2, 2026 20:19
Copilot AI review requested due to automatic review settings April 2, 2026 20:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR ports the TypeScript change to speed up removeStringLiteralsMatchedByTemplateLiterals by indexing template-literal patterns by their leading text, reducing repeated full scans when pruning redundant string-literal constituents during union reduction.

Changes:

  • Introduces an internal trie node type for indexing template-literal prefixes.
  • Adds trie construction + lookup helpers to find a matching template literal efficiently.
  • Refactors removeStringLiteralsMatchedByTemplateLiterals to use the trie (when beneficial) and to separately handle template literals vs string-mapping patterns.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated no comments.

File Description
internal/checker/types.go Adds templateLiteralTrieNode type to support prefix trie indexing.
internal/checker/relater.go Adds trie build + lookup helpers that leverage texts[0] as the prefix key for template-literal matching.
internal/checker/checker.go Refactors string-literal pruning to use trie-based matching for template literals and preserves string-mapping handling.

Optimize removeStringLiteralsMatchedByTemplateLiterals by building a
prefix trie from TemplateLiteralType patterns and using O(L) trie
traversal per string literal instead of O(m) linear scan across all
templates. StringMappingType templates (which cannot be trie-indexed)
are checked separately.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
}

func (c *Checker) buildTemplateLiteralTrieFromTypes(templateTypes []*Type) *templateLiteralTrieNode {
root := &templateLiteralTrieNode{}

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For this, you will probably benefit from using core.Arena to avoid a bunch of small allocs of these nodes, given they're all generated once in this func. Can just write var arena core.Arena[templateLiteralTrieNode] and then do arena.New() instead of &templateLiteralTrieNode{}.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ugh, so, I never hit send on this :(

@jakebailey

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) perf test this faster

@typescript-automation

typescript-automation Bot commented Aug 14, 2026

Copy link
Copy Markdown

Starting jobs; this comment will be updated as builds start and complete.

Command Status Results
perf test this faster ✅ Started 👀 Results

@typescript-automation

Copy link
Copy Markdown

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-Unions - native
Errors 41 41 ~ ~ ~ p=1.000 n=12
Symbols 115,480 115,480 ~ ~ ~ p=1.000 n=12
Types 96,945 96,945 ~ ~ ~ p=1.000 n=12
Memory Used 149,702k (± 0.47%) 149,080k (± 0.63%) ~ 147,286k 151,414k p=0.266 n=12
Memory Allocs 2,247,386 (± 0.01%) 2,247,351 (± 0.00%) ~ 2,247,198 2,247,572 p=0.943 n=12
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Parse Time 0.040s (± 3.03%) 0.040s (± 4.27%) ~ 0.036s 0.044s p=0.676 n=12
Bind Time 0.013s (±13.37%) 0.012s (±11.58%) ~ 0.010s 0.018s p=0.697 n=12
Check Time 0.506s (± 0.73%) 0.504s (± 0.58%) ~ 0.497s 0.511s p=0.466 n=12
Emit Time 0.270s (± 2.15%) 0.271s (± 2.39%) ~ 0.259s 0.292s p=0.744 n=12
Total Time 0.836s (± 0.73%) 0.834s (± 0.77%) ~ 0.822s 0.858s p=0.619 n=12
angular-1 - native
Errors 3 3 ~ ~ ~ p=1.000 n=12
Symbols 846,772 (± 0.11%) 846,936 (± 0.09%) ~ 844,433 848,311 p=0.932 n=12
Types 249,915 (± 0.00%) 249,912 (± 0.00%) ~ 249,910 249,914 p=0.717 n=12
Memory Used 793,279k (± 0.09%) 793,597k (± 0.07%) ~ 792,454k 795,260k p=0.478 n=12
Memory Allocs 13,038,229 (± 0.05%) 13,038,941 (± 0.06%) ~ 13,030,261 13,076,325 p=0.977 n=12
Config Time 0.016s (± 1.13%) 0.016s ~ ~ ~ p=1.000 n=12
Parse Time 0.283s (± 2.55%) 0.281s (± 1.77%) ~ 0.263s 0.291s p=0.401 n=12
Bind Time 0.063s (±15.23%) 0.064s (±17.12%) ~ 0.057s 0.119s p=0.741 n=12
Check Time 0s 0s ~ ~ ~ p=1.000 n=12
Emit Time 1.644s (± 1.07%) 1.649s (± 1.16%) ~ 1.616s 1.719s p=0.853 n=12
Total Time 2.021s (± 1.17%) 2.027s (± 1.32%) ~ 1.983s 2.135s p=0.799 n=12
mui-docs - native
Errors 11,278 (± 0.02%) 11,279 (± 0.02%) ~ 11,273 11,282 p=0.853 n=12
Symbols 4,230,792 4,230,792 ~ ~ ~ p=1.000 n=12
Types 1,591,020 1,591,020 ~ ~ ~ p=1.000 n=12
Memory Used 4,853,578k (± 0.03%) 4,853,389k (± 0.03%) ~ 4,850,141k 4,857,558k p=0.977 n=12
Memory Allocs 48,413,484 (± 0.04%) 48,414,099 (± 0.04%) ~ 48,369,012 48,462,483 p=0.887 n=12
Config Time 0.019s 0.019s ~ ~ ~ p=1.000 n=12
Parse Time 0.678s (± 1.90%) 0.673s (± 1.82%) ~ 0.637s 0.695s p=0.639 n=12
Bind Time 0.003s (±13.14%) 0.003s (±29.74%) ~ 0.002s 0.007s p=0.729 n=12
Check Time 18.768s (± 0.73%) 18.673s (± 0.77%) ~ 18.262s 18.979s p=0.291 n=12
Emit Time 0.526s (± 0.34%) 0.528s (± 0.24%) ~ 0.524s 0.531s p=0.097 n=12
Total Time 20.932s (± 0.74%) 20.832s (± 0.80%) ~ 20.326s 21.183s p=0.298 n=12
strada-build-src - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 1,394,411 1,394,411 ~ ~ ~ p=1.000 n=12
Types 443,627 443,627 ~ ~ ~ p=1.000 n=12
Memory Used 1,643,434k (± 0.27%) 1,644,158k (± 0.18%) ~ 1,634,080k 1,651,711k p=0.713 n=12
Memory Allocs 96,911,809 (± 0.04%) 96,920,143 (± 0.02%) ~ 96,875,224 96,998,710 p=0.410 n=12
Config Time 0.003s (±12.29%) 0.003s (±18.37%) ~ 0.002s 0.004s p=0.601 n=12
Parse Time 0.198s (± 3.14%) 0.194s (± 3.47%) ~ 0.177s 0.207s p=0.354 n=12
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Check Time 1.824s (± 0.37%) 1.814s (± 0.63%) ~ 1.788s 1.848s p=0.110 n=12
Emit Time 0.304s (± 3.62%) 0.290s (± 5.41%) ~ 0.242s 0.319s p=0.242 n=12
Total Time 25.262s (± 0.71%) 25.070s (± 0.52%) ~ 24.801s 25.438s p=0.089 n=12
strada-compiler - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 337,618 337,618 ~ ~ ~ p=1.000 n=12
Types 198,941 198,941 ~ ~ ~ p=1.000 n=12
Memory Used 319,619k (± 0.03%) 319,602k (± 0.03%) ~ 319,237k 319,852k p=0.876 n=12
Memory Allocs 4,660,721 (± 0.01%) 4,660,791 (± 0.01%) ~ 4,659,573 4,663,002 p=0.887 n=12
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=12
Parse Time 0.116s (± 4.61%) 0.118s (± 4.34%) ~ 0.102s 0.131s p=0.744 n=12
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Check Time 1.056s (± 0.45%) 1.045s (± 0.49%) -0.012s (- 1.10%) 1.035s 1.058s p=0.002 n=12
Emit Time 0.156s (± 6.71%) 0.159s (± 8.81%) ~ 0.116s 0.185s p=0.640 n=12
Total Time 1.382s (± 0.92%) 1.378s (± 0.98%) ~ 1.341s 1.405s p=0.810 n=12
ts-pre-modules - native
Errors 87 87 ~ ~ ~ p=1.000 n=12
Symbols 305,341 305,341 ~ ~ ~ p=1.000 n=12
Types 182,038 182,038 ~ ~ ~ p=1.000 n=12
Memory Used 277,284k (± 0.03%) 277,320k (± 0.03%) ~ 277,058k 277,536k p=0.478 n=12
Memory Allocs 1,628,064 (± 0.01%) 1,628,199 (± 0.01%) ~ 1,627,594 1,628,613 p=0.347 n=12
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Parse Time 0.082s (± 4.59%) 0.081s (± 5.15%) ~ 0.070s 0.092s p=0.599 n=12
Bind Time 0.027s (±11.04%) 0.030s (±10.97%) ~ 0.024s 0.039s p=0.336 n=12
Check Time 0.701s (± 0.59%) 0.700s (± 0.66%) ~ 0.691s 0.713s p=0.521 n=12
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Total Time 0.824s (± 0.53%) 0.822s (± 0.61%) ~ 0.813s 0.843s p=0.417 n=12
vscode - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 7,731,630 7,731,630 ~ ~ ~ p=1.000 n=12
Types 2,662,693 2,662,693 ~ ~ ~ p=1.000 n=12
Memory Used 5,225,839k (± 0.01%) 5,226,491k (± 0.01%) ~ 5,224,530k 5,228,209k p=0.128 n=12
Memory Allocs 40,495,184 (± 0.03%) 40,504,966 (± 0.04%) +9,783 (+ 0.02%) 40,489,351 40,568,823 p=0.024 n=12
Config Time 0.061s (± 0.53%) 0.061s (± 0.53%) ~ 0.060s 0.062s p=0.246 n=12
Parse Time 1.612s (± 1.34%) 1.572s (± 2.16%) ~ 1.467s 1.663s p=0.058 n=12
Bind Time 0.331s (± 0.77%) 0.368s (±15.81%) ~ 0.326s 0.613s p=0.578 n=12
Check Time 9.836s (± 0.18%) 9.734s (± 1.27%) ~ 9.293s 9.855s p=0.117 n=12
Emit Time 2.919s (± 0.55%) 3.163s (±10.38%) ~ 2.851s 4.302s p=0.855 n=12
Total Time 14.838s (± 0.24%) 14.981s (± 1.60%) ~ 14.713s 15.839s p=0.810 n=12
webpack - native
Errors 2 2 ~ ~ ~ p=1.000 n=12
Symbols 1,380 1,380 ~ ~ ~ p=1.000 n=12
Types 340 340 ~ ~ ~ p=1.000 n=12
Memory Used 194,373k (± 0.06%) 194,409k (± 0.08%) ~ 193,987k 194,871k p=0.682 n=12
Memory Allocs 824,276 (± 0.39%) 823,060 (± 0.16%) ~ 819,985 827,603 p=0.671 n=12
Config Time 0.008s 0.008s ~ ~ ~ p=1.000 n=12
Parse Time 0.205s (± 2.14%) 0.204s (± 2.22%) ~ 0.193s 0.215s p=0.989 n=12
Bind Time 0s 0s ~ ~ ~ p=1.000 n=12
Check Time 0s 0s ~ ~ ~ p=1.000 n=12
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Total Time 0.213s (± 2.08%) 0.212s (± 2.13%) ~ 0.201s 0.223s p=0.876 n=12
xstate-main - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 1,020,005 1,020,005 ~ ~ ~ p=1.000 n=12
Types 376,891 376,891 ~ ~ ~ p=1.000 n=12
Memory Used 603,425k (± 0.01%) 603,422k (± 0.02%) ~ 603,007k 603,579k p=0.713 n=12
Memory Allocs 4,749,823 (± 0.03%) 4,748,527 (± 0.04%) ~ 4,745,006 4,752,302 p=0.198 n=12
Config Time 0.003s 0.003s ~ ~ ~ p=1.000 n=12
Parse Time 0.146s (± 3.23%) 0.143s (± 2.65%) ~ 0.136s 0.156s p=0.339 n=12
Bind Time 0.040s (±18.20%) 0.042s (±15.26%) ~ 0.032s 0.065s p=0.425 n=12
Check Time 1.080s (± 0.85%) 1.085s (± 0.85%) ~ 1.059s 1.103s p=0.259 n=12
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Total Time 1.277s (± 0.85%) 1.286s (± 1.10%) ~ 1.257s 1.313s p=0.311 n=12
System info unknown
Hosts
  • native
Scenarios
  • Compiler-Unions - native
  • angular-1 - native
  • mui-docs - native
  • strada-build-src - native
  • strada-compiler - native
  • ts-pre-modules - native
  • vscode - native
  • webpack - native
  • xstate-main - native
Benchmark Name Iterations
Current pr 12
Baseline baseline 12

Developer Information:

Download Benchmarks

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.

type checking complexity with multiple template literals in unions

4 participants