Skip to content

Commit 16fea3e

Browse files
committed
Bump instantiation depth limit to 500
1 parent 0746f70 commit 16fea3e

File tree

1 file changed

+12
-19
lines changed

1 file changed

+12
-19
lines changed

src/compiler/checker.ts

Lines changed: 12 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16227,28 +16227,21 @@ namespace ts {
1622716227
let result = root.instantiations!.get(id);
1622816228
if (!result) {
1622916229
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
16230-
result = instantiateConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
16230+
const checkType = root.checkType;
16231+
const distributionType = root.isDistributive ? getMappedType(checkType, newMapper) : undefined;
16232+
// Distributive conditional types are distributed over union types. For example, when the
16233+
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
16234+
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
16235+
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
16236+
mapTypeWithAlias(distributionType, t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
16237+
getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
1623116238
root.instantiations!.set(id, result);
1623216239
}
1623316240
return result;
1623416241
}
1623516242
return type;
1623616243
}
1623716244

16238-
function instantiateConditionalType(root: ConditionalRoot, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
16239-
// Check if we have a conditional type where the check type is a naked type parameter. If so,
16240-
// the conditional type is distributive over union types and when T is instantiated to a union
16241-
// type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y).
16242-
if (root.isDistributive) {
16243-
const checkType = root.checkType as TypeParameter;
16244-
const instantiatedType = getMappedType(checkType, mapper);
16245-
if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
16246-
return mapTypeWithAlias(instantiatedType, t => getConditionalType(root, prependTypeMapping(checkType, t, mapper)), aliasSymbol, aliasTypeArguments);
16247-
}
16248-
}
16249-
return getConditionalType(root, mapper, aliasSymbol, aliasTypeArguments);
16250-
}
16251-
1625216245
function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
1625316246
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
1625416247
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
@@ -16259,10 +16252,10 @@ namespace ts {
1625916252
if (!couldContainTypeVariables(type)) {
1626016253
return type;
1626116254
}
16262-
if (instantiationDepth === 50 || instantiationCount >= 5000000) {
16263-
// We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
16264-
// with a combination of infinite generic types that perpetually generate new type identities. We stop
16265-
// the recursion here by yielding the error type.
16255+
if (instantiationDepth === 500 || instantiationCount >= 5000000) {
16256+
// We have reached 500 recursive type instantiations, or 5M type instantiations caused by the same statement
16257+
// or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types
16258+
// that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
1626616259
tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount });
1626716260
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
1626816261
return errorType;

0 commit comments

Comments
 (0)