Skip to content

Commit 48150e5

Browse files
committed
Fix ABI mismatch involving Sendable-refining protocols and deployment targets
A change to the way we determined whether a protocol conformance is "dependent" for marker protocols caused an ABI break for Sendable-refining protocols built with pre-6.0 Swift compilers. The fix for this issue (#75769) gated the change on deployment target. The deployment target change fixed the original problem, then caused a related issue when a project mixes deployment targets (pre-6.0 and 6.0+) with non-resilient protocols. Exempt non-resilient protocols from this change so we get consistent behavior. Fixes rdar://134953989.
1 parent c23563f commit 48150e5

File tree

3 files changed

+41
-10
lines changed

3 files changed

+41
-10
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,10 @@ static bool isSynthesizedNonUnique(const RootProtocolConformance *conformance) {
10301030
}
10311031

10321032
/// Determine whether a protocol can ever have a dependent conformance.
1033-
static bool protocolCanHaveDependentConformance(ProtocolDecl *proto) {
1033+
static bool protocolCanHaveDependentConformance(
1034+
ProtocolDecl *proto,
1035+
bool isResilient
1036+
) {
10341037
// Objective-C protocols have never been able to have a dependent conformance.
10351038
if (proto->isObjC())
10361039
return false;
@@ -1040,13 +1043,14 @@ static bool protocolCanHaveDependentConformance(ProtocolDecl *proto) {
10401043
// is a marker protocol (since they don't have requirements), but we must
10411044
// retain backward compatibility with binaries built for earlier deployment
10421045
// targets that concluded that these protocols might involve dependent
1043-
// conformances.
1044-
ASTContext &ctx = proto->getASTContext();
1045-
if (auto runtimeCompatVersion = getSwiftRuntimeCompatibilityVersionForTarget(
1046-
ctx.LangOpts.Target)) {
1047-
if (runtimeCompatVersion < llvm::VersionTuple(6, 0) &&
1048-
proto->isSpecificProtocol(KnownProtocolKind::Sendable))
1049-
return true;
1046+
// conformances. Only do this for resilient protocols.
1047+
if (isResilient && proto->isSpecificProtocol(KnownProtocolKind::Sendable)) {
1048+
ASTContext &ctx = proto->getASTContext();
1049+
if (auto runtimeCompatVersion = getSwiftRuntimeCompatibilityVersionForTarget(
1050+
ctx.LangOpts.Target)) {
1051+
if (runtimeCompatVersion < llvm::VersionTuple(6, 0))
1052+
return true;
1053+
}
10501054
}
10511055

10521056
return Lowering::TypeConverter::protocolRequiresWitnessTable(proto);
@@ -1055,6 +1059,7 @@ static bool protocolCanHaveDependentConformance(ProtocolDecl *proto) {
10551059
static bool isDependentConformance(
10561060
IRGenModule &IGM,
10571061
const RootProtocolConformance *rootConformance,
1062+
bool isResilient,
10581063
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> &visited){
10591064
// Self-conformances are never dependent.
10601065
auto conformance = dyn_cast<NormalProtocolConformance>(rootConformance);
@@ -1084,7 +1089,8 @@ static bool isDependentConformance(
10841089
continue;
10851090

10861091
auto assocProtocol = req.getProtocolDecl();
1087-
if (!protocolCanHaveDependentConformance(assocProtocol))
1092+
if (!protocolCanHaveDependentConformance(
1093+
assocProtocol, isResilient))
10881094
continue;
10891095

10901096
auto assocConformance =
@@ -1098,6 +1104,7 @@ static bool isDependentConformance(
10981104
isDependentConformance(IGM,
10991105
assocConformance.getConcrete()
11001106
->getRootConformance(),
1107+
isResilient,
11011108
visited))
11021109
return true;
11031110
}
@@ -1166,7 +1173,8 @@ static bool hasConditionalConformances(IRGenModule &IGM,
11661173
bool IRGenModule::isDependentConformance(
11671174
const RootProtocolConformance *conformance) {
11681175
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> visited;
1169-
return ::isDependentConformance(*this, conformance, visited);
1176+
return ::isDependentConformance(
1177+
*this, conformance, conformance->getProtocol()->isResilient(), visited);
11701178
}
11711179

11721180
static llvm::Value *

test/IRGen/protocol_resilience_sendable.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
// RUN: %empty-directory(%t)
22

33
// RUN: %target-swift-frontend -emit-module -enable-library-evolution -emit-module-path=%t/resilient_protocol.swiftmodule -module-name=resilient_protocol %S/../Inputs/resilient_protocol.swift
4+
// RUN: %target-swift-frontend -emit-module -emit-module-path=%t/non_resilient_protocol.swiftmodule -module-name=non_resilient_protocol %S/../Inputs/non_resilient_protocol.swift
45

56
// RUN: %target-swift-frontend -I %t -emit-ir %s -target %target-cpu-apple-macos14.0 | %FileCheck %s -DINT=i%target-ptrsize -check-prefix=CHECK-USAGE -check-prefix=CHECK-USAGE-BEFORE
67
// RUN: %target-swift-frontend -I %t -emit-ir %s -target %target-cpu-apple-macos15.0 | %FileCheck %s -DINT=i%target-ptrsize -check-prefix=CHECK-USAGE -check-prefix=CHECK-USAGE-AFTER
78

89
// REQUIRES: OS=macosx
910

1011
import resilient_protocol
12+
import non_resilient_protocol
1113

1214
func acceptResilientSendableBase<T: ResilientSendableBase>(_: T.Type) { }
1315

@@ -20,3 +22,12 @@ func passResilientSendableBase() {
2022
// CHECK-USAGE-AFTER-NEXT: call swiftcc void @"$s28protocol_resilience_sendable27acceptResilientSendableBaseyyxm010resilient_A00efG0RzlF"(ptr [[METATYPE]], ptr [[METATYPE]], ptr @"$s18resilient_protocol27ConformsToResilientSendableVAA0eF4BaseAAWP")
2123
acceptResilientSendableBase(ConformsToResilientSendable.self)
2224
}
25+
26+
func acceptNonResilientSendableBase<T: NonResilientSendableBase>(_: T.Type) { }
27+
28+
// CHECK-USAGE: define{{.*}}swiftcc void @"$s28protocol_resilience_sendable28passNonResilientSendableBaseyyF"()
29+
func passNonResilientSendableBase() {
30+
// CHECK-USAGE-NOT: ret
31+
// CHECK-USAGE: call swiftcc void @"$s28protocol_resilience_sendable30acceptNonResilientSendableBaseyyxm014non_resilient_A00efgH0RzlF"(ptr @"$s22non_resilient_protocol30ConformsToNonResilientSendableVN", ptr @"$s22non_resilient_protocol30ConformsToNonResilientSendableVN", ptr @"$s22non_resilient_protocol30ConformsToNonResilientSendableVAA0fgH4BaseAAWP")
32+
acceptNonResilientSendableBase(ConformsToNonResilientSendable.self)
33+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
public protocol NonResilientSendableBase: Sendable {
2+
func f()
3+
}
4+
5+
public protocol NonResilientSendable: NonResilientSendableBase {
6+
func g()
7+
}
8+
9+
public struct ConformsToNonResilientSendable: NonResilientSendable {
10+
public func f() { }
11+
public func g() { }
12+
}

0 commit comments

Comments
 (0)