From b37313c90d6d2039e4df5d93aa8007e1fd7e16b9 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 20 Oct 2016 15:42:24 -0700 Subject: [PATCH] Introduce EvolvingArrayType and associated ObjectFlag.EvolvingArray --- src/compiler/checker.ts | 20 ++++++++++---------- src/compiler/types.ts | 8 ++++++-- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32705df1725..843a21cbae3 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -115,7 +115,7 @@ namespace ts { const intersectionTypes = createMap(); const stringLiteralTypes = createMap(); const numericLiteralTypes = createMap(); - const evolvingArrayTypes: AnonymousType[] = []; + const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); const resolvingSymbol = createSymbol(SymbolFlags.Transient, "__resolving__"); @@ -8558,26 +8558,26 @@ namespace ts { // 'x.push(value)' or 'x[n] = value' operation along the control flow graph. Evolving // array types are ultimately converted into manifest array types (using getFinalArrayType) // and never escape the getFlowTypeOfReference function. - function createEvolvingArrayType(elementType: Type): AnonymousType { - const result = createObjectType(ObjectFlags.Anonymous); + function createEvolvingArrayType(elementType: Type): EvolvingArrayType { + const result = createObjectType(ObjectFlags.EvolvingArray); result.elementType = elementType; return result; } - function getEvolvingArrayType(elementType: Type): AnonymousType { + function getEvolvingArrayType(elementType: Type): EvolvingArrayType { return evolvingArrayTypes[elementType.id] || (evolvingArrayTypes[elementType.id] = createEvolvingArrayType(elementType)); } // When adding evolving array element types we do not perform subtype reduction. Instead, // we defer subtype reduction until the evolving array type is finalized into a manifest // array type. - function addEvolvingArrayElementType(evolvingArrayType: AnonymousType, node: Expression): AnonymousType { + function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType { const elementType = getBaseTypeOfLiteralType(checkExpression(node)); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } function isEvolvingArrayType(type: Type) { - return !!(getObjectFlags(type) & ObjectFlags.Anonymous && (type).elementType); + return !!(getObjectFlags(type) & ObjectFlags.EvolvingArray); } function createFinalArrayType(elementType: Type) { @@ -8589,16 +8589,16 @@ namespace ts { } // We perform subtype reduction upon obtaining the final array type from an evolving array type. - function getFinalArrayType(evolvingArrayType: AnonymousType): Type { + function getFinalArrayType(evolvingArrayType: EvolvingArrayType): Type { return evolvingArrayType.finalArrayType || (evolvingArrayType.finalArrayType = createFinalArrayType(evolvingArrayType.elementType)); } function finalizeEvolvingArrayType(type: Type): Type { - return isEvolvingArrayType(type) ? getFinalArrayType(type) : type; + return isEvolvingArrayType(type) ? getFinalArrayType(type) : type; } function getElementTypeOfEvolvingArrayType(type: Type) { - return isEvolvingArrayType(type) ? (type).elementType : neverType; + return isEvolvingArrayType(type) ? (type).elementType : neverType; } function isEvolvingArrayTypeList(types: Type[]) { @@ -8770,7 +8770,7 @@ namespace ts { const flowType = getTypeAtFlowNode(flow.antecedent); const type = getTypeFromFlowType(flowType); if (isEvolvingArrayType(type)) { - let evolvedType = type; + let evolvedType = type; if (node.kind === SyntaxKind.CallExpression) { for (const arg of (node).arguments) { evolvedType = addEvolvingArrayElementType(evolvedType, arg); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 0a298a78d02..551f8b8697e 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2663,6 +2663,7 @@ namespace ts { Anonymous = 1 << 4, // Anonymous Instantiated = 1 << 5, // Instantiated anonymous type ObjectLiteral = 1 << 6, // Originates in an object literal + EvolvingArray = 1 << 7, // Evolving array type } // Properties common to all types @@ -2763,8 +2764,11 @@ namespace ts { export interface AnonymousType extends ObjectType { target?: AnonymousType; // Instantiation target mapper?: TypeMapper; // Instantiation mapper - elementType?: Type; // Element expressions of evolving array type - finalArrayType?: Type; // Final array type of evolving array type + } + + export interface EvolvingArrayType extends ObjectType { + elementType: Type; // Element expressions of evolving array type + finalArrayType?: Type; // Final array type of evolving array type } /* @internal */