From 16a80030117e00f4ab046db5a2d1ff009ddebccb Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders <293473+sandersn@users.noreply.github.com> Date: Thu, 11 Jan 2018 10:07:59 -0800 Subject: [PATCH] push/popTypeResolution for circular base constraints Instead of a custom cache `typeStack`. --- src/compiler/checker.ts | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4b59cbc5d8a..d402f344d60 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -530,6 +530,7 @@ namespace ts { ResolvedBaseConstructorType, DeclaredType, ResolvedReturnType, + ResolvedBaseConstraint, } const enum CheckMode { @@ -4254,7 +4255,7 @@ namespace ts { return -1; } - function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type { + function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type | boolean { if (propertyName === TypeSystemPropertyName.Type) { return getSymbolLinks(target).type; } @@ -4267,6 +4268,10 @@ namespace ts { if (propertyName === TypeSystemPropertyName.ResolvedReturnType) { return (target).resolvedReturnType; } + if (propertyName === TypeSystemPropertyName.ResolvedBaseConstraint) { + const bc = (target).resolvedBaseConstraint; + return bc && bc !== circularConstraintType; + } Debug.fail("Unhandled TypeSystemPropertyName " + propertyName); } @@ -6301,9 +6306,9 @@ namespace ts { (type.typeParameter = getDeclaredTypeOfTypeParameter(getSymbolOfNode(type.declaration.typeParameter))); } - function getConstraintTypeFromMappedType(type: MappedType, typeStack?: Type[]) { + function getConstraintTypeFromMappedType(type: MappedType) { return type.constraintType || - (type.constraintType = instantiateType(getConstraintOfTypeParameter(getTypeParameterFromMappedType(type), typeStack), type.mapper || identityMapper) || unknownType); + (type.constraintType = instantiateType(getConstraintOfTypeParameter(getTypeParameterFromMappedType(type)), type.mapper || identityMapper) || unknownType); } function getTemplateTypeFromMappedType(type: MappedType) { @@ -6351,8 +6356,8 @@ namespace ts { return getObjectFlags(type) & ObjectFlags.Mapped && !!(type).declaration.questionToken; } - function isGenericMappedType(type: Type, typeStack?: Type[]): type is MappedType { - return getObjectFlags(type) & ObjectFlags.Mapped && isGenericIndexType(getConstraintTypeFromMappedType(type, typeStack)); + function isGenericMappedType(type: Type): type is MappedType { + return getObjectFlags(type) & ObjectFlags.Mapped && isGenericIndexType(getConstraintTypeFromMappedType(type)); } function resolveStructuredTypeMembers(type: StructuredType): ResolvedType { @@ -6458,10 +6463,7 @@ namespace ts { getBaseConstraintOfType(type); } - function getConstraintOfTypeParameter(typeParameter: TypeParameter, typeStack?: Type[]): Type { - if (typeStack) { - return !contains(typeStack, typeParameter) && getConstraintFromTypeParameter(typeParameter); - } + function getConstraintOfTypeParameter(typeParameter: TypeParameter): Type { return hasNonCircularBaseConstraint(typeParameter) ? getConstraintFromTypeParameter(typeParameter) : undefined; } @@ -6503,23 +6505,23 @@ namespace ts { * circularly references the type variable. */ function getResolvedBaseConstraint(type: TypeVariable | UnionOrIntersectionType): Type { - let typeStack: Type[]; let circular: boolean; if (!type.resolvedBaseConstraint) { - typeStack = []; const constraint = getBaseConstraint(type); type.resolvedBaseConstraint = circular ? circularConstraintType : getTypeWithThisArgument(constraint || noConstraintType, type); } return type.resolvedBaseConstraint; function getBaseConstraint(t: Type): Type { - if (contains(typeStack, t)) { + if (!pushTypeResolution(t, TypeSystemPropertyName.ResolvedBaseConstraint)) { circular = true; return undefined; } - typeStack.push(t); const result = computeBaseConstraint(t); - typeStack.pop(); + if (!popTypeResolution()) { + circular = true; + return undefined; + } return result; } @@ -6556,7 +6558,7 @@ namespace ts { const baseIndexedAccess = baseObjectType && baseIndexType ? getIndexedAccessType(baseObjectType, baseIndexType) : undefined; return baseIndexedAccess && baseIndexedAccess !== unknownType ? getBaseConstraint(baseIndexedAccess) : undefined; } - if (isGenericMappedType(t, typeStack)) { + if (isGenericMappedType(t)) { return emptyObjectType; } return t;