Skip to content

Commit 414fbe4

Browse files
committed
[Sema]Skip Sendable conformance check when sending are added to parameters or return types of an actor-isolated function
1 parent 5c24df2 commit 414fbe4

File tree

2 files changed

+132
-46
lines changed

2 files changed

+132
-46
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,34 +1160,59 @@ bool swift::diagnoseNonSendableTypesInReference(
11601160
return true;
11611161
}
11621162

1163-
// For functions, check the parameter and result types.
1163+
// For functions or subscripts, check the parameter and result types.
11641164
SubstitutionMap subs = declRef.getSubstitutions();
1165-
if (auto function = dyn_cast<AbstractFunctionDecl>(declRef.getDecl())) {
1165+
auto decl = declRef.getDecl();
1166+
if (isa<AbstractFunctionDecl>(decl) || isa<SubscriptDecl>(decl)) {
11661167
if (funcCheckOptions.contains(FunctionCheckKind::Params)) {
11671168
// only check params if funcCheckKind specifies so
1168-
for (auto param : *function->getParameters()) {
1169+
ParameterList *paramList = nullptr;
1170+
if (auto function = dyn_cast<AbstractFunctionDecl>(decl)) {
1171+
paramList = function->getParameters();
1172+
} else if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
1173+
paramList = subscript->getIndices();
1174+
}
1175+
1176+
// Check params of this function or subscript override for sendability
1177+
for (auto param : *paramList) {
11691178
Type paramType = param->getInterfaceType().subst(subs);
1179+
if (param->isSending() && !paramType->hasError()) {
1180+
continue;
1181+
}
11701182
if (diagnoseNonSendableTypes(
1171-
paramType, fromDC, derivedConformanceType,
1172-
refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc,
1173-
getSendableParamDiag(refKind),
1174-
function, getActorIsolation()))
1183+
paramType, fromDC, derivedConformanceType,
1184+
refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc,
1185+
getSendableParamDiag(refKind),
1186+
decl, getActorIsolation()))
11751187
return true;
11761188
}
11771189
}
11781190

