[Runtime] Introduce equality operation for nominal type descriptors.

Nominal type descriptors are not always unique, so testing them via pointer
equality is not correct. Introduce an "isEqual()" operation for
nominal type descriptors that performs the appropriate equality check,
using pointer equality when possible, and falling back to string
comparisons of the mangled type name when it is not possible.

Introduce a "nonunique" flag into nominal type descriptors to describe
when they are, in fact, not unique. The only nonunique nominal type
descriptors currently come from Clang-imported types; all
Swift-defined types have unique nominal type descriptors. Use this
flag to make the aforementioned operation efficient in the "unique"
case.

Use the new isEqual() operation for protocol conformance lookup, and
make sure we're caching results based on the known-canonical nominal
type descriptor.
This commit is contained in:
Doug Gregor
2018-01-04 11:47:50 -08:00
parent 12a774abec
commit 6118d86032
6 changed files with 64 additions and 8 deletions

View File

@@ -435,14 +435,18 @@ bool isRelatedType(const Metadata *type, const void *candidate,
bool candidateIsMetadata) {
while (true) {
if (type == candidate && candidateIsMetadata)
// Check whether the types match.
if (candidateIsMetadata && type == candidate)
return true;
// If the type is resilient or generic, see if there's a witness table
// keyed off the nominal type descriptor.
const auto *description = type->getNominalTypeDescriptor();
if (description == candidate && !candidateIsMetadata)
return true;
// Check whether the nominal type descriptors match.
if (!candidateIsMetadata) {
const auto *description = type->getNominalTypeDescriptor();
auto candidateDescription =
static_cast<const NominalTypeDescriptor *>(candidate);
if (description && description->isEqual(candidateDescription))
return true;
}
// If the type is a class, try its superclass.
if (const ClassMetadata *classType = type->getClassObject()) {
@@ -568,7 +572,8 @@ swift::swift_conformsToProtocol(const Metadata * const type,
case ProtocolConformanceReferenceKind::WitnessTable:
// If the record provides a nondependent witness table for all
// instances of a generic type, cache it for the generic pattern.
C.cacheSuccess(R, P, record.getStaticWitnessTable());
C.cacheSuccess(type->getNominalTypeDescriptor(), P,
record.getStaticWitnessTable());
break;
case ProtocolConformanceReferenceKind::WitnessTableAccessor: