Skip to content

Commit 7c45c7d

Browse files
committed
[Concurrency] Check sendability of the original argument expressions in a call
When checking for the sendability in a call, use the sendability of the original argument expressions rather than the parameter type, looking through any implicit conversions that might remove `Sendable`. Fixes rdar://110763694 / FB12343467.
1 parent 6d58bce commit 7c45c7d

File tree

3 files changed

+58
-10
lines changed

3 files changed

+58
-10
lines changed

lib/Sema/TypeCheckConcurrency.cpp

+36-2
Original file line numberDiff line numberDiff line change
@@ -2674,6 +2674,33 @@ namespace {
26742674
return result;
26752675
}
26762676

2677+
/// Find the original type of a value, looking through various implicit
2678+
/// conversions.
2679+
static Type findOriginalValueType(Expr *expr) {
2680+
do {
2681+
expr = expr->getSemanticsProvidingExpr();
2682+
2683+
if (auto inout = dyn_cast<InOutExpr>(expr)) {
2684+
expr = inout->getSubExpr();
2685+
continue;
2686+
}
2687+
2688+
if (auto ice = dyn_cast<ImplicitConversionExpr>(expr)) {
2689+
expr = ice->getSubExpr();
2690+
continue;
2691+
}
2692+
2693+
if (auto open = dyn_cast<OpenExistentialExpr>(expr)) {
2694+
expr = open->getSubExpr();
2695+
continue;
2696+
}
2697+
2698+
break;
2699+
} while (true);
2700+
2701+
return expr->getType()->getRValueType();
2702+
}
2703+
26772704
/// Check actor isolation for a particular application.
26782705
bool checkApply(ApplyExpr *apply) {
26792706
auto fnExprType = getType(apply->getFn());
@@ -2857,18 +2884,25 @@ namespace {
28572884

28582885
// Dig out the location of the argument.
28592886
SourceLoc argLoc = apply->getLoc();
2887+
Type argType;
28602888
if (auto argList = apply->getArgs()) {
28612889
auto arg = argList->get(paramIdx);
28622890
if (arg.getStartLoc().isValid())
28632891
argLoc = arg.getStartLoc();
2892+
2893+
// Determine the type of the argument, ignoring any implicit
2894+
// conversions that could have stripped sendability.
2895+
if (Expr *argExpr = arg.getExpr()) {
2896+
argType = findOriginalValueType(argExpr);
2897+
}
28642898
}
28652899

28662900
bool isExiting = !unsatisfiedIsolation->isActorIsolated();
28672901
ActorIsolation diagnoseIsolation = isExiting ? getContextIsolation()
28682902
: *unsatisfiedIsolation;
28692903
if (diagnoseNonSendableTypes(
2870-
param.getParameterType(), getDeclContext(), argLoc,
2871-
diag::non_sendable_call_argument,
2904+
argType ? argType : param.getParameterType(), getDeclContext(),
2905+
argLoc, diag::non_sendable_call_argument,
28722906
isExiting, diagnoseIsolation))
28732907
return true;
28742908
}

test/Concurrency/actor_call_implicitly_async.swift

+8-8
Original file line numberDiff line numberDiff line change
@@ -289,29 +289,29 @@ func blender(_ peeler : () -> Void) {
289289

290290

291291
await wisk({})
292-
// expected-warning@-1{{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
292+
// expected-warning@-1{{passing argument of non-sendable type '() -> ()' into global actor 'BananaActor'-isolated context may introduce data races}}
293+
// expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}}
293294
await wisk(1)
294-
// expected-warning@-1{{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
295295
await (peelBanana)()
296296
await (((((peelBanana)))))()
297297
await (((wisk)))((wisk)((wisk)(1)))
298-
// expected-warning@-1 3{{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
299298

300299
blender((peelBanana))
301300
// expected-warning@-1 2{{converting function value of type '@BananaActor () -> ()' to '() -> Void' loses global actor 'BananaActor'}}
302301

303302
await wisk(peelBanana)
304-
// expected-warning@-1{{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
303+
// expected-warning@-1{{passing argument of non-sendable type '() -> ()' into global actor 'BananaActor'-isolated context may introduce data races}}
304+
// expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}}
305305

306306
await wisk(wisk)
307-
// expected-warning@-1{{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
307+
// expected-warning@-1{{passing argument of non-sendable type '(Any) -> ()' into global actor 'BananaActor'-isolated context may introduce data races}}
308+
// expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}}
308309
await (((wisk)))(((wisk)))
309-
// expected-warning@-1{{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
310+
// expected-warning@-1{{passing argument of non-sendable type '(Any) -> ()' into global actor 'BananaActor'-isolated context may introduce data races}}
311+
// expected-note@-2{{a function type must be marked '@Sendable' to conform to 'Sendable'}}
310312

311-
// expected-warning@+1 {{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
312313
await {wisk}()(1)
313314

314-
// expected-warning@+1 {{passing argument of non-sendable type 'Any' into global actor 'BananaActor'-isolated context may introduce data races}}
315315
await (true ? wisk : {n in return})(1)
316316
}
317317

test/Concurrency/sendable_checking.swift

+14
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,17 @@ class SubWUnsafeSubscript : SuperWUnsafeSubscript {
216216
}
217217
}
218218
}
219+
220+
221+
// Test implicit conversions getting in the way
222+
@available(SwiftStdlib 5.1, *)
223+
extension MyActor {
224+
func f(_: Any) { }
225+
func g(_: () -> Void) { }
226+
}
227+
228+
@available(SwiftStdlib 5.1, *)
229+
func testConversionsAndSendable(a: MyActor, s: any Sendable, f: @Sendable () -> Void) async {
230+
await a.f(s)
231+
await a.g(f)
232+
}

0 commit comments

Comments
 (0)