Skip to content

Speed up narrowing of literal unions - #64044

Open
Jake Bailey (jakebailey) wants to merge 2 commits into
microsoft:mainfrom
jakebailey:fix-55948
Open

Speed up narrowing of literal unions#64044
Jake Bailey (jakebailey) wants to merge 2 commits into
microsoft:mainfrom
jakebailey:fix-55948

Conversation

@jakebailey

Copy link
Copy Markdown
Member

Fixes #55948

Version User CPU Wall time
Base 10.8–12.1 s 6.9–8.4 s
fix-55948 0.08–0.09 s 0.07–0.10 s

We'll see if this hurts too much elsewhere

Narrowing a union by a type predicate maps every source constituent
over every candidate constituent through the general type relation
machinery. Large generated literal unions therefore take quadratic
time even though matching literals only requires equality.

Intersect unions made entirely of non-enum literals using keyed sets.
Keep enum and mixed unions on the existing relation path because they
require broader assignability semantics. Also bypass relation work for
individual identical literals encountered by that fallback path.

Add coverage for narrowing mixed string and number literal unions,
including equal-valued literals of different primitive kinds.

Fixes microsoft#55948
Copilot AI balanced review requested due to automatic review settings August 26, 2026 22:59
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Aug 26, 2026

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

Optimizes literal-union narrowing for type predicates using direct literal comparisons and lookup-based filtering.

Changes:

  • Adds a fast path for non-enum literal unions.
  • Adds direct literal comparison during narrowing.
  • Adds a compiler regression test and baselines.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tsc/internal/checker/flow.go Implements literal-union narrowing optimizations.
tsc/testdata/tests/cases/compiler/narrowLiteralUnionByTypePredicate.ts Adds the regression test.
tsc/testdata/baselines/reference/compiler/narrowLiteralUnionByTypePredicate.types Records narrowed types.
tsc/testdata/baselines/reference/compiler/narrowLiteralUnionByTypePredicate.symbols Records symbol resolution.
tsc/testdata/baselines/reference/compiler/narrowLiteralUnionByTypePredicate.js Records emitted JavaScript.

💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +928 to +933
if tLiteralFlags != 0 && tLiteralFlags == nLiteralFlags && !(t.flags&TypeFlagsEnumLiteral != 0 && n.flags&TypeFlagsEnumLiteral != 0) {
if t.AsLiteralType().value == n.AsLiteralType().value {
return t
}
return c.neverType
}
The per-literal fast path compared values and retained the source
constituent. When a plain string literal was narrowed by a predicate
whose candidate was the matching enum member, this lost the enum type
and made the result unassignable to that string enum member.

Retain the candidate when it carries enum identity and the source does
not. Continue using the existing relation machinery when both sides are
enum members, where equal underlying values are not sufficient.

Add a string-enum predicate regression that requires the narrowed value
to remain assignable to the asserted enum member.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Not started

Development

Successfully merging this pull request may close these issues.

Performance regression from #49625 and #52984

2 participants