Skip to content

Commit 028fa8e

Browse files
committed
mark deep indexed accesses as deeply nested in comparisons
1 parent 8ca36f3 commit 028fa8e

File tree

1 file changed

+25
-0
lines changed

1 file changed

+25
-0
lines changed

src/compiler/checker.ts

+25
Original file line numberDiff line numberDiff line change
@@ -14549,6 +14549,9 @@ namespace ts {
1454914549
// though highly unlikely, for this test to be true in a situation where a chain of instantiations is not infinitely
1455014550
// expanding. Effectively, we will generate a false positive when two types are structurally equal to at least 5
1455114551
// levels, but unequal at some level beyond that.
14552+
// In addition, this will also detect when an indexed access has been chained off of 5 or more times (which is essentially
14553+
// the dual of the structural comparison), and likewise mark the type as deeply nested, potentially adding false positives
14554+
// for finite but deeply expanding indexed accesses (eg, for `Q[P1][P2][P3][P4][P5]`).
1455214555
function isDeeplyNestedType(type: Type, stack: Type[], depth: number): boolean {
1455314556
// We track all object types that have an associated symbol (representing the origin of the type)
1455414557
if (depth >= 5 && type.flags & TypeFlags.Object) {
@@ -14564,9 +14567,31 @@ namespace ts {
1456414567
}
1456514568
}
1456614569
}
14570+
if (depth >= 5 && type.flags & TypeFlags.IndexedAccess) {
14571+
const root = getRootObjectTypeFromIndexedAccessChain(type);
14572+
let count = 0;
14573+
for (let i = 0; i < depth; i++) {
14574+
const t = stack[i];
14575+
if (getRootObjectTypeFromIndexedAccessChain(t) === root) {
14576+
count++;
14577+
if (count >= 5) return true;
14578+
}
14579+
}
14580+
}
1456714581
return false;
1456814582
}
1456914583

14584+
/**
14585+
* Gets the leftmost object type in a chain of indexed accesses, eg, in A[P][Q], returns A
14586+
*/
14587+
function getRootObjectTypeFromIndexedAccessChain(type: Type) {
14588+
let t = type;
14589+
while (t.flags & TypeFlags.IndexedAccess) {
14590+
t = (t as IndexedAccessType).objectType;
14591+
}
14592+
return t;
14593+
}
14594+
1457014595
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
1457114596
return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False;
1457214597
}

0 commit comments

Comments
 (0)