@@ -20355,27 +20355,25 @@ namespace ts {
20355
20355
}
20356
20356
20357
20357
// Return true if the given type is deeply nested. We consider this to be the case when structural type comparisons
20358
- // for 5 or more occurrences or instantiations of the type have been recorded on the given stack. It is possible,
20358
+ // for maxDepth or more occurrences or instantiations of the type have been recorded on the given stack. It is possible,
20359
20359
// though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely
20360
- // expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5
20360
+ // expanding. Effectively, we will generate a false positive when two types are structurally equal to at least maxDepth
20361
20361
// levels, but unequal at some level beyond that.
20362
- // In addition, this will also detect when an indexed access has been chained off of 5 or more times (which is essentially
20363
- // the dual of the structural comparison), and likewise mark the type as deeply nested, potentially adding false positives
20364
- // for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][P3][P4][P5]`).
20365
- // It also detects when a recursive type reference has expanded 5 or more times, eg, if the true branch of
20366
- // `type A<T> = null extends T ? [A<NonNullable<T>>] : [T]`
20367
- // has expanded into `[A<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T>>>>>>]`
20368
- // in such cases we need to terminate the expansion, and we do so here.
20369
- function isDeeplyNestedType(type: Type, stack: Type[], depth: number, maxDepth = 5): boolean {
20362
+ function isDeeplyNestedType(type: Type, stack: Type[], depth: number, maxDepth = 3): boolean {
20370
20363
if (depth >= maxDepth) {
20371
20364
const identity = getRecursionIdentity(type);
20372
20365
let count = 0;
20366
+ let lastTypeId = 0;
20373
20367
for (let i = 0; i < depth; i++) {
20374
- if (getRecursionIdentity(stack[i]) === identity) {
20368
+ const t = stack[i];
20369
+ // We only count occurrences with higher type ids than the previous occurrences, since higher
20370
+ // type ids are an indicator of newer instantiations caused by recursion.
20371
+ if (getRecursionIdentity(t) === identity && t.id >= lastTypeId) {
20375
20372
count++;
20376
20373
if (count >= maxDepth) {
20377
20374
return true;
20378
20375
}
20376
+ lastTypeId = t.id;
20379
20377
}
20380
20378
}
20381
20379
}
@@ -20410,13 +20408,6 @@ namespace ts {
20410
20408
if (type.flags & TypeFlags.TypeParameter) {
20411
20409
return type.symbol;
20412
20410
}
20413
- if (type.flags & TypeFlags.IndexedAccess) {
20414
- // Identity is the leftmost object type in a chain of indexed accesses, eg, in A[P][Q] it is A
20415
- do {
20416
- type = (type as IndexedAccessType).objectType;
20417
- } while (type.flags & TypeFlags.IndexedAccess);
20418
- return type;
20419
- }
20420
20411
if (type.flags & TypeFlags.Conditional) {
20421
20412
// The root object represents the origin of the conditional type
20422
20413
return (type as ConditionalType).root;
0 commit comments