@@ -20355,27 +20355,25 @@ namespace ts {
2035520355        }
2035620356
2035720357        // 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,
2035920359        // 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 
2036120361        // 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 {
2037020363            if (depth >= maxDepth) {
2037120364                const identity = getRecursionIdentity(type);
2037220365                let count = 0;
20366+                 let lastTypeId = 0;
2037320367                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) {
2037520372                        count++;
2037620373                        if (count >= maxDepth) {
2037720374                            return true;
2037820375                        }
20376+                         lastTypeId = t.id;
2037920377                    }
2038020378                }
2038120379            }
@@ -20410,13 +20408,6 @@ namespace ts {
2041020408            if (type.flags & TypeFlags.TypeParameter) {
2041120409                return type.symbol;
2041220410            }
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-             }
2042020411            if (type.flags & TypeFlags.Conditional) {
2042120412                // The root object represents the origin of the conditional type
2042220413                return (type as ConditionalType).root;
0 commit comments