diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9f85b552378ca..1d5d6cc7347ca 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16892,7 +16892,6 @@ namespace ts { return isIdenticalTo(source, target); } - // We fastpath comparing a type parameter to exactly its constraint, as this is _super_ common, // and otherwise, for type parameters in large unions, causes us to need to compare the union to itself, // as we break down the _target_ union first, _then_ get the source constraint - so for every @@ -16953,6 +16952,8 @@ namespace ts { return Ternary.False; } + traceUnionsOrIntersectionsTooLarge(source, target); + let result = Ternary.False; const saveErrorInfo = captureErrorCalculationState(); @@ -17088,11 +17089,41 @@ namespace ts { } } + function traceUnionsOrIntersectionsTooLarge(source: Type, target: Type): void { + if (!tracing.isTracing()) { + return; + } + + if ((source.flags & TypeFlags.UnionOrIntersection) && (target.flags & TypeFlags.UnionOrIntersection)) { + const sourceUnionOrIntersection = source as UnionOrIntersectionType; + const targetUnionOrIntersection = target as UnionOrIntersectionType; + + if (sourceUnionOrIntersection.objectFlags & targetUnionOrIntersection.objectFlags & ObjectFlags.PrimitiveUnion) { + // There's a fast path for comparing primitive unions + return; + } + + const sourceSize = sourceUnionOrIntersection.types.length; + const targetSize = targetUnionOrIntersection.types.length; + if (sourceSize * targetSize > 1E6) { + tracing.instant(tracing.Phase.CheckTypes, "traceUnionsOrIntersectionsTooLarge_DepthLimit", { + sourceId: source.id, + sourceSize, + targetId: target.id, + targetSize, + pos: errorNode?.pos, + end: errorNode?.end + }); + } + } + } + function isIdenticalTo(source: Type, target: Type): Ternary { const flags = source.flags & target.flags; if (!(flags & TypeFlags.Substructure)) { return Ternary.False; } + traceUnionsOrIntersectionsTooLarge(source, target); if (flags & TypeFlags.UnionOrIntersection) { let result = eachTypeRelatedToSomeType(source, target); if (result) {