Increase type instantiation depth limit (#45025)

* Bump instantiation depth limit to 500

* Accept new baselines

* Update tests

* Accept new baselines
This commit is contained in:
Anders Hejlsberg
2021-08-17 07:00:19 -07:00
committed by GitHub
parent dc80e6a28b
commit 79474fdfd2
6 changed files with 253 additions and 249 deletions

View File

@@ -16272,7 +16272,14 @@ namespace ts {
let result = root.instantiations!.get(id);
if (!result) {
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
result = instantiateConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
const checkType = root.checkType;
const distributionType = root.isDistributive ? getMappedType(checkType, newMapper) : undefined;
// Distributive conditional types are distributed over union types. For example, when the
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
mapTypeWithAlias(distributionType, t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
root.instantiations!.set(id, result);
}
return result;
@@ -16280,20 +16287,6 @@ namespace ts {
return type;
}
function instantiateConditionalType(root: ConditionalRoot, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
// Check if we have a conditional type where the check type is a naked type parameter. If so,
// the conditional type is distributive over union types and when T is instantiated to a union
// type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y).
if (root.isDistributive) {
const checkType = root.checkType as TypeParameter;
const instantiatedType = getMappedType(checkType, mapper);
if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
return mapTypeWithAlias(instantiatedType, t => getConditionalType(root, prependTypeMapping(checkType, t, mapper)), aliasSymbol, aliasTypeArguments);
}
}
return getConditionalType(root, mapper, aliasSymbol, aliasTypeArguments);
}
function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
@@ -16304,10 +16297,10 @@ namespace ts {
if (!couldContainTypeVariables(type)) {
return type;
}
if (instantiationDepth === 50 || instantiationCount >= 5000000) {
// We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
// with a combination of infinite generic types that perpetually generate new type identities. We stop
// the recursion here by yielding the error type.
if (instantiationDepth === 500 || instantiationCount >= 5000000) {
// We have reached 500 recursive type instantiations, or 5M type instantiations caused by the same statement
// or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types
// that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount });
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
return errorType;