@@ -481,7 +481,7 @@ searchInConformanceCache(const Metadata *type,
481
481
482
482
namespace {
483
483
// / Describes a protocol conformance "candidate" that can be checked
484
- // / against the
484
+ // / against a type metadata.
485
485
class ConformanceCandidate {
486
486
const void *candidate;
487
487
bool candidateIsMetadata;
@@ -492,17 +492,17 @@ namespace {
492
492
ConformanceCandidate (const ProtocolConformanceDescriptor &conformance)
493
493
: ConformanceCandidate()
494
494
{
495
- if (auto metadata = conformance.getCanonicalTypeMetadata ()) {
496
- candidate = metadata;
497
- candidateIsMetadata = true ;
498
- return ;
499
- }
500
-
501
495
if (auto description = conformance.getTypeDescriptor ()) {
502
496
candidate = description;
503
497
candidateIsMetadata = false ;
504
498
return ;
505
499
}
500
+
501
+ if (auto metadata = conformance.getCanonicalTypeMetadata ()) {
502
+ candidate = metadata;
503
+ candidateIsMetadata = true ;
504
+ return ;
505
+ }
506
506
}
507
507
508
508
// / Retrieve the conforming type as metadata, or NULL if the candidate's
@@ -513,6 +513,29 @@ namespace {
513
513
: nullptr ;
514
514
}
515
515
516
+ const ContextDescriptor *
517
+ getContextDescriptor (const Metadata *conformingType) const {
518
+ const auto *description = conformingType->getTypeContextDescriptor ();
519
+ if (description)
520
+ return description;
521
+
522
+ // Handle single-protocol existential types for self-conformance.
523
+ auto *existentialType = dyn_cast<ExistentialTypeMetadata>(conformingType);
524
+ if (existentialType == nullptr ||
525
+ existentialType->getProtocols ().size () != 1 ||
526
+ existentialType->getSuperclassConstraint () != nullptr )
527
+ return nullptr ;
528
+
529
+ auto proto = existentialType->getProtocols ()[0 ];
530
+
531
+ #if SWIFT_OBJC_INTEROP
532
+ if (proto.isObjC ())
533
+ return nullptr ;
534
+ #endif
535
+
536
+ return proto.getSwiftProtocol ();
537
+ }
538
+
516
539
// / Whether the conforming type exactly matches the conformance candidate.
517
540
bool matches (const Metadata *conformingType) const {
518
541
// Check whether the types match.
@@ -521,7 +544,7 @@ namespace {
521
544
522
545
// Check whether the nominal type descriptors match.
523
546
if (!candidateIsMetadata) {
524
- const auto *description = conformingType-> getTypeContextDescriptor ( );
547
+ const auto *description = getContextDescriptor (conformingType );
525
548
auto candidateDescription =
526
549
static_cast <const ContextDescriptor *>(candidate);
527
550
if (description && equalContexts (description, candidateDescription))
0 commit comments