Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion tsc/internal/checker/relater.go
Original file line number Diff line number Diff line change
Expand Up @@ -3239,7 +3239,15 @@ func (r *Relater) structuredTypeRelatedTo(source *Type, target *Type, reportErro
// needs to have its constraint hoisted into an intersection with said type parameter, this way
// the type param can be compared with itself in the target (with the influence of its constraint to match other parts)
// For example, if `T extends 1 | 2` and `U extends 2 | 3` and we compare `T & U` to `T & U & (1 | 2 | 3)`
if result == TernaryFalse && (source.flags&TypeFlagsIntersection != 0 || source.flags&TypeFlagsTypeParameter != 0 && target.flags&TypeFlagsUnion != 0) {
// We skip the combined-constraint check while measuring variances. Variance
// measurement compares marker instantiations, and there the hoisted constraint may
// itself be an intersection with instantiable constituents (e.g. deferred conditional
// types, as produced by heavily overloaded generic builder types), so a failed
// comparison re-enters this logic with a structurally new and ever larger source
// that the relation cache and the deeply-nested-type guards never recognize as
// recursive, and the chase grows without bound (see microsoft/TypeScript#64423).
// The check never contributes to the measured relation between the marker types.
if result == TernaryFalse && len(r.c.varianceStack) == 0 && (source.flags&TypeFlagsIntersection != 0 || source.flags&TypeFlagsTypeParameter != 0 && target.flags&TypeFlagsUnion != 0) {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

LLM-generated test added


Regression test checked in as bd456af6e3 (tests/cases/compiler/effectiveConstraintChaseDuringVarianceMeasurement.ts plus .types/.symbols baselines), in response to the review comment asking for a checked-in test for the variance-stack guard.

  1. Minimized from the real repro. It is hand-distilled from the three.js TSL node types that triggered TypeScript 7.0.2 silently runs out of memory while typechecking a project that TypeScript 6.0.3 checks successfully #64423. Only the constructs needed to drive the combined-constraint comparison in structuredTypeRelatedTo during variance measurement were kept — resolving uv().div(vec2()) measures the variances of the generic extension interfaces, whose hoisted constraints form deferred conditional intersections.

  2. It fails without the fix. On the pre-fix revision (673a5f17d7) this file enters the unbounded relation chase and the process dies with runtime: out of memory. Removing or weakening the variance-stack guard reintroduces this immediately, so CI catches it instead of the regression going unnoticed.

  3. It passes with the fix and pins the exact output. With the guard, the file checks to completion in under a second with no diagnostics, and the baselines record the precise inferred types (e.g. x : Node<"vec2">). This also guards the opposite failure mode: a future change that "fixes" a hang by making the checker give up and infer different types would fail the baseline comparison.

Reproducing the pre-fix failure locally:

git show 673a5f17d7:tsc/internal/checker/relater.go > tsc/internal/checker/relater.go
cd tsc && GOMAXPROCS=2 timeout 120 go test ./internal/testrunner \
  -run 'TestLocal/effectiveConstraintChaseDuringVarianceMeasurement'
# pre-fix: never terminates (chase grows until OOM) / fixed: "ok" in ~1s

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

What do you think Jake Bailey (@jakebailey)? :)

var sourceTypes []*Type
if source.flags&TypeFlagsIntersection != 0 {
sourceTypes = source.Types()
Expand Down
Loading