Added protocol matching optimization for the case where the source type and the destination protocol are both non-generic classes. In this case, we can safely cache the protocol relationship and shortcut future checks.

This commit is contained in:
Eric Traut 2022-05-29 22:43:11 -07:00
parent 3730932513
commit 469cc162f9
2 changed files with 30 additions and 0 deletions

View File

@ -76,6 +76,16 @@ export function assignClassToProtocol(
return true;
}
// See if we've already determined that this class is compatible with this protocol.
if (
!treatSourceAsInstantiable &&
destType.details.typeParameters.length === 0 &&
srcType.details.typeParameters.length === 0 &&
srcType.details.compatibleProtocols?.has(destType.details.fullName)
) {
return true;
}
protocolAssignmentStack.push({ srcType, destType });
let isCompatible = true;
@ -100,6 +110,22 @@ export function assignClassToProtocol(
protocolAssignmentStack.pop();
// If the destination protocol is not generic and the source type is not
// generic and the two are compatible, cache that information so we can
// skip the check next time.
if (
isCompatible &&
!treatSourceAsInstantiable &&
destType.details.typeParameters.length === 0 &&
srcType.details.typeParameters.length === 0
) {
if (!srcType.details.compatibleProtocols) {
srcType.details.compatibleProtocols = new Set<string>();
}
srcType.details.compatibleProtocols.add(destType.details.fullName);
}
return isCompatible;
}

View File

@ -479,6 +479,10 @@ interface ClassDetails {
inheritedSlotsNames?: string[];
localSlotsNames?: string[];
// A cache of protocol classes (indexed by the class full name)
// that have been determined to be compatible with this class.
compatibleProtocols?: Set<string>;
// Transforms to apply if this class is used as a metaclass
// or a base class.
classDataClassTransform?: DataClassBehaviors | undefined;