Skip to content

Commit 4b33db0

Browse files
authored
Merge pull request #85605 from xedin/tilde-sendable-cond-conformances
[Concurrency] Allow conditionally conforming to `Sendable` when confo…
2 parents 36a3c6e + d868e68 commit 4b33db0

File tree

3 files changed

+73
-8
lines changed

3 files changed

+73
-8
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7183,14 +7183,6 @@ static bool checkSendableInstanceStorage(
71837183
}
71847184
}
71857185

7186-
if (nominal->suppressesConformance(KnownProtocolKind::Sendable)) {
7187-
auto *conformanceDecl = dc->getAsDecl() ? dc->getAsDecl() : nominal;
7188-
if (!isImplicitSendableCheck(check)) {
7189-
conformanceDecl->diagnose(diag::non_sendable_type_suppressed);
7190-
}
7191-
return true;
7192-
}
7193-
71947186
// Stored properties of structs and classes must have
71957187
// Sendable-conforming types.
71967188
class Visitor: public StorageVisitor {
@@ -7465,6 +7457,25 @@ bool swift::checkSendableConformance(
74657457
// and not some (possibly constrained) extension.
74667458
if (wasImplied)
74677459
conformanceDC = nominal;
7460+
7461+
// Sendable supression allows conditional conformances only.
7462+
if (nominal->suppressesConformance(KnownProtocolKind::Sendable)) {
7463+
bool hasUnconditionalConformance = false;
7464+
if (auto *normalConf = dyn_cast<NormalProtocolConformance>(conformance)) {
7465+
hasUnconditionalConformance =
7466+
normalConf->getConditionalRequirements().empty();
7467+
}
7468+
7469+
if (hasUnconditionalConformance) {
7470+
if (!isImplicitSendableCheck(check)) {
7471+
auto *conformanceDecl =
7472+
conformanceDC->getAsDecl() ? conformanceDC->getAsDecl() : nominal;
7473+
conformanceDecl->diagnose(diag::non_sendable_type_suppressed);
7474+
}
7475+
return true;
7476+
}
7477+
}
7478+
74687479
return checkSendableInstanceStorage(nominal, conformanceDC, check);
74697480
}
74707481

test/ModuleInterface/tilde_sendable.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,18 @@ protocol P {
3333
public struct S: P, ~Sendable {
3434
public let x: Int
3535
}
36+
37+
// CHECK: #if compiler(>=5.3) && $TildeSendable
38+
// CHECK: public struct B<T> : ~Swift.Sendable {
39+
// CHECK: }
40+
// CHECK: #else
41+
// CHECK: public struct B<T> {
42+
// CHECK: }
43+
// CHECK: #endif
44+
public struct B<T>: ~Sendable {
45+
}
46+
47+
// CHECK: extension Library.B : Swift.Sendable where T : Swift.Sendable {
48+
// CHECK: }
49+
extension B: Sendable where T: Sendable {
50+
}

test/Sema/tilde_sendable.swift

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,42 @@ do {
5252
check(NonSendable()) // expected-warning {{type 'NonSendable' does not conform to the 'Sendable' protocol}}
5353
check(NoInference()) // Ok
5454
}
55+
56+
func takesSendable<T: Sendable>(_: T) {}
57+
58+
class MyValue {} // expected-note 2 {{class 'MyValue' does not conform to the 'Sendable' protocol}}
59+
60+
public struct D: ~Sendable {
61+
}
62+
63+
extension D: Sendable {} // expected-error {{cannot both conform to and suppress conformance to 'Sendable'}}
64+
65+
takesSendable(D())
66+
67+
public struct F<T>: ~Sendable {
68+
let x: T
69+
}
70+
71+
extension F: Sendable where T: Sendable { }
72+
73+
takesSendable(F(x: 42))
74+
75+
public struct G<T, U>: ~Sendable { // expected-note {{making generic parameter 'U' conform to the 'Sendable' protocol}}
76+
let t: T
77+
let u: U // expected-warning {{stored property 'u' of 'Sendable'-conforming generic struct 'G' has non-Sendable type 'U'}}
78+
}
79+
80+
extension G: Sendable where T: Sendable { }
81+
82+
takesSendable(G(t: "", u: 42))
83+
takesSendable(G(t: MyValue(), u: 0)) // expected-warning {{type 'MyValue' does not conform to the 'Sendable' protocol}}
84+
85+
public struct H<T, U>: ~Sendable {
86+
let t: T
87+
let u: U
88+
}
89+
90+
extension H: Sendable where T: Sendable, U: Sendable { }
91+
92+
takesSendable(H(t: "", u: 42))
93+
takesSendable(H(t: "", u: MyValue())) // expected-warning {{type 'MyValue' does not conform to the 'Sendable' protocol}}

0 commit comments

Comments
 (0)