Skip to content

Commit 21b2f09

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 4e3f665 commit 21b2f09

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
@@ -959,8 +959,13 @@ namespace {
959959

960960
/// Return true if the witness table requires runtime instantiation to
961961
/// handle resiliently-added requirements with default implementations.
962+
///
963+
/// If ignoreGenericity is true, skip the optimization for non-generic
964+
/// conformances are considered non-resilient.
962965
bool IRGenModule::isResilientConformance(
963-
const NormalProtocolConformance *conformance) {
966+
const NormalProtocolConformance *conformance,
967+
bool ignoreGenericity
968+
) {
964969
// If the protocol is not resilient, the conformance is not resilient
965970
// either.
966971
bool shouldTreatProtocolNonResilient =
@@ -992,16 +997,18 @@ bool IRGenModule::isResilientConformance(
992997
// This is an optimization -- a conformance of a non-generic type cannot
993998
// resiliently become dependent.
994999
if (!conformance->getDeclContext()->isGenericContext() &&
995-
conformanceModule == conformance->getProtocol()->getParentModule())
1000+
conformanceModule == conformance->getProtocol()->getParentModule() &&
1001+
!ignoreGenericity)
9961002
return false;
9971003

9981004
// We have a resilient conformance.
9991005
return true;
10001006
}
10011007

1002-
bool IRGenModule::isResilientConformance(const RootProtocolConformance *root) {
1008+
bool IRGenModule::isResilientConformance(const RootProtocolConformance *root,
1009+
bool ignoreGenericity) {
10031010
if (auto normal = dyn_cast<NormalProtocolConformance>(root))
1004-
return isResilientConformance(normal);
1011+
return isResilientConformance(normal, ignoreGenericity);
10051012
// Self-conformances never require this.
10061013
return false;
10071014
}
@@ -1185,7 +1192,9 @@ bool IRGenModule::isDependentConformance(
11851192
const RootProtocolConformance *conformance) {
11861193
llvm::SmallPtrSet<const NormalProtocolConformance *, 4> visited;
11871194
return ::isDependentConformance(
1188-
*this, conformance, conformance->getProtocol()->isResilient(), visited);
1195+
*this, conformance,
1196+
isResilientConformance(conformance, /*ignoreGenericity=*/true),
1197+
visited);
11891198
}
11901199

11911200
static llvm::Value *

lib/IRGen/IRGenModule.h

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

11201120
TypeExpansionContext getMaximalTypeExpansionContext() const;
11211121

1122-
bool isResilientConformance(const NormalProtocolConformance *conformance);
1123-
bool isResilientConformance(const RootProtocolConformance *root);
1122+
bool isResilientConformance(const NormalProtocolConformance *conformance,
1123+
bool ignoreGenericity = false);
1124+
bool isResilientConformance(const RootProtocolConformance *root,
1125+
bool ignoreGenericity = false);
11241126
bool isDependentConformance(const RootProtocolConformance *conformance);
11251127

11261128
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)