1179-
// Check the result type of a function.
1180-
if (auto func = dyn_cast<FuncDecl>(function)) {
1181-
if (funcCheckOptions.contains(FunctionCheckKind::Results)) {
1182-
// only check results if funcCheckKind specifies so
1183-
Type resultType = func->getResultInterfaceType().subst(subs);
1184-
if (diagnoseNonSendableTypes(
1185-
resultType, fromDC, derivedConformanceType,
1186-
refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc,
1187-
getSendableResultDiag(refKind),
1188-
func, getActorIsolation()))
1189-
return true;
1191+
// Check the result type of a function or subscript.
1192+
if (funcCheckOptions.contains(FunctionCheckKind::Results)) {
1193+
Type resultType;
1194+
bool hasSendingResult;
1195+
if (auto func = dyn_cast<FuncDecl>(decl)) {
1196+
resultType = func->getResultInterfaceType().subst(subs);
1197+
hasSendingResult = func->hasSendingResult();
1198+
decl = func;
1199+
} else if (auto subscript = dyn_cast<SubscriptDecl>(decl)) {
1200+
resultType = subscript->getElementInterfaceType().subst(subs);
1201+
hasSendingResult = isa<SendingTypeRepr>(subscript->getResultTypeRepr());
1202+
}
1203+
if (!resultType) {
1204+
return false;
1205+
}
1206+
auto diag = getSendableResultDiag(refKind);
1207+
if (diag.ID == diag::non_sendable_result_in_witness.ID &&
1208+
hasSendingResult && !resultType->hasError()) {
1209+
return false;
11901210
}
1211+
if (diagnoseNonSendableTypes(
1212+
resultType, fromDC, derivedConformanceType, refLoc,
1213+
diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc, diag, decl,
1214+
getActorIsolation()))
1215+
return true;
11911216
}
11921217

11931218
return false;
@@ -1205,34 +1230,6 @@ bool swift::diagnoseNonSendableTypesInReference(
12051230
return true;
12061231
}
12071232

1208-
if (auto subscript = dyn_cast<SubscriptDecl>(declRef.getDecl())) {
1209-
for (auto param : *subscript->getIndices()) {
1210-
if (funcCheckOptions.contains(FunctionCheckKind::Params)) {
1211-
// Check params of this subscript override for sendability
1212-
Type paramType = param->getInterfaceType().subst(subs);
1213-
if (diagnoseNonSendableTypes(
1214-
paramType, fromDC, derivedConformanceType,
1215-
refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc,
1216-
getSendableParamDiag(refKind),
1217-
subscript, getActorIsolation()))
1218-
return true;
1219-
}
1220-
}
1221-
1222-
if (funcCheckOptions.contains(FunctionCheckKind::Results)) {
1223-
// Check the element type of a subscript.
1224-
Type resultType = subscript->getElementInterfaceType().subst(subs);
1225-
if (diagnoseNonSendableTypes(
1226-
resultType, fromDC, derivedConformanceType,
1227-
refLoc, diagnoseLoc.isInvalid() ? refLoc : diagnoseLoc,
1228-
getSendableResultDiag(refKind),
1229-
subscript, getActorIsolation()))
1230-
return true;
1231-
}
1232-
1233-
return false;
1234-
}
1235-
12361233
return false;
12371234
}
12381235

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 6
2+
3+
// https://github.com/swiftlang/swift/issues/76710
4+
5+
class NonSendableKlass1 {}
6+
7+
protocol P1 {
8+
func bar(_ a: sending NonSendableKlass1) async -> sending NonSendableKlass1
9+
}
10+
11+
@MainActor
12+
class P1Class: P1 {
13+
func bar(_ a: sending NonSendableKlass1) async -> sending NonSendableKlass1 { a }
14+
}
15+
16+
class NonSendableKlass2 {}
17+
// expected-note@-1 2{{class 'NonSendableKlass2' does not conform to the 'Sendable' protocol}}
18+
19+
protocol P2 {
20+
func bar(_ a: NonSendableKlass2) async -> NonSendableKlass2
21+
}
22+
23+
@MainActor
24+
class P2Class: P2 {
25+
func bar(_ a: NonSendableKlass2) async -> NonSendableKlass2 { a }
26+
// expected-error@-1 {{non-sendable type 'NonSendableKlass2' cannot be returned from main actor-isolated implementation to caller of protocol requirement 'bar'}}
27+
// expected-error@-2 {{non-sendable parameter type 'NonSendableKlass2' cannot be sent from caller of protocol requirement 'bar' into main actor-isolated implementation}}
28+
}
29+
30+
class NonSendableKlass3 {}
31+
32+
protocol P3 {
33+
func bar(_ a: sending NonSendableKlass3) async -> sending NonSendableKlass3
34+
}
35+
36+
actor P3Actor: P3 {
37+
func bar(_ a: sending NonSendableKlass3) async -> sending NonSendableKlass3 { NonSendableKlass3() }
38+
}
39+
40+
class NonSendableKlass4 {}
41+
// expected-note@-1 2{{class 'NonSendableKlass4' does not conform to the 'Sendable' protocol}}
42+
43+
protocol P4 {
44+
func bar(_ a: NonSendableKlass4) async -> NonSendableKlass4
45+
}
46+
47+
actor P4Actor: P4 {
48+
func bar(_ a: NonSendableKlass4) async -> NonSendableKlass4 { NonSendableKlass4() }
49+
// expected-error@-1 {{non-sendable type 'NonSendableKlass4' cannot be returned from actor-isolated implementation to caller of protocol requirement 'bar'}}
50+
// expected-error@-2 {{non-sendable parameter type 'NonSendableKlass4' cannot be sent from caller of protocol requirement 'bar' into actor-isolated implementation}}
51+
}
52+
53+
class NonSendableKlass5 {}
54+
// expected-note@-1 {{class 'NonSendableKlass5' does not conform to the 'Sendable' protocol}}
55+
56+
57+
protocol P5 {
58+
func bar(_ a: sending NonSendableKlass5, _ b: NonSendableKlass5) async -> sending NonSendableKlass5
59+
}
60+
61+
@MainActor
62+
class P5Class: P5 {
63+
func bar(_ a: sending NonSendableKlass5, _ b: NonSendableKlass5) async -> sending NonSendableKlass5 { a }
64+
// expected-error@-1 {{non-sendable parameter type 'NonSendableKlass5' cannot be sent from caller of protocol requirement 'bar' into main actor-isolated implementation}}
65+
}
66+
67+
class NonSendableKlass6 {}
68+
69+
protocol P6 {
70+
func bar(_ a: sending NonSendableKlass6, _ b: sending NonSendableKlass6) async -> sending NonSendableKlass6
71+
}
72+
73+
@MainActor
74+
class P6Class: P6 {
75+
func bar(_ a: sending NonSendableKlass6, _ b: sending NonSendableKlass6) async -> sending NonSendableKlass6 { a }
76+
}
77+
78+
class NonSendableKlass7 {}
79+
80+
protocol P7 {
81+
subscript(_: sending NonSendableKlass7) -> sending NonSendableKlass7 { get async }
82+
}
83+
84+
@MainActor
85+
struct S: P7 {
86+
subscript(_: sending NonSendableKlass7) -> sending NonSendableKlass7 {
87+
get async { NonSendableKlass7() }
88+
}
89+
}

0 commit comments

Comments
 (0)