Skip to content

Commit 5f99e87

Browse files
ahejlsbergBobobUnicorn
authored andcommitted
Increase type instantiation depth limit (microsoft#45025)
* Bump instantiation depth limit to 500 * Accept new baselines * Update tests * Accept new baselines
1 parent 61928e1 commit 5f99e87

6 files changed

+245
-241
lines changed

src/compiler/checker.ts

+12-19
Original file line numberDiff line numberDiff line change
@@ -16272,28 +16272,21 @@ namespace ts {
1627216272
let result = root.instantiations!.get(id);
1627316273
if (!result) {
1627416274
const newMapper = createTypeMapper(root.outerTypeParameters, typeArguments);
16275-
result = instantiateConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
16275+
const checkType = root.checkType;
16276+
const distributionType = root.isDistributive ? getMappedType(checkType, newMapper) : undefined;
16277+
// Distributive conditional types are distributed over union types. For example, when the
16278+
// distributive conditional type T extends U ? X : Y is instantiated with A | B for T, the
16279+
// result is (A extends U ? X : Y) | (B extends U ? X : Y).
16280+
result = distributionType && checkType !== distributionType && distributionType.flags & (TypeFlags.Union | TypeFlags.Never) ?
16281+
mapTypeWithAlias(distributionType, t => getConditionalType(root, prependTypeMapping(checkType, t, newMapper)), aliasSymbol, aliasTypeArguments) :
16282+
getConditionalType(root, newMapper, aliasSymbol, aliasTypeArguments);
1627616283
root.instantiations!.set(id, result);
1627716284
}
1627816285
return result;
1627916286
}
1628016287
return type;
1628116288
}
1628216289

