Skip to content

Commit 69477c1

Browse files
committed
Revert "[ConformanceLookup] Always prefer unavailable Sendable conformances from the"
This reverts commit 85b66d1.
1 parent 3ea3c1d commit 69477c1

File tree

8 files changed

+50
-119
lines changed

8 files changed

+50
-119
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3176,9 +3176,6 @@ GROUPED_WARNING(
31763176
"protocol %1%select{|: %2}2",
31773177
(const ValueDecl *, Identifier, StringRef))
31783178

3179-
WARNING(unavailable_conformance,none,
3180-
"conformance of %0 to protocol %1 is already unavailable",
3181-
(Type, Identifier))
31823179
ERROR(redundant_conformance,none,
31833180
"redundant conformance of %0 to protocol %1", (Type, Identifier))
31843181
ERROR(redundant_conformance_conditional,none,

lib/AST/ConformanceLookupTable.cpp

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -598,31 +598,47 @@ ConformanceLookupTable::Ordering ConformanceLookupTable::compareConformances(
598598
}
599599
}
600600

601-
// Unavailable Sendable conformances cannot be replaced by available ones.
602-
if (!lhs->getProtocol()->isMarkerProtocol()) {
603-
// If only one of the conformances is unconditionally available on the
604-
// current deployment target, pick that one.
605-
//
606-
// FIXME: Conformance lookup should really depend on source location for
607-
// this to be 100% correct.
608-
// FIXME: When a class and an extension with the same availability declare the
609-
// same conformance, this silently takes the class and drops the extension.
610-
if (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() !=
611-
rhs->getDeclContext()->isAlwaysAvailableConformanceContext()) {
612-
return (lhs->getDeclContext()->isAlwaysAvailableConformanceContext()
613-
? Ordering::Before
614-
: Ordering::After);
615-
}
601+
// If only one of the conformances is unconditionally available on the
602+
// current deployment target, pick that one.
603+
//
604+
// FIXME: Conformance lookup should really depend on source location for
605+
// this to be 100% correct.
606+
// FIXME: When a class and an extension with the same availability declare the
607+
// same conformance, this silently takes the class and drops the extension.
608+
if (lhs->getDeclContext()->isAlwaysAvailableConformanceContext() !=
609+
rhs->getDeclContext()->isAlwaysAvailableConformanceContext()) {
610+
return (lhs->getDeclContext()->isAlwaysAvailableConformanceContext()
611+
? Ordering::Before
612+
: Ordering::After);
616613
}
617614

618615
// If one entry is fixed and the other is not, we have our answer.
619616
if (lhs->isFixed() != rhs->isFixed()) {
617+
auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool {
618+
ConformanceEntryKind kind = entry->getRankingKind();
619+
if (isReplaceable(kind))
620+
return true;
621+
622+
// Allow replacement of an explicit conformance to a marker protocol.
623+
// (This permits redundant explicit declarations of `Sendable`.)
624+
//
625+
// FIXME: We need to warn on attempts to make an unavailable Sendable
626+
// conformance available, which does not work.
627+
//
628+
// We probably also want to warn if there is an existing, explicit
629+
// conformance, so clients are prompted to remove retroactive unchecked
630+
// Sendable conformances when the proper Sendable conformance is added
631+
// in the original module.
632+
return (kind == ConformanceEntryKind::Explicit
633+
&& entry->getProtocol()->isMarkerProtocol());
634+
};
635+
620636
// If the non-fixed conformance is not replaceable, we have a failure to
621637
// diagnose.
622638
// FIXME: We should probably diagnose if they have different constraints.
623-
diagnoseSuperseded = (lhs->isFixed() && !isReplaceable(rhs->getRankingKind())) ||
624-
(rhs->isFixed() && !isReplaceable(lhs->getRankingKind()));
625-
639+
diagnoseSuperseded = (lhs->isFixed() && !isReplaceableOrMarker(rhs)) ||
640+
(rhs->isFixed() && !isReplaceableOrMarker(lhs));
641+
626642
return lhs->isFixed() ? Ordering::Before : Ordering::After;
627643
}
628644

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 1 addition & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6703,16 +6703,8 @@ ProtocolConformance *swift::deriveImplicitSendableConformance(
67036703

67046704
// Local function to form the implicit conformance.
67056705
auto formConformance = [&](const DeclAttribute *attrMakingUnavailable)
6706-
-> ProtocolConformance * {
6706+
-> NormalProtocolConformance * {
67076707
DeclContext *conformanceDC = nominal;
6708-
6709-
// FIXME: @_nonSendable should be a builtin extension macro. This behavior
6710-
// of explanding the unavailable conformance during implicit Sendable
6711-
// derivation means that clients can unknowingly ignore unavailable Sendable
6712-
// Sendable conformances from the original module added via @_nonSendable
6713-
// because they are not expanded if an explicit conformance is found via
6714-
// conformance lookup. So, if a retroactive, unchecked Sendable conformance
6715-
// is written, no redundant conformance warning is emitted.
67166708
if (attrMakingUnavailable) {
67176709
// Conformance availability is currently tied to the declaring extension.
67186710
// FIXME: This is a hack--we should give conformances real availability.
@@ -6740,18 +6732,6 @@ ProtocolConformance *swift::deriveImplicitSendableConformance(
67406732
file->getOrCreateSynthesizedFile().addTopLevelDecl(extension);
67416733

67426734
conformanceDC = extension;
6743-
6744-
// Let the conformance lookup table register the conformance
6745-
// from the extension. Otherwise, we'll end up with redundant
6746-
// conformances between the explicit conformance from the extension
6747-
// and the conformance synthesized below.
6748-
SmallVector<ProtocolConformance *, 2> conformances;
6749-
nominal->lookupConformance(proto, conformances);
6750-
for (auto conformance : conformances) {
6751-
if (conformance->getDeclContext() == conformanceDC) {
6752-
return conformance;
6753-
}
6754-
}
67556735
}
67566736

67576737
auto conformance = ctx.getNormalConformance(

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6370,56 +6370,20 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
63706370
// protocol, just warn; we'll pick up the original conformance.
63716371
auto existingModule = diag.ExistingDC->getParentModule();
63726372
auto extendedNominal = diag.ExistingDC->getSelfNominalTypeDecl();
6373-
auto definingModule = extendedNominal->getParentModule()->getName();
6374-
bool conformanceInOrigModule =
6375-
(existingModule->getName() == definingModule ||
6373+
if (existingModule != dc->getParentModule() &&
6374+
(existingModule->getName() ==
6375+
extendedNominal->getParentModule()->getName() ||
63766376
existingModule == diag.Protocol->getParentModule() ||
6377-
existingModule->getName().is("CoreGraphics"));
6378-
6379-
// Redundant Sendable conformances are always warnings.
6380-
auto knownProtocol = diag.Protocol->getKnownProtocolKind();
6381-
bool isSendable = knownProtocol == KnownProtocolKind::Sendable;
6382-
// Try to find an inherited Sendable conformance if there is one.
6383-
if (isSendable && !SendableConformance) {
6384-
SmallVector<ProtocolConformance *, 2> conformances;
6385-
nominal->lookupConformance(diag.Protocol, conformances);
6386-
for (auto conformance : conformances) {
6387-
if (isa<InheritedProtocolConformance>(conformance))
6388-
SendableConformance = conformance;
6389-
}
6390-
}
6391-
6392-
if ((existingModule != dc->getParentModule() && conformanceInOrigModule) ||
6393-
isSendable) {
6377+
existingModule->getName().is("CoreGraphics"))) {
63946378
// Warn about the conformance.
6395-
if (isSendable && SendableConformance &&
6396-
isa<InheritedProtocolConformance>(SendableConformance)) {
6397-
// Allow re-stated unchecked conformances to Sendable in subclasses
6398-
// as long as the inherited conformance isn't unavailable.
6399-
auto *conformance = SendableConformance->getRootConformance();
6400-
auto *decl = conformance->getDeclContext()->getAsDecl();
6401-
if (!AvailableAttr::isUnavailable(decl)) {
6402-
continue;
6403-
}
6404-
6405-
Context.Diags.diagnose(diag.Loc, diag::unavailable_conformance,
6406-
nominal->getDeclaredInterfaceType(),
6407-
diag.Protocol->getName());
6408-
} else if (existingModule == dc->getParentModule()) {
6409-
Context.Diags.diagnose(diag.Loc, diag::redundant_conformance,
6410-
nominal->getDeclaredInterfaceType(),
6411-
diag.Protocol->getName())
6412-
.limitBehavior(DiagnosticBehavior::Warning);
6413-
} else {
6414-
auto diagID = differentlyConditional
6415-
? diag::redundant_conformance_adhoc_conditional
6416-
: diag::redundant_conformance_adhoc;
6417-
Context.Diags.diagnose(diag.Loc, diagID, dc->getDeclaredInterfaceType(),
6418-
diag.Protocol->getName(),
6419-
existingModule->getName() ==
6420-
extendedNominal->getParentModule()->getName(),
6421-
existingModule->getName());
6422-
}
6379+
auto diagID = differentlyConditional
6380+
? diag::redundant_conformance_adhoc_conditional
6381+
: diag::redundant_conformance_adhoc;
6382+
Context.Diags.diagnose(diag.Loc, diagID, dc->getDeclaredInterfaceType(),
6383+
diag.Protocol->getName(),
6384+
existingModule->getName() ==
6385+
extendedNominal->getParentModule()->getName(),
6386+
existingModule->getName());
64236387

64246388
// Complain about any declarations in this extension whose names match
64256389
// a requirement in that protocol.

test/Concurrency/Inputs/SendableConformances.swift

Lines changed: 0 additions & 7 deletions
This file was deleted.

test/Concurrency/redundant_sendable_conformance.swift

Lines changed: 0 additions & 19 deletions
This file was deleted.

test/Concurrency/sendable_checking.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,8 +112,8 @@ struct WrapClass<T: NSClass> {
112112

113113
extension WrapClass: Sendable where T: Sendable { }
114114

115-
// expected-warning@+2 {{conformance of 'SendableSubclass' to protocol 'Sendable' is already unavailable}}
116-
// expected-note@+1 {{'SendableSubclass' inherits conformance to protocol 'Sendable' from superclass here}}
115+
// Make sure we don't inherit the unavailable Sendable conformance from
116+
// our superclass.
117117
class SendableSubclass: NSClass, @unchecked Sendable { }
118118

119119
@available(SwiftStdlib 5.1, *)

test/Concurrency/sendable_conformance_checking.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ extension SendableExtSub: @unchecked Sendable {}
180180

181181
// Still want to know about same-class redundancy
182182
class MultiConformance: @unchecked Sendable {} // expected-note {{'MultiConformance' declares conformance to protocol 'Sendable' here}}
183-
extension MultiConformance: @unchecked Sendable {} // expected-warning {{redundant conformance of 'MultiConformance' to protocol 'Sendable'}}
183+
extension MultiConformance: @unchecked Sendable {} // expected-error {{redundant conformance of 'MultiConformance' to protocol 'Sendable'}}
184184

185185
@available(SwiftStdlib 5.1, *)
186186
actor MyActor {

0 commit comments

Comments
 (0)