@@ -53,7 +53,8 @@ namespace ts {
53
53
let typeCount = 0;
54
54
let symbolCount = 0;
55
55
let enumCount = 0;
56
- let symbolInstantiationDepth = 0;
56
+ let instantiationDepth = 0;
57
+ let constraintDepth = 0;
57
58
58
59
const emptySymbols = createSymbolTable();
59
60
const identityMapper: (type: Type) => Type = identity;
@@ -5303,22 +5304,14 @@ namespace ts {
5303
5304
function getTypeOfInstantiatedSymbol(symbol: Symbol): Type {
5304
5305
const links = getSymbolLinks(symbol);
5305
5306
if (!links.type) {
5306
- if (symbolInstantiationDepth === 100) {
5307
- error(symbol.valueDeclaration, Diagnostics.Generic_type_instantiation_is_excessively_deep_and_possibly_infinite);
5308
- links.type = errorType;
5307
+ if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
5308
+ return links.type = errorType;
5309
5309
}
5310
- else {
5311
- if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
5312
- return links.type = errorType;
5313
- }
5314
- symbolInstantiationDepth++;
5315
- let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper!);
5316
- symbolInstantiationDepth--;
5317
- if (!popTypeResolution()) {
5318
- type = reportCircularityError(symbol);
5319
- }
5320
- links.type = type;
5310
+ let type = instantiateType(getTypeOfSymbol(links.target!), links.mapper!);
5311
+ if (!popTypeResolution()) {
5312
+ type = reportCircularityError(symbol);
5321
5313
}
5314
+ links.type = type;
5322
5315
}
5323
5316
return links.type;
5324
5317
}
@@ -6928,7 +6921,8 @@ namespace ts {
6928
6921
// over the conditional type and possibly reduced. For example, 'T extends undefined ? never : T'
6929
6922
// removes 'undefined' from T.
6930
6923
if (type.root.isDistributive) {
6931
- const constraint = getConstraintOfType(getSimplifiedType(type.checkType));
6924
+ const simplified = getSimplifiedType(type.checkType);
6925
+ const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified;
6932
6926
if (constraint) {
6933
6927
const mapper = makeUnaryTypeMapper(type.root.checkType, constraint);
6934
6928
const instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper));
@@ -7011,6 +7005,7 @@ namespace ts {
7011
7005
* circularly references the type variable.
7012
7006
*/
7013
7007
function getResolvedBaseConstraint(type: InstantiableType | UnionOrIntersectionType): Type {
7008
+ let nonTerminating = false;
7014
7009
return type.resolvedBaseConstraint ||
7015
7010
(type.resolvedBaseConstraint = getTypeWithThisArgument(getImmediateBaseConstraint(type), type));
7016
7011
@@ -7019,8 +7014,18 @@ namespace ts {
7019
7014
if (!pushTypeResolution(t, TypeSystemPropertyName.ImmediateBaseConstraint)) {
7020
7015
return circularConstraintType;
7021
7016
}
7017
+ if (constraintDepth === 50) {
7018
+ // We have reached 50 recursive invocations of getImmediateBaseConstraint and there is a
7019
+ // very high likelyhood we're dealing with an infinite generic type that perpetually generates
7020
+ // new type identities as we descend into it. We stop the recursion here and mark this type
7021
+ // and the outer types as having circular constraints.
7022
+ nonTerminating = true;
7023
+ return t.immediateBaseConstraint = noConstraintType;
7024
+ }
7025
+ constraintDepth++;
7022
7026
let result = computeBaseConstraint(getSimplifiedType(t));
7023
- if (!popTypeResolution()) {
7027
+ constraintDepth--;
7028
+ if (!popTypeResolution() || nonTerminating) {
7024
7029
result = circularConstraintType;
7025
7030
}
7026
7031
t.immediateBaseConstraint = result || noConstraintType;
@@ -10293,49 +10298,66 @@ namespace ts {
10293
10298
function instantiateType(type: Type, mapper: TypeMapper | undefined): Type;
10294
10299
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined;
10295
10300
function instantiateType(type: Type | undefined, mapper: TypeMapper | undefined): Type | undefined {
10296
- if (type && mapper && mapper !== identityMapper) {
10297
- if (type.flags & TypeFlags.TypeParameter) {
10298
- return mapper(<TypeParameter>type);
10299
- }
10300
- if (type.flags & TypeFlags.Object) {
10301
- if ((<ObjectType>type).objectFlags & ObjectFlags.Anonymous) {
10302
- // If the anonymous type originates in a declaration of a function, method, class, or
10303
- // interface, in an object type literal, or in an object literal expression, we may need
10304
- // to instantiate the type because it might reference a type parameter.
10305
- return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ?
10306
- getAnonymousTypeInstantiation(<AnonymousType>type, mapper) : type;
10307
- }
10308
- if ((<ObjectType>type).objectFlags & ObjectFlags.Mapped) {
10309
- return getAnonymousTypeInstantiation(<MappedType>type, mapper);
10310
- }
10311
- if ((<ObjectType>type).objectFlags & ObjectFlags.Reference) {
10312
- const typeArguments = (<TypeReference>type).typeArguments;
10313
- const newTypeArguments = instantiateTypes(typeArguments, mapper);
10314
- return newTypeArguments !== typeArguments ? createTypeReference((<TypeReference>type).target, newTypeArguments) : type;
10315
- }
10316
- }
10317
- if (type.flags & TypeFlags.Union && !(type.flags & TypeFlags.Primitive)) {
10318
- const types = (<UnionType>type).types;
10319
- const newTypes = instantiateTypes(types, mapper);
10320
- return newTypes !== types ? getUnionType(newTypes, UnionReduction.Literal, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type;
10321
- }
10322
- if (type.flags & TypeFlags.Intersection) {
10323
- const types = (<IntersectionType>type).types;
10324
- const newTypes = instantiateTypes(types, mapper);
10325
- return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type;
10326
- }
10327
- if (type.flags & TypeFlags.Index) {
10328
- return getIndexType(instantiateType((<IndexType>type).type, mapper));
10329
- }
10330
- if (type.flags & TypeFlags.IndexedAccess) {
10331
- return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
10301
+ if (!type || !mapper || mapper === identityMapper) {
10302
+ return type;
10303
+ }
10304
+ if (instantiationDepth === 50) {
10305
+ // We have reached 50 recursive type instantiations and there is a very high likelyhood we're dealing
10306
+ // with a combination of infinite generic types that perpetually generate new type identities. We stop
10307
+ // the recursion here by yielding the error type.
10308
+ return errorType;
10309
+ }
10310
+ instantiationDepth++;
10311
+ const result = instantiateTypeWorker(type, mapper);
10312
+ instantiationDepth--;
10313
+ return result;
10314
+ }
10315
+
10316
+ function instantiateTypeWorker(type: Type, mapper: TypeMapper): Type {
10317
+ const flags = type.flags;
10318
+ if (flags & TypeFlags.TypeParameter) {
10319
+ return mapper(type);
10320
+ }
10321
+ if (flags & TypeFlags.Object) {
10322
+ const objectFlags = (<ObjectType>type).objectFlags;
10323
+ if (objectFlags & ObjectFlags.Anonymous) {
10324
+ // If the anonymous type originates in a declaration of a function, method, class, or
10325
+ // interface, in an object type literal, or in an object literal expression, we may need
10326
+ // to instantiate the type because it might reference a type parameter.
10327
+ return type.symbol && type.symbol.flags & (SymbolFlags.Function | SymbolFlags.Method | SymbolFlags.Class | SymbolFlags.TypeLiteral | SymbolFlags.ObjectLiteral) && type.symbol.declarations ?
10328
+ getAnonymousTypeInstantiation(<AnonymousType>type, mapper) : type;
10332
10329
}
10333
- if (type.flags & TypeFlags.Conditional ) {
10334
- return getConditionalTypeInstantiation(<ConditionalType >type, combineTypeMappers((<ConditionalType>type). mapper, mapper) );
10330
+ if (objectFlags & ObjectFlags.Mapped ) {
10331
+ return getAnonymousTypeInstantiation(<AnonymousType >type, mapper);
10335
10332
}
10336
- if (type.flags & TypeFlags.Substitution) {
10337
- return instantiateType((<SubstitutionType>type).typeVariable, mapper);
10333
+ if (objectFlags & ObjectFlags.Reference) {
10334
+ const typeArguments = (<TypeReference>type).typeArguments;
10335
+ const newTypeArguments = instantiateTypes(typeArguments, mapper);
10336
+ return newTypeArguments !== typeArguments ? createTypeReference((<TypeReference>type).target, newTypeArguments) : type;
10338
10337
}
10338
+ return type;
10339
+ }
10340
+ if (flags & TypeFlags.Union && !(flags & TypeFlags.Primitive)) {
10341
+ const types = (<UnionType>type).types;
10342
+ const newTypes = instantiateTypes(types, mapper);
10343
+ return newTypes !== types ? getUnionType(newTypes, UnionReduction.Literal, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type;
10344
+ }
10345
+ if (flags & TypeFlags.Intersection) {
10346
+ const types = (<IntersectionType>type).types;
10347
+ const newTypes = instantiateTypes(types, mapper);
10348
+ return newTypes !== types ? getIntersectionType(newTypes, type.aliasSymbol, instantiateTypes(type.aliasTypeArguments, mapper)) : type;
10349
+ }
10350
+ if (flags & TypeFlags.Index) {
10351
+ return getIndexType(instantiateType((<IndexType>type).type, mapper));
10352
+ }
10353
+ if (flags & TypeFlags.IndexedAccess) {
10354
+ return getIndexedAccessType(instantiateType((<IndexedAccessType>type).objectType, mapper), instantiateType((<IndexedAccessType>type).indexType, mapper));
10355
+ }
10356
+ if (flags & TypeFlags.Conditional) {
10357
+ return getConditionalTypeInstantiation(<ConditionalType>type, combineTypeMappers((<ConditionalType>type).mapper, mapper));
10358
+ }
10359
+ if (flags & TypeFlags.Substitution) {
10360
+ return instantiateType((<SubstitutionType>type).typeVariable, mapper);
10339
10361
}
10340
10362
return type;
10341
10363
}
0 commit comments