Skip to content

Commit 5ecfee7

Browse files
committed
[ConformanceLookup] Don't allow skipping inherited unavailable conformances
in favor of explicit available ones. The type checker does not support the notion of multiple protocol conformances; there can only be one conformance, and if that conformance is unavailable, you cannot specify your own available conformance. This is important for Sendable checking; if a framework specifies that a type is explicitly not Sendable with an unavailable Sendable conformance, clients cannot ignore Sendable violations involving that type. If a superclass wants to allow subclasses to add a Sendable conformance, it should not declare an unavailable Sendable conformance. (cherry picked from commit 7356fe8)
1 parent ce381e7 commit 5ecfee7

File tree

2 files changed

+13
-12
lines changed

2 files changed

+13
-12
lines changed

lib/AST/ConformanceLookupTable.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -258,14 +258,6 @@ void ConformanceLookupTable::inheritConformances(ClassDecl *classDecl,
258258
auto addInheritedConformance = [&](ConformanceEntry *entry) {
259259
auto protocol = entry->getProtocol();
260260

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-
269261
// Don't add redundant conformances here. This is merely an
270262
// optimization; resolveConformances() would zap the duplicates
271263
// anyway.
@@ -627,6 +619,14 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
627619

628620
// Allow replacement of an explicit conformance to a marker protocol.
629621
// (This permits redundant explicit declarations of `Sendable`.)
622+
//
623+
// FIXME: We need to warn on attempts to make an unavailable Sendable
624+
// conformance available, which does not work.
625+
//
626+
// We probably also want to warn if there is an existing, explicit
627+
// conformance, so clients are prompted to remove retroactive unchecked
628+
// Sendable conformances when the proper Sendable conformance is added
629+
// in the original module.
630630
return (kind == ConformanceEntryKind::Explicit
631631
&& entry->getProtocol()->isMarkerProtocol());
632632
};
@@ -879,8 +879,6 @@ DeclContext *ConformanceLookupTable::getConformingContext(
879879
return nullptr;
880880
auto inheritedConformance = module->lookupConformance(
881881
superclassTy, protocol, /*allowMissing=*/false);
882-
if (inheritedConformance.hasUnavailableConformance())
883-
inheritedConformance = ProtocolConformanceRef::forInvalid();
884882
if (inheritedConformance)
885883
return superclassDecl;
886884
} while ((superclassDecl = superclassDecl->getSuperclassDecl()));

test/Concurrency/sendable_checking.swift

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ public actor MyActor: MyProto {
102102
}
103103

104104
// Make sure the generic signature doesn't minimize away Sendable requirements.
105-
@_nonSendable class NSClass { }
105+
class NSClass { }
106+
107+
@available(*, unavailable)
108+
extension NSClass: @unchecked Sendable {} // expected-note {{conformance of 'NSClass' to 'Sendable' has been explicitly marked unavailable here}}
106109

107110
struct WrapClass<T: NSClass> {
108111
var t: T
@@ -116,7 +119,7 @@ class SendableSubclass: NSClass, @unchecked Sendable { }
116119

117120
@available(SwiftStdlib 5.1, *)
118121
func testSubclassing(obj: SendableSubclass) async {
119-
acceptCV(obj) // okay!
122+
acceptCV(obj) // expected-warning {{conformance of 'NSClass' to 'Sendable' is unavailable; this is an error in the Swift 6 language mode}}
120123
}
121124

122125

0 commit comments

Comments
 (0)