Skip to content

Commit 4925f2f

Browse files
ahejlsbergsandersn
authored andcommitted
Optimize relations for type references with unconstrained type arguments
1 parent 171c664 commit 4925f2f

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
@@ -8800,8 +8800,7 @@ namespace ts {
88008800
return true;
88018801
}
88028802
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
8803-
const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
8804-
const related = relation.get(id);
8803+
const related = relation.get(getRelationKey(source, target, relation));
88058804
if (related !== undefined) {
88068805
return related === RelationComparisonResult.Succeeded;
88078806
}
@@ -9202,7 +9201,7 @@ namespace ts {
92029201
if (overflow) {
92039202
return Ternary.False;
92049203
}
9205-
const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
9204+
const id = getRelationKey(source, target, relation);
92069205
const related = relation.get(id);
92079206
if (related !== undefined) {
92089207
if (reportErrors && related === RelationComparisonResult.Failed) {
@@ -9767,6 +9766,45 @@ namespace ts {
97679766
}
97689767
}
97699768

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

0 commit comments

Comments
 (0)