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