@@ -69,9 +69,18 @@ void ConformanceLookupTable::ConformanceEntry::markSupersededBy(
6969 SupersededBy = entry;
7070
7171 if (diagnose) {
72+ // If an unavailable Sendable conformance is superseded by a
73+ // retroactive one in the client, we need to record this error
74+ // at the client decl context.
75+ auto *dc = getDeclContext ();
76+ if (getProtocol ()->isMarkerProtocol () && isFixed () &&
77+ !entry->isFixed ()) {
78+ dc = entry->getDeclContext ();
79+ }
80+
7281 // Record the problem in the conformance table. We'll
7382 // diagnose these in semantic analysis.
74- table.AllSupersededDiagnostics [getDeclContext () ].push_back (this );
83+ table.AllSupersededDiagnostics [dc ].push_back (this );
7584 }
7685}
7786
@@ -259,14 +268,6 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl,
259268 auto addInheritedConformance = [&](ConformanceEntry *entry) {
260269 auto protocol = entry->getProtocol ();
261270
262- // Don't add unavailable conformances.
263- if (auto dc = entry->Source .getDeclContext ()) {
264- if (auto ext = dyn_cast<ExtensionDecl>(dc)) {
265- if (AvailableAttr::isUnavailable (ext))
266- return ;
267- }
268- }
269-
270271 // Don't add redundant conformances here. This is merely an
271272 // optimization; resolveConformances() would zap the duplicates
272273 // anyway.
@@ -614,30 +615,23 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
614615 // same conformance, this silently takes the class and drops the extension.
615616 if (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext () !=
616617 rhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()) {
618+ // Diagnose conflicting marker protocol conformances that differ in
619+ // un-availability.
620+ diagnoseSuperseded = lhs->getProtocol ()->isMarkerProtocol ();
621+
617622 return (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()
618623 ? Ordering::Before
619624 : Ordering::After);
620625 }
621626
622627 // If one entry is fixed and the other is not, we have our answer.
623628 if (lhs->isFixed () != rhs->isFixed ()) {
624- auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool {
625- ConformanceEntryKind kind = entry->getRankingKind ();
626- if (isReplaceable (kind))
627- return true ;
628-
629- // Allow replacement of an explicit conformance to a marker protocol.
630- // (This permits redundant explicit declarations of `Sendable`.)
631- return (kind == ConformanceEntryKind::Explicit
632- && entry->getProtocol ()->isMarkerProtocol ());
633- };
634-
635629 // If the non-fixed conformance is not replaceable, we have a failure to
636630 // diagnose.
637631 // FIXME: We should probably diagnose if they have different constraints.
638- diagnoseSuperseded = (lhs->isFixed () && !isReplaceableOrMarker (rhs)) ||
639- (rhs->isFixed () && !isReplaceableOrMarker (lhs));
640-
632+ diagnoseSuperseded = (lhs->isFixed () && !isReplaceable (rhs-> getRankingKind () )) ||
633+ (rhs->isFixed () && !isReplaceable (lhs-> getRankingKind () ));
634+
641635 return lhs->isFixed () ? Ordering::Before : Ordering::After;
642636 }
643637
@@ -879,8 +873,6 @@ DeclContext *ConformanceLookupTable::getConformingContext(
879873 return nullptr ;
880874 auto inheritedConformance = ModuleDecl::lookupConformance (
881875 superclassTy, protocol, /* allowMissing=*/ false );
882- if (inheritedConformance.hasUnavailableConformance ())
883- inheritedConformance = ProtocolConformanceRef::forInvalid ();
884876 if (inheritedConformance)
885877 return superclassDecl;
886878 } while ((superclassDecl = superclassDecl->getSuperclassDecl ()));
@@ -1145,9 +1137,17 @@ void ConformanceLookupTable::lookupConformances(
11451137 if (diagnostics) {
11461138 auto knownDiags = AllSupersededDiagnostics.find (dc);
11471139 if (knownDiags != AllSupersededDiagnostics.end ()) {
1148- for (const auto *entry : knownDiags->second ) {
1140+ for (auto *entry : knownDiags->second ) {
11491141 ConformanceEntry *supersededBy = entry->getSupersededBy ();
11501142
1143+ // Diagnose the client conformance as superseded.
1144+ auto *definingModule = nominal->getParentModule ();
1145+ if (entry->getDeclContext ()->getParentModule () == definingModule &&
1146+ supersededBy->getDeclContext ()->getParentModule () != definingModule) {
1147+ supersededBy = entry;
1148+ entry = entry->getSupersededBy ();
1149+ }
1150+
11511151 diagnostics->push_back ({entry->getProtocol (),
11521152 entry->getDeclaredLoc (),
11531153 entry->getKind (),
0 commit comments