@@ -535,6 +535,8 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
535
535
//
536
536
// FIXME: Conformance lookup should really depend on source location for
537
537
// this to be 100% correct.
538
+ // FIXME: When a class and an extension with the same availability declare the
539
+ // same conformance, this silently takes the class and drops the extension.
538
540
if (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext () !=
539
541
rhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()) {
540
542
return (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()
@@ -544,12 +546,22 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
544
546
545
547
// If one entry is fixed and the other is not, we have our answer.
546
548
if (lhs->isFixed () != rhs->isFixed ()) {
549
+ auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool {
550
+ ConformanceEntryKind kind = entry->getRankingKind ();
551
+ if (isReplaceable (kind))
552
+ return true ;
553
+
554
+ // Allow replacement of an explicit conformance to a marker protocol.
555
+ // (This permits redundant explicit declarations of `Sendable`.)
556
+ return (kind == ConformanceEntryKind::Explicit
557
+ && entry->getProtocol ()->isMarkerProtocol ());
558
+ };
559
+
547
560
// If the non-fixed conformance is not replaceable, we have a failure to
548
561
// diagnose.
549
- diagnoseSuperseded = (lhs->isFixed () &&
550
- !isReplaceable (rhs->getRankingKind ())) ||
551
- (rhs->isFixed () &&
552
- !isReplaceable (lhs->getRankingKind ()));
562
+ // FIXME: We should probably diagnose if they have different constraints.
563
+ diagnoseSuperseded = (lhs->isFixed () && !isReplaceableOrMarker (rhs)) ||
564
+ (rhs->isFixed () && !isReplaceableOrMarker (lhs));
553
565
554
566
return lhs->isFixed () ? Ordering::Before : Ordering::After;
555
567
}
0 commit comments