@@ -456,42 +456,74 @@ searchInConformanceCache(const Metadata *type,
456
456
return ConformanceCacheResult::cacheMiss ();
457
457
}
458
458
459
- // / Checks if a given candidate is a type itself, one of its
460
- // / superclasses or a related generic type.
461
- // /
462
- // / This check is supposed to use the same logic that is used
463
- // / by searchInConformanceCache.
464
- // /
465
- // / \param candidate Pointer to a Metadata or a NominalTypeDescriptor.
466
- // /
467
- static
468
- bool isRelatedType (const Metadata *type, const void *candidate,
469
- bool candidateIsMetadata) {
459
+ namespace {
460
+ // / Describes a protocol conformance "candidate" that can be checked
461
+ // / against the
462
+ class ConformanceCandidate {
463
+ const void *candidate;
464
+ bool candidateIsMetadata;
470
465
471
- while (true ) {
472
- // Check whether the types match.
473
- if (candidateIsMetadata && type == candidate)
474
- return true ;
466
+ public:
467
+ ConformanceCandidate () : candidate(0 ), candidateIsMetadata(false ) { }
468
+
469
+ ConformanceCandidate (const ProtocolConformanceDescriptor &conformance)
470
+ : ConformanceCandidate()
471
+ {
472
+ if (auto metadata = conformance.getCanonicalTypeMetadata ()) {
473
+ candidate = metadata;
474
+ candidateIsMetadata = true ;
475
+ return ;
476
+ }
475
477
476
- // Check whether the nominal type descriptors match.
477
- if (!candidateIsMetadata) {
478
- const auto *description = type->getTypeContextDescriptor ();
479
- auto candidateDescription =
480
- static_cast <const TypeContextDescriptor *>(candidate);
481
- if (description && equalContexts (description, candidateDescription))
482
- return true ;
478
+ if (auto description = conformance.getTypeContextDescriptor ()) {
479
+ candidate = description;
480
+ candidateIsMetadata = false ;
481
+ return ;
482
+ }
483
483
}
484
484
485
- // If there is a superclass, look there.
486
- if (auto superclass = _swift_class_getSuperclass (type)) {
487
- type = superclass;
488
- continue ;
485
+ // / Retrieve the conforming type as metadata, or NULL if the candidate's
486
+ // / conforming type is described in another way (e.g., a nominal type
487
+ // / descriptor).
488
+ const Metadata *getConformingTypeAsMetadata () const {
489
+ return candidateIsMetadata ? static_cast <const Metadata *>(candidate)
490
+ : nullptr ;
489
491
}
490
492
491
- break ;
492
- }
493
+ // / Whether the conforming type exactly matches the conformance candidate.
494
+ bool matches (const Metadata *conformingType) const {
495
+ // Check whether the types match.
496
+ if (candidateIsMetadata && conformingType == candidate)
497
+ return true ;
493
498
494
- return false ;
499
+ // Check whether the nominal type descriptors match.
500
+ if (!candidateIsMetadata) {
501
+ const auto *description = conformingType->getTypeContextDescriptor ();
502
+ auto candidateDescription =
503
+ static_cast <const TypeContextDescriptor *>(candidate);
504
+ if (description && equalContexts (description, candidateDescription))
505
+ return true ;
506
+ }
507
+
508
+ return false ;
509
+ }
510
+
511
+ // / Retrieve the type that matches the conformance candidate, which may
512
+ // / be a superclass of the given type. Returns null if this type does not
513
+ // / match this conformance.
514
+ const Metadata *getMatchingType (const Metadata *conformingType) const {
515
+ while (conformingType) {
516
+ // Check for a match.
517
+ if (matches (conformingType))
518
+ return conformingType;
519
+
520
+ // Look for a superclass.
521
+ conformingType = _swift_class_getSuperclass (conformingType);
522
+ }
523
+
524
+ return nullptr ;
525
+ }
526
+ };
495
527
}
496
528
497
529
static const WitnessTable *
@@ -541,38 +573,18 @@ swift_conformsToProtocolImpl(const Metadata * const type,
541
573
for (const auto &record : section) {
542
574
auto &descriptor = *record.get ();
543
575
544
- // If the record applies to a specific type, cache it.
545
- if (auto metadata = descriptor.getCanonicalTypeMetadata ()) {
546
- auto P = descriptor.getProtocol ();
547
-
548
- // Look for an exact match.
549
- if (protocol != P)
550
- continue ;
551
-
552
- if (!isRelatedType (type, metadata, /* candidateIsMetadata=*/ true ))
553
- continue ;
554
-
555
- // Record the witness table.
556
- recordWitnessTable (descriptor, metadata);
557
-
558
- // TODO: "Nondependent witness table" probably deserves its own flag.
559
- // An accessor function might still be necessary even if the witness table
560
- // can be shared.
561
- } else if (descriptor.getTypeKind ()
562
- == TypeReferenceKind::DirectNominalTypeDescriptor ||
563
- descriptor.getTypeKind ()
564
- == TypeReferenceKind::IndirectNominalTypeDescriptor) {
565
- auto R = descriptor.getTypeContextDescriptor ();
566
- auto P = descriptor.getProtocol ();
567
-
568
- // Look for an exact match.
569
- if (protocol != P)
570
- continue ;
576
+ // We only care about conformances for this protocol.
577
+ if (descriptor.getProtocol () != protocol)
578
+ continue ;
571
579
572
- if (!isRelatedType (type, R, /* candidateIsMetadata=*/ false ))
573
- continue ;
580
+ // If there's a matching type, record the positive result.
581
+ ConformanceCandidate candidate (descriptor);
582
+ if (candidate.getMatchingType (type)) {
583
+ const Metadata *matchingType = candidate.getConformingTypeAsMetadata ();
584
+ if (!matchingType)
585
+ matchingType = type;
574
586
575
- recordWitnessTable (descriptor, type );
587
+ recordWitnessTable (descriptor, matchingType );
576
588
}
577
589
}
578
590
}
@@ -692,18 +704,13 @@ bool swift::_checkGenericRequirements(
692
704
}
693
705
694
706
const Metadata *swift::findConformingSuperclass (
695
- const Metadata *type,
696
- const ProtocolDescriptor *protocol) {
697
- const Metadata *conformingType = type;
698
- while (true ) {
699
- const Metadata *superclass = _swift_class_getSuperclass (conformingType);
700
- if (!superclass)
701
- break ;
702
- if (!swift_conformsToProtocol (superclass, protocol))
703
- break ;
704
- conformingType = superclass;
705
- }
707
+ const Metadata *type,
708
+ const ProtocolConformanceDescriptor *conformance) {
709
+ // Figure out which type we're looking for.
710
+ ConformanceCandidate candidate (*conformance);
706
711
712
+ const Metadata *conformingType = candidate.getMatchingType (type);
713
+ assert (conformingType);
707
714
return conformingType;
708
715
}
709
716
0 commit comments