Skip to content

Commit f4fc9ed

Browse files
Anders HejlsbergAnders Hejlsberg
authored andcommitted
Fix deeply nested type check
1 parent 868802b commit f4fc9ed

File tree

2 files changed

+19
-18
lines changed

2 files changed

+19
-18
lines changed

src/compiler/checker.ts

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -8277,8 +8277,8 @@ namespace ts {
82778277
maybeStack[depth].set(id, RelationComparisonResult.Succeeded);
82788278
depth++;
82798279
const saveExpandingFlags = expandingFlags;
8280-
if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack, depth)) expandingFlags |= 1;
8281-
if (!(expandingFlags & 2) && isDeeplyNestedGeneric(target, targetStack, depth)) expandingFlags |= 2;
8280+
if (!(expandingFlags & 1) && isDeeplyNestedType(source, sourceStack, depth)) expandingFlags |= 1;
8281+
if (!(expandingFlags & 2) && isDeeplyNestedType(target, targetStack, depth)) expandingFlags |= 2;
82828282
let result: Ternary;
82838283
if (expandingFlags === 3) {
82848284
result = Ternary.Maybe;
@@ -8698,21 +8698,23 @@ namespace ts {
86988698
return false;
86998699
}
87008700

8701-
// Return true if the given type is part of a deeply nested chain of generic instantiations. We consider this to be the case
8702-
// when structural type comparisons have been started for 10 or more instantiations of the same generic type. It is possible,
8703-
// though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely expanding.
8704-
// Effectively, we will generate a false positive when two types are structurally equal to at least 10 levels, but unequal at
8705-
// some level beyond that.
8706-
function isDeeplyNestedGeneric(type: Type, stack: Type[], depth: number): boolean {
8707-
// We track type references (created by createTypeReference) and instantiated types (created by instantiateType)
8708-
if (getObjectFlags(type) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && depth >= 5) {
8701+
// Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons
8702+
// for 5 or more occurrences or instantiations of the type have been recorded on the given stack. It is possible,
8703+
// though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely
8704+
// expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5
8705+
// levels, but unequal at some level beyond that.
8706+
function isDeeplyNestedType(type: Type, stack: Type[], depth: number): boolean {
8707+
// We track all object types that have an associated symbol (representing the origin of the type)
8708+
if (depth >= 5 && type.flags & TypeFlags.Object) {
87098709
const symbol = type.symbol;
8710-
let count = 0;
8711-
for (let i = 0; i < depth; i++) {
8712-
const t = stack[i];
8713-
if (getObjectFlags(t) & (ObjectFlags.Reference | ObjectFlags.Instantiated) && t.symbol === symbol) {
8714-
count++;
8715-
if (count >= 5) return true;
8710+
if (symbol) {
8711+
let count = 0;
8712+
for (let i = 0; i < depth; i++) {
8713+
const t = stack[i];
8714+
if (t.flags & TypeFlags.Object && t.symbol === symbol) {
8715+
count++;
8716+
if (count >= 5) return true;
8717+
}
87168718
}
87178719
}
87188720
}
@@ -9455,7 +9457,7 @@ namespace ts {
94559457
if (isInProcess(source, target)) {
94569458
return;
94579459
}
9458-
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
9460+
if (isDeeplyNestedType(source, sourceStack, depth) && isDeeplyNestedType(target, targetStack, depth)) {
94599461
return;
94609462
}
94619463
const key = source.id + "," + target.id;

src/compiler/types.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3014,7 +3014,6 @@ namespace ts {
30143014
ObjectLiteral = 1 << 7, // Originates in an object literal
30153015
EvolvingArray = 1 << 8, // Evolving array type
30163016
ObjectLiteralPatternWithComputedProperties = 1 << 9, // Object literal pattern with computed properties
3017-
NonPrimitive = 1 << 10, // NonPrimitive object type
30183017
ClassOrInterface = Class | Interface
30193018
}
30203019

0 commit comments

Comments
 (0)