@@ -513,42 +513,74 @@ searchInConformanceCache(const Metadata *type,
513
513
return ConformanceCacheResult::cacheMiss ();
514
514
}
515
515
516
- // / Checks if a given candidate is a type itself, one of its
517
- // / superclasses or a related generic type.
518
- // /
519
- // / This check is supposed to use the same logic that is used
520
- // / by searchInConformanceCache.
521
- // /
522
- // / \param candidate Pointer to a Metadata or a NominalTypeDescriptor.
523
- // /
524
- static
525
- bool isRelatedType (const Metadata *type, const void *candidate,
526
- bool candidateIsMetadata) {
516
+ namespace {
517
+ // / Describes a protocol conformance "candidate" that can be checked
518
+ // / against the
519
+ class ConformanceCandidate {
520
+ const void *candidate;
521
+ bool candidateIsMetadata;
527
522
528
- while (true ) {
529
- // Check whether the types match.
530
- if (candidateIsMetadata && type == candidate)
531
- return true ;
523
+ public:
524
+ ConformanceCandidate () : candidate(0 ), candidateIsMetadata(false ) { }
525
+
526
+ ConformanceCandidate (const ProtocolConformanceDescriptor &conformance)
527
+ : ConformanceCandidate()
528
+ {
529
+ if (auto metadata = conformance.getCanonicalTypeMetadata ()) {
530
+ candidate = metadata;
531
+ candidateIsMetadata = true ;
532
+ return ;
533
+ }
532
534
533
- // Check whether the nominal type descriptors match.
534
- if (!candidateIsMetadata) {
535
- const auto *description = type->getTypeContextDescriptor ();
536
- auto candidateDescription =
537
- static_cast <const TypeContextDescriptor *>(candidate);
538
- if (description && equalContexts (description, candidateDescription))
539
- return true ;
535
+ if (auto description = conformance.getTypeContextDescriptor ()) {
536
+ candidate = description;
537
+ candidateIsMetadata = false ;
538
+ return ;
539
+ }
540
540
}
541
541
542
- // If there is a superclass, look there.
543
- if (auto superclass = _swift_class_getSuperclass (type)) {
544
- type = superclass;
545
- continue ;
542
+ // / Retrieve the conforming type as metadata, or NULL if the candidate's
543
+ // / conforming type is described in another way (e.g., a nominal type
544
+ // / descriptor).
545
+ const Metadata *getConformingTypeAsMetadata () const {
546
+ return candidateIsMetadata ? static_cast <const Metadata *>(candidate)
547
+ : nullptr ;
546
548
}
547
549
548
- break ;
549
- }
550
+ // / Whether the conforming type exactly matches the conformance candidate.
551
+ bool matches (const Metadata *conformingType) const {
552
+ // Check whether the types match.
553
+ if (candidateIsMetadata && conformingType == candidate)
554
+ return true ;
550
555
551
- return false ;
556
+ // Check whether the nominal type descriptors match.
557
+ if (!candidateIsMetadata) {
558
+ const auto *description = conformingType->getTypeContextDescriptor ();
559
+ auto candidateDescription =
560
+ static_cast <const TypeContextDescriptor *>(candidate);
561
+ if (description && equalContexts (description, candidateDescription))
562
+ return true ;
563
+ }
564
+
565
+ return false ;
566
+ }
567
+
568
+ // / Retrieve the type that matches the conformance candidate, which may
569
+ // / be a superclass of the given type. Returns null if this type does not
570
+ // / match this conformance.
571
+ const Metadata *getMatchingType (const Metadata *conformingType) const {
572
+ while (conformingType) {
573
+ // Check for a match.
574
+ if (matches (conformingType))
575
+ return conformingType;
576
+
577
+ // Look for a superclass.
578
+ conformingType = _swift_class_getSuperclass (conformingType);
579
+ }
580
+
581
+ return nullptr ;
582
+ }
583
+ };
552
584
}
553
585
554
586
const ProtocolConformanceDescriptor *
@@ -661,34 +693,18 @@ swift::_conformsToSwiftProtocol(const Metadata * const type,
661
693
for (const auto &record : section) {
662
694
auto &descriptor = *record.get ();
663
695
664
- // If the record applies to a specific type, cache it.
665
- if (auto metadata = descriptor.getCanonicalTypeMetadata ()) {
666
- auto P = descriptor.getProtocol ();
667
-
668
- // Look for an exact match.
669
- if (protocol != P)
670
- continue ;
671
-
672
- if (!isRelatedType (type, metadata, /* candidateIsMetadata=*/ true ))
673
- continue ;
674
-
675
- // Record the conformance descriptor.
676
- recordResult (descriptor, metadata);
677
- } else if (descriptor.getTypeKind ()
678
- == TypeReferenceKind::DirectNominalTypeDescriptor ||
679
- descriptor.getTypeKind ()
680
- == TypeReferenceKind::IndirectNominalTypeDescriptor) {
681
- auto R = descriptor.getTypeContextDescriptor ();
682
- auto P = descriptor.getProtocol ();
683
-
684
- // Look for an exact match.
685
- if (protocol != P)
686
- continue ;
696
+ // We only care about conformances to the same protocol.
697
+ if (descriptor.getProtocol () != protocol)
698
+ continue ;
687
699
688
- if (!isRelatedType (type, R, /* candidateIsMetadata=*/ false ))
689
- continue ;
700
+ // If there's a matching type, record the positive result.
701
+ ConformanceCandidate candidate (descriptor);
702
+ if (candidate.getMatchingType (type)) {
703
+ const Metadata *matchingType = candidate.getConformingTypeAsMetadata ();
704
+ if (!matchingType)
705
+ matchingType = type;
690
706
691
- recordResult (descriptor, type );
707
+ recordResult (descriptor, matchingType );
692
708
}
693
709
}
694
710
}
@@ -928,18 +944,13 @@ bool swift::_checkGenericRequirements(
928
944
}
929
945
930
946
const Metadata *swift::findConformingSuperclass (
931
- const Metadata *type,
932
- const ProtocolDescriptor *protocol) {
933
- const Metadata *conformingType = type;
934
- while (true ) {
935
- const Metadata *superclass = _swift_class_getSuperclass (conformingType);
936
- if (!superclass)
937
- break ;
938
- if (!swift_conformsToProtocol (superclass, protocol))
939
- break ;
940
- conformingType = superclass;
941
- }
947
+ const Metadata *type,
948
+ const ProtocolConformanceDescriptor *conformance) {
949
+ // Figure out which type we're looking for.
950
+ ConformanceCandidate candidate (*conformance);
942
951
952
+ const Metadata *conformingType = candidate.getMatchingType (type);
953
+ assert (conformingType);
943
954
return conformingType;
944
955
}
945
956
0 commit comments