Repository navigation
Cache inferences made from type arguments - #64553
Conversation
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
The cache key omits propagation state, and the performance regression lacks direct test coverage.
Review effort: Balanced
Findings: 1
Open (2)
What changed in this PR
Caches type-argument inference for matching aliases and generic references to prevent exponential checking.
Changes:
- Extends inference cache keys with variance and priority state.
- Routes alias/reference inference through
invokeOnce. - Updates correlated-union tests for corrected inference behavior.
| File | Description |
|---|---|
tsc/internal/checker/inference.go |
Implements expanded inference caching. |
tsc/testdata/tests/cases/compiler/correlatedUnions.ts |
Uses NoInfer to preserve intended inference. |
tsc/testdata/baselines/reference/compiler/correlatedUnions.types |
Updates type baseline. |
tsc/testdata/baselines/reference/compiler/correlatedUnions.symbols |
Updates symbol baseline. |
tsc/testdata/baselines/reference/compiler/correlatedUnions.js |
Updates emit baseline. |
| // between the same pair of types. | ||
| func (c *Checker) invokeOnce(n *InferenceState, source *Type, target *Type, action func(c *Checker, n *InferenceState, source *Type, target *Type)) { | ||
| key := InferenceKey{s: source.id, t: target.id} | ||
| key := InferenceKey{source: source.id, target: target.id, priority: n.priority, contravariant: n.contravariant, bivariant: n.bivariant} |
| case source.objectFlags&ObjectFlagsReference != 0 && target.objectFlags&ObjectFlagsReference != 0 && (source.AsTypeReference().target == target.AsTypeReference().target || c.isArrayType(source) && c.isArrayType(target)) && !(source.AsTypeReference().node != nil && target.AsTypeReference().node != nil): | ||
| // If source and target are references to the same generic type, infer from type arguments | ||
| c.inferFromTypeArguments(n, c.getTypeArguments(source), c.getTypeArguments(target), c.getVariances(source.AsTypeReference().target)) | ||
| c.invokeOnce(n, source, target, (*Checker).inferFromReferenceTypeArguments) |
|
Oleksandr Tarasiuk (@a-tarasyuk) I have manually verified that this has the same effect on check times for the original repro and the test you included in #64388. Can you describe what goes on in that test? I'd like to understand before we include it. |
|
TypeScript Bot (@typescript-bot) test it |
|
Anders Hejlsberg (@ahejlsberg), the perf run you requested failed. You can check the log here. |
|
Hey Anders Hejlsberg (@ahejlsberg), the results of running the DT tests are ready. Everything looks the same! |
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the user tests with tsc comparing Something interesting changed - please have a look. Details
|
|
Anders Hejlsberg (@ahejlsberg) Here are the results of running the top 400 repos with tsc comparing Everything looks good! |
|
TypeScript Bot (@typescript-bot) perf test this faster |
|
The change in the webpack user test is simply that we're inferring a different type now that there aren't dropped inferences. The errors themselves are actually follow-on errors from other issues in webpack (specifically here that use of values as types now require explicit |
|
Anders Hejlsberg (@ahejlsberg) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||


With this PR we cache inferences made from type arguments of references to the same alias or class/interface. The PR supersedes #64388 which implements similar caching, but does so through a separate cache instead of leveraging the existing
invokeOncecaching infrastructure.The PR fixes an issue with the existing cache where
priority,contravariant, andbivariantstates weren't included in the cache key. This would cause false matches and lead to dropped inferences. This fix revealed a test case incorrelatedUnions.tsthat incorrectly depended on dropped inferences and now requires use ofNoInfer<T>. The issue can be observed by the error in this version of the test that simply reverses the declaration order ofletterandcallerin theLetterCallertype.Thanks Oleksandr Tarasiuk (@a-tarasyuk) for researching the root cause and fix for the issue in #64378.
Fixes #64378.