Skip to content
Merged
Changes from 1 commit
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Remove deduplication logic now that subtype reduction was optimized
  • Loading branch information
ahejlsberg committed Feb 28, 2021
commit a18aac27c604a85de6dd4f219619870fa5545392
45 changes: 1 addition & 44 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25215,9 +25215,8 @@ namespace ts {
if (forceTuple || inConstContext || contextualType && forEachType(contextualType, isTupleLikeType)) {
return createArrayLiteralType(createTupleType(elementTypes, elementFlags, /*readonly*/ inConstContext));
}
const deduplicatedTypes = deduplicateObjectOrArrayLiteralTypes(sameMap(elementTypes, (t, i) => elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t));
return createArrayLiteralType(createArrayType(elementTypes.length ?
getUnionType(deduplicatedTypes, UnionReduction.Subtype) :
getUnionType(sameMap(elementTypes, (t, i) => elementFlags[i] & ElementFlags.Variadic ? getIndexedAccessTypeOrUndefined(t, numberType) || anyType : t), UnionReduction.Subtype) :
strictNullChecks ? implicitNeverType : undefinedWideningType, inConstContext));
}

Expand All @@ -25233,48 +25232,6 @@ namespace ts {
return literalType;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As-is, I think this'd intern { set a(x: string) {} } and { get a(){ return ""; } } to the same type, even though the later has a readonly a. Maybe just encoding the symbol flags wholesale in the key will be the most future proof thing, and then you can just join the names with , and not worry about the name length list thing.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I'll look to make sure we properly preserve that distinction. The name length list is still needed since property names can contain any character, including any separator we might use to separate them.

}

/**
* Replaces all references to structurally equivalent object and array literal types in the given list
* with references to a single one of those types. The process is applied recursively to properties of
* object literals and elements of array literals.
*/
function deduplicateObjectOrArrayLiteralTypes(types: Type[]) {
if (!some(types, isObjectOrArrayLiteralType)) {
return types;
}
const typeMap = new Map<string, Type>();
return sameMap(types, getInternedType);

function getInternedType(type: Type): Type {
if (type.flags & TypeFlags.Union) {
const newTypes = sameMap((<UnionType>type).types, getInternedType);
return newTypes !== (<UnionType>type).types ? getUnionType(newTypes) : type;
}
const key = getLiteralTypeKey(type);
return key ? typeMap.get(key) || (typeMap.set(key, type), type) : type;
}

function getLiteralTypeKey(type: Type): string | undefined {
const objectFlags = getObjectFlags(type);
if (objectFlags & ObjectFlags.ObjectLiteral) {
const props = getPropertiesOfObjectType(type);
const propTypes = map(props, p => getInternedType(getTypeOfSymbol(p)));
const nameLengths = map(props, p => p.flags & SymbolFlags.Optional ? -(<string>p.escapedName).length : (<string>p.escapedName).length);
const nameStrings = map(props, p => <string>p.escapedName);
return `${getTypeListId(propTypes)}|${nameLengths.join(",")}|${nameStrings.join("")}`;
}
if (objectFlags & ObjectFlags.ArrayLiteral) {
if (isArrayType(type)) {
return `${isReadonlyArrayType(type) ? "R" : "A"}${getTypeId(getInternedType(getTypeArguments(type)[0]))}`;
}
if (isTupleType(type)) {
return `T${getTypeId(type.target)}|${getTypeListId(sameMap(getTypeArguments(type), getInternedType))}`;
}
}
return undefined;
}
}

function isNumericName(name: DeclarationName): boolean {
switch (name.kind) {
case SyntaxKind.ComputedPropertyName:
Expand Down