Skip to content

Commit 80dfe07

Browse files
committed
Use "resilient conformance" logic for deciding protocol dependencies involving Sendable
When compiling with library evolution and a pre-Swift 6.0 deployment target, a mismatch between the notion of resilience used for determining whether a protocol that inherits Sendable might need to be treated as "dependent" differed from how other parts of IR generation decided whether to conformance should be considered as resilient. The difference came when both the protocol and its conforming type are in the same module as the user. Switch over to the "is this conformance resilient?" query that takes into account such conformances. Fixes rdar://136586922.
1 parent c1245b0 commit 80dfe07

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

lib/IRGen/GenProto.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -950,8 +950,13 @@ namespace {
950950

951951
/// Return true if the witness table requires runtime instantiation to
952952
/// handle resiliently-added requirements with default implementations.
953+
///
954+
/// If ignoreGenericity is true, skip the optimization for non-generic
955+
/// conformances are considered non-resilient.
953956
bool IRGenModule::isResilientConformance(
954-
const NormalProtocolConformance *conformance) {
957+
const NormalProtocolConformance *conformance,
958+
bool ignoreGenericity
959+
) {
955960
// If the protocol is not resilient, the conformance is not resilient
956961
// either.
957962
bool shouldTreatProtocolNonResilient =
@@ -983,16 +988,18 @@ bool IRGenModule::isResilientConformance(
983988
// This is an optimization -- a conformance of a non-generic type cannot
984989
// resiliently become dependent.
985990
if (!conformance->getDeclContext()->isGenericContext() &&
986-
conformanceModule == conformance->getProtocol()->getParentModule())
991+
conformanceModule == conformance->getProtocol()->getParentModule() &&
992+
!ignoreGenericity)
987993
return false;
988994

989995
// We have a resilient conformance.
990996
return true;
991997
}
992998

993-
bool IRGenModule::isResilientConformance(const RootProtocolConformance *root) {
999+
bool IRGenModule::isResilientConformance(const RootProtocolConformance *root,
1000+
bool ignoreGenericity) {
9941001
if (auto normal = dyn_cast<NormalProtocolConformance>(root))
995-
return isResilientConformance(normal);
1002+
return isResilientConformance(normal, ignoreGenericity);
9961003
// Self-conformances never require this.
9971004
return false;
9981005
}
@@ -1174,7 +1181,9 @@ bool IRGenModule::isDependentConformance(
11741181
const RootProtocolConformance *conformance) {
11751182
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> visited;
11761183
return ::isDependentConformance(
1177-
*this, conformance, conformance->getProtocol()->isResilient(), visited);
1184+
*this, conformance,
1185+
isResilientConformance(conformance, /*ignoreGenericity=*/true),
1186+
visited);
11781187
}
11791188

11801189
static llvm::Value *

lib/IRGen/IRGenModule.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1114,8 +1114,10 @@ class IRGenModule {
11141114

11151115
TypeExpansionContext getMaximalTypeExpansionContext() const;
11161116

1117-
bool isResilientConformance(const NormalProtocolConformance *conformance);
1118-
bool isResilientConformance(const RootProtocolConformance *root);
1117+
bool isResilientConformance(const NormalProtocolConformance *conformance,
1118+
bool ignoreGenericity = false);
1119+
bool isResilientConformance(const RootProtocolConformance *root,
1120+
bool ignoreGenericity = false);
11191121
bool isDependentConformance(const RootProtocolConformance *conformance);
11201122

11211123
Alignment getCappedAlignment(Alignment alignment);

test/IRGen/protocol_resilience_sendable.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,37 @@
66
// 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
77
// 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
88

9+
// RUN: %target-swift-frontend -I %t -emit-ir %s -target %target-cpu-apple-macos14.0 -enable-library-evolution | %FileCheck %s -DINT=i%target-ptrsize -check-prefix=CHECK-USAGE -check-prefix=CHECK-USAGE-BEFORE
10+
// RUN: %target-swift-frontend -I %t -emit-ir %s -target %target-cpu-apple-macos15.0 -enable-library-evolution | %FileCheck %s -DINT=i%target-ptrsize -check-prefix=CHECK-USAGE -check-prefix=CHECK-USAGE-AFTER
11+
912
// REQUIRES: OS=macosx
1013

1114
import resilient_protocol
1215
import non_resilient_protocol
1316

17+
// CHECK-USAGE: @"$s28protocol_resilience_sendable9LocalTypeVAA0D11SubProtocolAAWP" = hidden constant [3 x ptr] [
18+
// CHECK-USAGE-SAME: ptr @"$s28protocol_resilience_sendable9LocalTypeVAA0D11SubProtocolAAMc",
19+
// CHECK-USAGE-SAME: ptr @"$s28protocol_resilience_sendable9LocalTypeVAA0D8ProtocolAAWP",
20+
// CHECK-USAGE-SAME: ptr @"$s28protocol_resilience_sendable9LocalTypeVAA0D11SubProtocolA2aDP9subMethodyyFTW"
21+
public protocol LocalProtocol: Sendable {
22+
func method()
23+
}
24+
25+
protocol LocalSubProtocol: Sendable, LocalProtocol {
26+
func subMethod()
27+
}
28+
29+
struct LocalType: Sendable, LocalSubProtocol {
30+
func method() { }
31+
func subMethod() { }
32+
}
33+
34+
func acceptLocalProtocol<T: LocalProtocol>(_: T.Type) { }
35+
func testLocalType() {
36+
acceptLocalProtocol(LocalType.self)
37+
}
38+
39+
1440
func acceptResilientSendableBase<T: ResilientSendableBase>(_: T.Type) { }
1541

1642
// CHECK-USAGE: define{{.*}}swiftcc void @"$s28protocol_resilience_sendable25passResilientSendableBaseyyF"()

0 commit comments

Comments
 (0)