@@ -68,9 +68,18 @@ 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+
7180 // Record the problem in the conformance table. We'll
7281 // diagnose these in semantic analysis.
73- table.AllSupersededDiagnostics [getDeclContext () ].push_back (this );
82+ table.AllSupersededDiagnostics [dc ].push_back (this );
7483 }
7584}
7685
@@ -258,14 +267,6 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl,
258267 auto addInheritedConformance = [&](ConformanceEntry *entry) {
259268 auto protocol = entry->getProtocol ();
260269
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-
269270 // Don't add redundant conformances here. This is merely an
270271 // optimization; resolveConformances() would zap the duplicates
271272 // anyway.
@@ -613,30 +614,23 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
613614 // same conformance, this silently takes the class and drops the extension.
614615 if (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext () !=
615616 rhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()) {
617+ // Diagnose conflicting marker protocol conformances that differ in
618+ // un-availability.
619+ diagnoseSuperseded = lhs->getProtocol ()->isMarkerProtocol ();
620+
616621 return (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()
617622 ? Ordering::Before
618623 : Ordering::After);
619624 }
620625
621626 // If one entry is fixed and the other is not, we have our answer.
622627 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-
634628 // If the non-fixed conformance is not replaceable, we have a failure to
635629 // diagnose.
636630 // FIXME: We should probably diagnose if they have different constraints.
637- diagnoseSuperseded = (lhs->isFixed () && !isReplaceableOrMarker (rhs)) ||
638- (rhs->isFixed () && !isReplaceableOrMarker (lhs));
639-
631+ diagnoseSuperseded = (lhs->isFixed () && !isReplaceable (rhs-> getRankingKind () )) ||
632+ (rhs->isFixed () && !isReplaceable (lhs-> getRankingKind () ));
633+
640634 return lhs->isFixed () ? Ordering::Before : Ordering::After;
641635 }
642636
@@ -879,8 +873,6 @@ DeclContext *ConformanceLookupTable::getConformingContext(
879873 return nullptr ;
880874 auto inheritedConformance = module ->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 ()));
@@ -1146,9 +1138,17 @@ void ConformanceLookupTable::lookupConformances(
11461138 if (diagnostics) {
11471139 auto knownDiags = AllSupersededDiagnostics.find (dc);
11481140 if (knownDiags != AllSupersededDiagnostics.end ()) {
1149- for (const auto *entry : knownDiags->second ) {
1141+ for (auto *entry : knownDiags->second ) {
11501142 ConformanceEntry *supersededBy = entry->getSupersededBy ();
11511143
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