Skip to content

Commit 5e3cf7d

Browse files
committed
Revert "[ConformanceLookup] Always prefer unavailable Sendable conformances from the"
This reverts commit 8159d20.
1 parent 57de275 commit 5e3cf7d

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
@@ -3129,9 +3129,6 @@ WARNING(witness_deprecated,none,
31293129
"protocol %1%select{|: %2}2",
31303130
(const ValueDecl *, Identifier, StringRef))
31313131

3132-
WARNING(unavailable_conformance,none,
3133-
"conformance of %0 to protocol %1 is already unavailable",
3134-
(Type, Identifier))
31353132
ERROR(redundant_conformance,none,
31363133
"redundant conformance of %0 to protocol %1", (Type, Identifier))
31373134
ERROR(redundant_conformance_conditional,none,

lib/AST/ConformanceLookupTable.cpp

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

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

616613
// If one entry is fixed and the other is not, we have our answer.
617614
if (lhs->isFixed() != rhs->isFixed()) {
615+
auto isReplaceableOrMarker = [](ConformanceEntry *entry) -> bool {
616+
ConformanceEntryKind kind = entry->getRankingKind();
617+
if (isReplaceable(kind))
618+
return true;
619+
620+
// Allow replacement of an explicit conformance to a marker protocol.
621+
// (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.
630+
return (kind == ConformanceEntryKind::Explicit
631+
&& entry->getProtocol()->isMarkerProtocol());
632+
};
633+
618634
// If the non-fixed conformance is not replaceable, we have a failure to
619635
// diagnose.
620636
// FIXME: We should probably diagnose if they have different constraints.
621-
diagnoseSuperseded = (lhs->isFixed() && !isReplaceable(rhs->getRankingKind())) ||
622-
(rhs->isFixed() && !isReplaceable(lhs->getRankingKind()));
623-
637+
diagnoseSuperseded = (lhs->isFixed() && !isReplaceableOrMarker(rhs)) ||
638+
(rhs->isFixed() && !isReplaceableOrMarker(lhs));
639+
624640
return lhs->isFixed() ? Ordering::Before : Ordering::After;
625641
}
626642

lib/Sema/TypeCheckConcurrency.cpp

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

64436443
// Local function to form the implicit conformance.
64446444
auto formConformance = [&](const DeclAttribute *attrMakingUnavailable)
6445-
-> ProtocolConformance * {
6445+
-> NormalProtocolConformance * {
64466446
DeclContext *conformanceDC = nominal;
6447-
6448-
// FIXME: @_nonSendable should be a builtin extension macro. This behavior
6449-
// of explanding the unavailable conformance during implicit Sendable
6450-
// derivation means that clients can unknowingly ignore unavailable Sendable
6451-
// Sendable conformances from the original module added via @_nonSendable
6452-
// because they are not expanded if an explicit conformance is found via
6453-
// conformance lookup. So, if a retroactive, unchecked Sendable conformance
6454-
// is written, no redundant conformance warning is emitted.
64556447
if (attrMakingUnavailable) {
64566448
// Conformance availability is currently tied to the declaring extension.
64576449
// FIXME: This is a hack--we should give conformances real availability.
@@ -6479,18 +6471,6 @@ ProtocolConformance *swift::deriveImplicitSendableConformance(
64796471
file->getOrCreateSynthesizedFile().addTopLevelDecl(extension);
64806472

64816473
conformanceDC = extension;
6482-
6483-
// Let the conformance lookup table register the conformance
6484-
// from the extension. Otherwise, we'll end up with redundant
6485-
// conformances between the explicit conformance from the extension
6486-
// and the conformance synthesized below.
6487-
SmallVector<ProtocolConformance *, 2> conformances;
6488-
nominal->lookupConformance(proto, conformances);
6489-
for (auto conformance : conformances) {
6490-
if (conformance->getDeclContext() == conformanceDC) {
6491-
return conformance;
6492-
}
6493-
}
64946474
}
64956475

64966476
auto conformance = ctx.getNormalConformance(

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 12 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -6263,56 +6263,20 @@ void TypeChecker::checkConformancesInContext(IterableDeclContext *idc) {
62636263
// protocol, just warn; we'll pick up the original conformance.
62646264
auto existingModule = diag.ExistingDC->getParentModule();
62656265
auto extendedNominal = diag.ExistingDC->getSelfNominalTypeDecl();
6266-
auto definingModule = extendedNominal->getParentModule()->getName();
6267-
bool conformanceInOrigModule =
6268-
(existingModule->getName() == definingModule ||
6266+
if (existingModule != dc->getParentModule() &&
6267+
(existingModule->getName() ==
6268+
extendedNominal->getParentModule()->getName() ||
62696269
existingModule == diag.Protocol->getParentModule() ||
6270-
existingModule->getName().is("CoreGraphics"));
6271-
6272-
// Redundant Sendable conformances are always warnings.
6273-
auto knownProtocol = diag.Protocol->getKnownProtocolKind();
6274-
bool isSendable = knownProtocol == KnownProtocolKind::Sendable;
6275-
// Try to find an inherited Sendable conformance if there is one.
6276-
if (isSendable && !SendableConformance) {
6277-
SmallVector<ProtocolConformance *, 2> conformances;
6278-
nominal->lookupConformance(diag.Protocol, conformances);
6279-
for (auto conformance : conformances) {
6280-
if (isa<InheritedProtocolConformance>(conformance))
6281-
SendableConformance = conformance;
6282-
}
6283-
}
6284-
6285-
if ((existingModule != dc->getParentModule() && conformanceInOrigModule) ||
6286-
isSendable) {
6270+
existingModule->getName().is("CoreGraphics"))) {
62876271
// Warn about the conformance.
6288-
if (isSendable && SendableConformance &&
6289-
isa<InheritedProtocolConformance>(SendableConformance)) {
6290-
// Allow re-stated unchecked conformances to Sendable in subclasses
6291-
// as long as the inherited conformance isn't unavailable.
6292-
auto *conformance = SendableConformance->getRootConformance();
6293-
auto *decl = conformance->getDeclContext()->getAsDecl();
6294-
if (!AvailableAttr::isUnavailable(decl)) {
6295-
continue;
6296-
}
6297-
6298-
Context.Diags.diagnose(diag.Loc, diag::unavailable_conformance,
6299-
nominal->getDeclaredInterfaceType(),
6300-
diag.Protocol->getName());
6301-
} else if (existingModule == dc->getParentModule()) {
6302-
Context.Diags.diagnose(diag.Loc, diag::redundant_conformance,
6303-
nominal->getDeclaredInterfaceType(),
6304-
diag.Protocol->getName())
6305-
.limitBehavior(DiagnosticBehavior::Warning);
6306-
} else {
6307-
auto diagID = differentlyConditional
6308-
? diag::redundant_conformance_adhoc_conditional
6309-
: diag::redundant_conformance_adhoc;
6310-
Context.Diags.diagnose(diag.Loc, diagID, dc->getDeclaredInterfaceType(),
6311-
diag.Protocol->getName(),
6312-
existingModule->getName() ==
6313-
extendedNominal->getParentModule()->getName(),
6314-
existingModule->getName());
6315-
}
6272+
auto diagID = differentlyConditional
6273+
? diag::redundant_conformance_adhoc_conditional
6274+
: diag::redundant_conformance_adhoc;
6275+
Context.Diags.diagnose(diag.Loc, diagID, dc->getDeclaredInterfaceType(),
6276+
diag.Protocol->getName(),
6277+
existingModule->getName() ==
6278+
extendedNominal->getParentModule()->getName(),
6279+
existingModule->getName());
63166280

63176281
// Complain about any declarations in this extension whose names match
63186282
// 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
@@ -113,8 +113,8 @@ struct WrapClass<T: NSClass> {
113113

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

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

120120
@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)