@@ -68,18 +68,9 @@ void ConformanceLookupTable::ConformanceEntry::markSupersededBy(
6868 SupersededBy = entry;
6969
7070 if (diagnose) {
71- // If an unavailable Sendable conformance is superseded by a
72- // retroactive one in the client, we need to record this error
73- // at the client decl context.
74- auto *dc = getDeclContext ();
75- if (getProtocol ()->isMarkerProtocol () && isFixed () &&
76- !entry->isFixed ()) {
77- dc = entry->getDeclContext ();
78- }
79-
8071 // Record the problem in the conformance table. We'll
8172 // diagnose these in semantic analysis.
82- table.AllSupersededDiagnostics [dc ].push_back (this );
73+ table.AllSupersededDiagnostics [getDeclContext () ].push_back (this );
8374 }
8475}
8576
@@ -267,6 +258,14 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl,
267258 auto addInheritedConformance = [&](ConformanceEntry *entry) {
268259 auto protocol = entry->getProtocol ();
269260
261+ // Don't add unavailable conformances.
262+ if (auto dc = entry->Source .getDeclContext ()) {
263+ if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
264+ if (AvailableAttr::isUnavailable (ext))
265+ return ;
266+ }
267+ }
268+
270269 // Don't add redundant conformances here. This is merely an
271270 // optimization; resolveConformances() would zap the duplicates
272271 // anyway.
@@ -614,23 +613,30 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
614613 // same conformance, this silently takes the class and drops the extension.
615614 if (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext () !=
616615 rhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()) {
617- // Diagnose conflicting marker protocol conformances that differ in
618- // un-availability.
619- diagnoseSuperseded = lhs->getProtocol ()->isMarkerProtocol ();
620-
621616 return (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()
622617 ? Ordering::Before
623618 : Ordering::After);
624619 }
625620
626621 // If one entry is fixed and the other is not, we have our answer.
627622 if (lhs->isFixed () != rhs->isFixed ()) {
623+ auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool {
624+ ConformanceEntryKind kind = entry->getRankingKind ();
625+ if (isReplaceable (kind))
626+ return true ;
627+
628+ // Allow replacement of an explicit conformance to a marker protocol.
629+ // (This permits redundant explicit declarations of `Sendable`.)
630+ return (kind == ConformanceEntryKind::Explicit
631+ && entry->getProtocol ()->isMarkerProtocol ());
632+ };
633+
628634 // If the non-fixed conformance is not replaceable, we have a failure to
629635 // diagnose.
630636 // FIXME: We should probably diagnose if they have different constraints.
631- diagnoseSuperseded = (lhs->isFixed () && !isReplaceable (rhs-> getRankingKind () )) ||
632- (rhs->isFixed () && !isReplaceable (lhs-> getRankingKind () ));
633-
637+ diagnoseSuperseded = (lhs->isFixed () && !isReplaceableOrMarker (rhs)) ||
638+ (rhs->isFixed () && !isReplaceableOrMarker (lhs));
639+
634640 return lhs->isFixed () ? Ordering::Before : Ordering::After;
635641 }
636642
@@ -873,6 +879,8 @@ DeclContext *ConformanceLookupTable::getConformingContext(
873879 return nullptr ;
874880 auto inheritedConformance = module ->lookupConformance (
875881 superclassTy, protocol, /* allowMissing=*/ false );
882+ if (inheritedConformance.hasUnavailableConformance ())
883+ inheritedConformance = ProtocolConformanceRef::forInvalid ();
876884 if (inheritedConformance)
877885 return superclassDecl;
878886 } while ((superclassDecl = superclassDecl->getSuperclassDecl ()));
@@ -1138,17 +1146,9 @@ void ConformanceLookupTable::lookupConformances(
11381146 if (diagnostics) {
11391147 auto knownDiags = AllSupersededDiagnostics.find (dc);
11401148 if (knownDiags != AllSupersededDiagnostics.end ()) {
1141- for (auto *entry : knownDiags->second ) {
1149+ for (const auto *entry : knownDiags->second ) {
11421150 ConformanceEntry *supersededBy = entry->getSupersededBy ();
11431151
1144- // Diagnose the client conformance as superseded.
1145- auto *definingModule = nominal->getParentModule ();
1146- if (entry->getDeclContext ()->getParentModule () == definingModule &&
1147- supersededBy->getDeclContext ()->getParentModule () != definingModule) {
1148- supersededBy = entry;
1149- entry = entry->getSupersededBy ();
1150- }
1151-
11521152 diagnostics->push_back ({entry->getProtocol (),
11531153 entry->getDeclaredLoc (),
11541154 entry->getKind (),
0 commit comments