@@ -535,6 +535,8 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
535535 //
536536 // FIXME: Conformance lookup should really depend on source location for
537537 // 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.
538540 if (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext () !=
539541 rhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()) {
540542 return (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()
@@ -544,12 +546,22 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
544546
545547 // If one entry is fixed and the other is not, we have our answer.
546548 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+
547560 // If the non-fixed conformance is not replaceable, we have a failure to
548561 // 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));
553565
554566 return lhs->isFixed () ? Ordering::Before : Ordering::After;
555567 }
0 commit comments