fix(relater): add property comparison cache fast path to avoid false TS2321#4382
fix(relater): add property comparison cache fast path to avoid false TS2321#4382maoger wants to merge 2 commits into
Conversation
|
@microsoft-github-policy-service agree |
There was a problem hiding this comment.
Pull request overview
This PR adjusts the checker’s type-relating logic to reduce false TS2321 (“Excessive stack depth comparing types”) reports when comparing very large object literals against complex target types.
Changes:
- Increase the relater recursion stack depth limit from 100 to 400.
- Add a relation-cache lookup fast path during per-property type comparisons.
- Add a new compiler regression test (plus baselines) exercising large object-literal assignment scenarios.
Reviewed changes
Copilot reviewed 3 out of 5 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| internal/checker/relater.go | Raises stack depth limit and adds a property-comparison cache fast path in the relater. |
| testdata/tests/cases/compiler/largeObjectLiteralNoExcessiveStackDepth.ts | New regression test covering large object literal assignments that previously triggered false TS2321. |
| testdata/baselines/reference/compiler/largeObjectLiteralNoExcessiveStackDepth.types | New/updated .types baseline for the regression test. |
| testdata/baselines/reference/compiler/excessivelyDeepConditionalTypes.errors.txt | Baseline update reflecting changed TS2321 printing/trigger point after increasing the stack depth limit. |
| if len(r.sourceStack) == 400 || len(r.targetStack) == 400 { | ||
| r.overflow = true | ||
| return TernaryFalse | ||
| } |
| // Fast path: query the relation cache directly before entering the recursive comparison | ||
| // path. This avoids unnecessary stack depth growth when comparing large object literals | ||
| // (e.g. Vite/Linter configs with 100+ rules) against complex target types, where each | ||
| // property comparison would otherwise push onto the source/target stacks. |
| if effectiveSource.flags&TypeFlagsObject != 0 && effectiveTarget.flags&TypeFlagsObject != 0 { | ||
| id, _ := getRelationKey(effectiveSource, effectiveTarget, intersectionState, r.relation == r.c.identityRelation, false /*ignoreConstraints*/) | ||
| if entry := r.relation.get(id); entry != RelationComparisonResultNone && entry&RelationComparisonResultSucceeded != 0 { | ||
| return TernaryTrue | ||
| } | ||
| } |
|
We are not going to be raising any limits |
…TS2321 Add a relation-cache lookup fast path in isPropertySymbolTypeRelated that short-circuits on confirmed cached success before entering the full isRelatedToEx recursive comparison. This reduces redundant stack depth growth when comparing large object literals (100+ properties) against complex target types, where many properties share the same type (e.g. RuleConfig, string). The fast path also propagates cached reliability flags (ReportsUnmeasurable/ReportsUnreliable) to match recursiveTypeRelatedTo behavior.
Add largeObjectLiteralNoExcessiveStackDepth.ts with two scenarios: 200 RuleConfig-typed properties and 150 function-typed properties, both assigned to complex target types. Previously these would trigger false TS2321 errors; with the property cache fast path they compile with zero errors.
34bccf1 to
a997839
Compare
|
Thanks for the feedback. I've updated the PR to remove the stack depth limit change — the fix now relies solely on a relation-cache fast path in The full test suite passes ( The PR is ready for review when you have time. |
|
I'm a little unclear as to the history of this change. Where did it come from? Is this an issue in TS 6? Why is there no issue for this? Have you experienced this in a real codebase? You're also certainly not disclosing the tooling you're using for this; you're replying like an LLM. https://github.com/microsoft/typescript-go/blob/main/CONTRIBUTING.md#use-of-ai-assistance |
Summary
Fix false TS2321 ("Excessive stack depth comparing types") errors when comparing large object literals (100+ properties) against complex target types, by adding a relation-cache fast path in
isPropertySymbolTypeRelated.Problem
When comparing large object literals (e.g.
defineConfig({...})with 190+ lint rules) against complex target types, tsgo produces false TS2321 errors that the originaltscdoes not report.The root cause: each property comparison in a large object literal goes through the full
isRelatedToEx→recursiveTypeRelatedTopath, even when the relation cache already has a result for that type pair. When many properties share the same type (e.g.RuleConfig,string), this causes redundant stack pushes that exhaust the recursion limit.Changes
internal/checker/relater.goAdd a relation-cache lookup fast path in
isPropertySymbolTypeRelated, before theisRelatedToExcall:recursiveTypeRelatedTobehaviorScope: This fix targets false TS2321 caused by repeated property-type comparisons in large object literals. It does not address cases where recursion depth is inherently deep (e.g. recursive conditional types).
testdata/tests/cases/compiler/largeObjectLiteralNoExcessiveStackDepth.ts(new)Regression test with two scenarios:
RuleConfig-typed properties assigned to aLargeConfigtargetFnType) properties assigned to aConfigWithFunctionstargetBoth compile with zero errors (no TS2321).
Testing
Related Issues
@sinclair/typebox@0.27.8#1730 — "Excessive stack depth comparing types" when linting@sinclair/typebox@0.27.8