16283-
function instantiateConditionalType(root: ConditionalRoot, mapper: TypeMapper, aliasSymbol?: Symbol, aliasTypeArguments?: readonly Type[]): Type {
16284-
// Check if we have a conditional type where the check type is a naked type parameter. If so,
16285-
// the conditional type is distributive over union types and when T is instantiated to a union
16286-
// type A | B, we produce (A extends U ? X : Y) | (B extends U ? X : Y).
16287-
if (root.isDistributive) {
16288-
const checkType = root.checkType as TypeParameter;
16289-
const instantiatedType = getMappedType(checkType, mapper);
16290-
if (checkType !== instantiatedType && instantiatedType.flags & (TypeFlags.Union | TypeFlags.Never)) {
16291-
return mapTypeWithAlias(instantiatedType, t => getConditionalType(root, prependTypeMapping(checkType, t, mapper)), aliasSymbol, aliasTypeArguments);
16292-
}
16293-
}
16294-
return getConditionalType(root, mapper, aliasSymbol, aliasTypeArguments);
16295-
}
16296-
1629716290
function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
1629816291
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
1629916292
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
@@ -16304,10 +16297,10 @@ namespace ts {
1630416297
if (!couldContainTypeVariables(type)) {
1630516298
return type;
1630616299
}
16307-
if (instantiationDepth === 50 || instantiationCount >= 5000000) {
16308-
// We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
16309-
// with a combination of infinite generic types that perpetually generate new type identities. We stop
16310-
// the recursion here by yielding the error type.
16300+
if (instantiationDepth === 500 || instantiationCount >= 5000000) {
16301+
// We have reached 500 recursive type instantiations, or 5M type instantiations caused by the same statement
16302+
// or expression. There is a very high likelyhood we're dealing with a combination of infinite generic types
16303+
// that perpetually generate new type identities, so we stop the recursion here by yielding the error type.
1631116304
tracing?.instant(tracing.Phase.CheckTypes, "instantiateType_DepthLimit", { typeId: type.id, instantiationDepth, instantiationCount });
1631216305
error(currentNode, Diagnostics.Type_instantiation_is_excessively_deep_and_possibly_infinite);
1631316306
return errorType;

tests/baselines/reference/recursiveConditionalTypes.errors.txt

+7-6
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ tests/cases/compiler/recursiveConditionalTypes.ts(21,5): error TS2322: Type 'T'
66
tests/cases/compiler/recursiveConditionalTypes.ts(22,5): error TS2322: Type 'Awaited<T>' is not assignable to type 'T'.
77
'T' could be instantiated with an arbitrary type which could be unrelated to 'Awaited<T>'.
88
tests/cases/compiler/recursiveConditionalTypes.ts(35,11): error TS2589: Type instantiation is excessively deep and possibly infinite.
9-
tests/cases/compiler/recursiveConditionalTypes.ts(46,12): error TS2589: Type instantiation is excessively deep and possibly infinite.
10-
tests/cases/compiler/recursiveConditionalTypes.ts(49,5): error TS2322: Type 'TupleOf<number, M>' is not assignable to type 'TupleOf<number, N>'.
9+
tests/cases/compiler/recursiveConditionalTypes.ts(47,12): error TS2589: Type instantiation is excessively deep and possibly infinite.
10+
tests/cases/compiler/recursiveConditionalTypes.ts(50,5): error TS2322: Type 'TupleOf<number, M>' is not assignable to type 'TupleOf<number, N>'.
1111
Type 'number extends M ? number[] : _TupleOf<number, M, []>' is not assignable to type 'TupleOf<number, N>'.
1212
Type 'number[] | _TupleOf<number, M, []>' is not assignable to type 'TupleOf<number, N>'.
1313
Type 'number[]' is not assignable to type 'TupleOf<number, N>'.
14-
tests/cases/compiler/recursiveConditionalTypes.ts(50,5): error TS2322: Type 'TupleOf<number, N>' is not assignable to type 'TupleOf<number, M>'.
14+
tests/cases/compiler/recursiveConditionalTypes.ts(51,5): error TS2322: Type 'TupleOf<number, N>' is not assignable to type 'TupleOf<number, M>'.
1515
Type 'number extends N ? number[] : _TupleOf<number, N, []>' is not assignable to type 'TupleOf<number, M>'.
1616
Type 'number[] | _TupleOf<number, N, []>' is not assignable to type 'TupleOf<number, M>'.
1717
Type 'number[]' is not assignable to type 'TupleOf<number, M>'.
18-
tests/cases/compiler/recursiveConditionalTypes.ts(116,9): error TS2345: Argument of type 'Grow2<[], T>' is not assignable to parameter of type 'Grow1<[], T>'.
18+
tests/cases/compiler/recursiveConditionalTypes.ts(117,9): error TS2345: Argument of type 'Grow2<[], T>' is not assignable to parameter of type 'Grow1<[], T>'.
1919
Type '[] | Grow2<[string], T>' is not assignable to type 'Grow1<[], T>'.
2020
Type '[]' is not assignable to type 'Grow1<[], T>'.
2121
Type 'Grow2<[string], T>' is not assignable to type 'Grow1<[number], T>'.
@@ -84,8 +84,9 @@ tests/cases/compiler/recursiveConditionalTypes.ts(116,9): error TS2345: Argument
8484
type TT1 = TupleOf<number, 0 | 2 | 4>;
8585
type TT2 = TupleOf<number, number>;
8686
type TT3 = TupleOf<number, any>;
87-
type TT4 = TupleOf<number, 100>; // Depth error
88-
~~~~~~~~~~~~~~~~~~~~
87+
type TT4 = TupleOf<number, 100>;
88+
type TT5 = TupleOf<number, 1000>; // Depth error
89+
~~~~~~~~~~~~~~~~~~~~~
8990
!!! error TS2589: Type instantiation is excessively deep and possibly infinite.
9091

9192
function f22<N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) {

tests/baselines/reference/recursiveConditionalTypes.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,8 @@ type TT0 = TupleOf<string, 4>;
4444
type TT1 = TupleOf<number, 0 | 2 | 4>;
4545
type TT2 = TupleOf<number, number>;
4646
type TT3 = TupleOf<number, any>;
47-
type TT4 = TupleOf<number, 100>; // Depth error
47+
type TT4 = TupleOf<number, 100>;
48+
type TT5 = TupleOf<number, 1000>; // Depth error
4849

4950
function f22<N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>) {
5051
tn = tm;
@@ -194,6 +195,7 @@ declare type TT1 = TupleOf<number, 0 | 2 | 4>;
194195
declare type TT2 = TupleOf<number, number>;
195196
declare type TT3 = TupleOf<number, any>;
196197
declare type TT4 = TupleOf<number, 100>;
198+
declare type TT5 = TupleOf<number, 1000>;
197199
declare function f22<N extends number, M extends N>(tn: TupleOf<number, N>, tm: TupleOf<number, M>): void;
198200
declare function f23<T>(t: TupleOf<T, 3>): T;
199201
interface Box<T> {

0 commit comments

Comments
 (0)