Repository navigation
Avoid allocations and no-op work during type inference - #65036
Jake Bailey (jakebailey) wants to merge 3 commits into
Conversation
Inferring to a target that cannot contain type variables is a no-op: inferFromTypes bails out immediately. Several callers nevertheless did all the work of producing the source side of such a pair before discovering this, e.g. resolving the source parameter or property type, or the source signatures and index infos. Check the target first in applyToParameterTypes, applyToReturnTypes, and inferFromProperties, and only compute the source type when the target could receive inferences. Likewise, look up target signatures and index infos before the source's, and stop early when there are none, since nothing would be inferred from the source anyway. Co-authored-by: Steven Chong <25894545+teamchong@users.noreply.github.com>
When a higher priority inference is made for a type parameter, its existing candidates are discarded. Setting the slices to nil threw away their backing arrays, so the following appends had to allocate and grow new ones from scratch. Truncate the slices instead so the existing capacity is reused. The old elements are cleared first so the discarded candidate types are not kept alive by the backing array. Candidate slices are never shared between inference infos (clones copy them), so reusing them in place is safe. Co-authored-by: Steven Chong <25894545+teamchong@users.noreply.github.com>
Several inference helpers build small temporary slices that never outlive the call: the matched sources and targets in inferFromMatchingTypes, the single-element source list, matched flags, and unmatched sources in inferToMultipleTypes, and the true/false branch pair in inferToConditionalType. These run for nearly every union and conditional type inference, and each one cost a heap allocation. Back these slices with small fixed-size arrays so the common cases stay on the stack, falling back to the heap only when they grow past the buffer. Co-authored-by: Steven Chong <25894545+teamchong@users.noreply.github.com>
There was a problem hiding this comment.
🟢 Approval recommended
There are no active review issues for the type-inference optimizations.
No open issues 🎉
What changed in this PR
This PR reduces allocation overhead and unnecessary work in the native TypeScript compiler’s type inference.
Changes:
- Reuses candidate slice capacity and adds fixed-size buffers for temporary collections.
- Skips selected inference work when target types cannot contain type variables.
- Returns early when targets have no relevant signatures or index information.
| File | Description |
|---|---|
tsc/internal/checker/inference.go |
Optimizes temporary storage and avoids unnecessary type resolution and inference calls. |
Review effort: Balanced
|
One or more custom setup steps configured for this repository failed during this Copilot code review run: Setup steps run before each review. If the review above is missing context, or no review was posted at all, the failing step above may be the cause. See the workflow run for failure details, fix your setup steps configuration, and re-request a review. Note You can configure setup steps for Copilot code review separately from Copilot cloud agent with a |
|
TypeScript Bot (@typescript-bot) perf test this faster |
|
Jake Bailey (@jakebailey) Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Thanks Steven (@teamchong) for finding these!