@@ -69,9 +69,18 @@ void ConformanceLookupTable::ConformanceEntry::markSupersededBy(
69
69
SupersededBy = entry;
70
70
71
71
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
+
72
81
// Record the problem in the conformance table. We'll
73
82
// diagnose these in semantic analysis.
74
- table.AllSupersededDiagnostics [getDeclContext () ].push_back (this );
83
+ table.AllSupersededDiagnostics [dc ].push_back (this );
75
84
}
76
85
}
77
86
@@ -259,14 +268,6 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl,
259
268
auto addInheritedConformance = [&](ConformanceEntry *entry) {
260
269
auto protocol = entry->getProtocol ();
261
270
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
-
270
271
// Don't add redundant conformances here. This is merely an
271
272
// optimization; resolveConformances() would zap the duplicates
272
273
// anyway.
@@ -614,30 +615,23 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
614
615
// same conformance, this silently takes the class and drops the extension.
615
616
if (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext () !=
616
617
rhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()) {
618
+ // Diagnose conflicting marker protocol conformances that differ in
619
+ // un-availability.
620
+ diagnoseSuperseded = lhs->getProtocol ()->isMarkerProtocol ();
621
+
617
622
return (lhs->getDeclContext ()->isAlwaysAvailableConformanceContext ()
618
623
? Ordering::Before
619
624
: Ordering::After);
620
625
}
621
626
622
627
// If one entry is fixed and the other is not, we have our answer.
623
628
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
-
635
629
// If the non-fixed conformance is not replaceable, we have a failure to
636
630
// diagnose.
637
631
// 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
+
641
635
return lhs->isFixed () ? Ordering::Before : Ordering::After;
642
636
}
643
637
@@ -879,8 +873,6 @@ DeclContext *ConformanceLookupTable::getConformingContext(
879
873
return nullptr ;
880
874
auto inheritedConformance = ModuleDecl::lookupConformance (
881
875
superclassTy, protocol, /* allowMissing=*/ false );
882
- if (inheritedConformance.hasUnavailableConformance ())
883
- inheritedConformance = ProtocolConformanceRef::forInvalid ();
884
876
if (inheritedConformance)
885
877
return superclassDecl;
886
878
} while ((superclassDecl = superclassDecl->getSuperclassDecl ()));
@@ -1145,9 +1137,17 @@ void ConformanceLookupTable::lookupConformances(
1145
1137
if (diagnostics) {
1146
1138
auto knownDiags = AllSupersededDiagnostics.find (dc);
1147
1139
if (knownDiags != AllSupersededDiagnostics.end ()) {
1148
- for (const auto *entry : knownDiags->second ) {
1140
+ for (auto *entry : knownDiags->second ) {
1149
1141
ConformanceEntry *supersededBy = entry->getSupersededBy ();
1150
1142
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
+
1151
1151
diagnostics->push_back ({entry->getProtocol (),
1152
1152
entry->getDeclaredLoc (),
1153
1153
entry->getKind (),
0 commit comments