Skip to content

addTypeToIntersection performance improvement #32388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 17, 2019
Merged
Changes from all commits
Commits
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
15 changes: 8 additions & 7 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9868,28 +9868,28 @@ namespace ts {
return links.resolvedType;
}

function addTypeToIntersection(typeSet: Type[], includes: TypeFlags, type: Type) {
function addTypeToIntersection(typeSet: Map<Type>, includes: TypeFlags, type: Type) {
const flags = type.flags;
if (flags & TypeFlags.Intersection) {
return addTypesToIntersection(typeSet, includes, (<IntersectionType>type).types);
}
if (isEmptyAnonymousObjectType(type)) {
if (!(includes & TypeFlags.IncludesEmptyObject)) {
includes |= TypeFlags.IncludesEmptyObject;
typeSet.push(type);
typeSet.set(type.id.toString(), type);
Copy link
Member

Choose a reason for hiding this comment

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

We should use the getTypeId function here, since IIRC, type IDs are lazily assigned.

}
}
else {
if (flags & TypeFlags.AnyOrUnknown) {
if (type === wildcardType) includes |= TypeFlags.IncludesWildcard;
}
else if ((strictNullChecks || !(flags & TypeFlags.Nullable)) && !contains(typeSet, type)) {
else if ((strictNullChecks || !(flags & TypeFlags.Nullable)) && !typeSet.has(type.id.toString())) {
if (type.flags & TypeFlags.Unit && includes & TypeFlags.Unit) {
// We have seen two distinct unit types which means we should reduce to an
// empty intersection. Adding TypeFlags.NonPrimitive causes that to happen.
includes |= TypeFlags.NonPrimitive;
}
typeSet.push(type);
typeSet.set(type.id.toString(), type);
}
includes |= flags & TypeFlags.IncludesMask;
}
Expand All @@ -9898,7 +9898,7 @@ namespace ts {

// Add the given types to the given type set. Order is preserved, freshness is removed from literal
// types, duplicates are removed, and nested types of the given kind are flattened into the set.
function addTypesToIntersection(typeSet: Type[], includes: TypeFlags, types: ReadonlyArray<Type>) {
function addTypesToIntersection(typeSet: Map<Type>, includes: TypeFlags, types: ReadonlyArray<Type>) {
for (const type of types) {
includes = addTypeToIntersection(typeSet, includes, getRegularTypeOfLiteralType(type));
}
Expand Down Expand Up @@ -10005,8 +10005,9 @@ namespace ts {
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
// for intersections of types with signatures can be deterministic.
function getIntersectionType(types: ReadonlyArray<Type>, aliasSymbol?: Symbol, aliasTypeArguments?: ReadonlyArray<Type>): Type {
const typeSet: Type[] = [];
const includes = addTypesToIntersection(typeSet, 0, types);
const typeMembershipMap: Map<Type> = createMap();
const includes = addTypesToIntersection(typeMembershipMap, 0, types);
const typeSet: Type[] = arrayFrom(typeMembershipMap.values());
// An intersection type is considered empty if it contains
// the type never, or
// more than one unit type or,
Expand Down