Skip to content

Commit a3a2ff5

Browse files
committed
Optimize relations for type references with unconstrained type arguments
1 parent 2b10784 commit a3a2ff5

File tree

1 file changed

+41
-3
lines changed

1 file changed

+41
-3
lines changed

src/compiler/checker.ts

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8805,8 +8805,7 @@ namespace ts {
88058805
return true;
88068806
}
88078807
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
8808-
const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
8809-
const related = relation.get(id);
8808+
const related = relation.get(getRelationKey(source, target, relation));
88108809
if (related !== undefined) {
88118810
return related === RelationComparisonResult.Succeeded;
88128811
}
@@ -9207,7 +9206,7 @@ namespace ts {
92079206
if (overflow) {
92089207
return Ternary.False;
92099208
}
9210-
const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
9209+
const id = getRelationKey(source, target, relation);
92119210
const related = relation.get(id);
92129211
if (related !== undefined) {
92139212
if (reportErrors && related === RelationComparisonResult.Failed) {
@@ -9772,6 +9771,45 @@ namespace ts {
97729771
}
97739772
}
97749773

9774+
function isUnconstrainedTypeParameter(type: Type) {
9775+
return type.flags & TypeFlags.TypeParameter && !getConstraintFromTypeParameter(<TypeParameter>type);
9776+
}
9777+
9778+
function isTypeReferenceWithGenericArguments(type: Type) {
9779+
return getObjectFlags(type) & ObjectFlags.Reference && some((<TypeReference>type).typeArguments, isUnconstrainedTypeParameter);
9780+
}
9781+
9782+
function getTypeReferenceId(type: TypeReference, typeParameters: Type[]) {
9783+
let result = "" + type.id;
9784+
for (const t of type.typeArguments) {
9785+
if (isUnconstrainedTypeParameter(t)) {
9786+
let index = indexOf(typeParameters, t);
9787+
if (index < 0) {
9788+
index = typeParameters.length;
9789+
typeParameters.push(t);
9790+
}
9791+
result += "=" + index;
9792+
}
9793+
else {
9794+
result += "-" + t.id;
9795+
}
9796+
}
9797+
return result;
9798+
}
9799+
9800+
function getRelationKey(source: Type, target: Type, relation: Map<RelationComparisonResult>) {
9801+
if (relation === identityRelation && source.id > target.id) {
9802+
const temp = source;
9803+
source = target;
9804+
target = temp;
9805+
}
9806+
if (isTypeReferenceWithGenericArguments(source) && isTypeReferenceWithGenericArguments(target)) {
9807+
const typeParameters: Type[] = [];
9808+
return getTypeReferenceId(<TypeReference>source, typeParameters) + "," + getTypeReferenceId(<TypeReference>target, typeParameters);
9809+
}
9810+
return source.id + "," + target.id;
9811+
}
9812+
97759813
// Invoke the callback for each underlying property symbol of the given symbol and return the first
97769814
// value that isn't undefined.
97779815
function forEachProperty<T>(prop: Symbol, callback: (p: Symbol) => T): T {

0 commit comments

Comments
 (0)