@@ -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;
0 commit comments