Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 36 additions & 2 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2674,6 +2674,33 @@ namespace {
return result;
}

/// Find the original type of a value, looking through various implicit
/// conversions.
static Type findOriginalValueType(Expr *expr) {
do {
expr = expr->getSemanticsProvidingExpr();

if (auto inout = dyn_cast<InOutExpr>(expr)) {
expr = inout->getSubExpr();
continue;
}

if (auto ice = dyn_cast<ImplicitConversionExpr>(expr)) {
expr = ice->getSubExpr();
continue;
}

if (auto open = dyn_cast<OpenExistentialExpr>(expr)) {
expr = open->getSubExpr();
continue;
}

break;
} while (true);

return expr->getType()->getRValueType();
}

/// Check actor isolation for a particular application.
bool checkApply(ApplyExpr *apply) {
auto fnExprType = getType(apply->getFn());
Expand Down Expand Up @@ -2857,18 +2884,25 @@ namespace {

// Dig out the location of the argument.
SourceLoc argLoc = apply->getLoc();
Type argType;
if (auto argList = apply->getArgs()) {
auto arg = argList->get(paramIdx);
if (arg.getStartLoc().isValid())
argLoc = arg.getStartLoc();

// Determine the type of the argument, ignoring any implicit
// conversions that could have stripped sendability.
if (Expr *argExpr = arg.getExpr()) {
argType = findOriginalValueType(argExpr);
}
}

bool isExiting = !unsatisfiedIsolation->isActorIsolated();
ActorIsolation diagnoseIsolation = isExiting ? getContextIsolation()
: *unsatisfiedIsolation;
if (diagnoseNonSendableTypes(
param.getParameterType(), getDeclContext(), argLoc,
diag::non_sendable_call_argument,
argType ? argType : param.getParameterType(), getDeclContext(),
argLoc, diag::non_sendable_call_argument,
isExiting, diagnoseIsolation))
return true;
}
Expand Down
16 changes: 8 additions & 8 deletions test/Concurrency/actor_call_implicitly_async.swift
Original file line number Diff line number Diff line change
Expand Up @@ -289,29 +289,29 @@ func blender(_ peeler : () -> Void) {


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

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

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

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

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

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

Expand Down
14 changes: 14 additions & 0 deletions test/Concurrency/sendable_checking.swift
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,17 @@ class SubWUnsafeSubscript : SuperWUnsafeSubscript {
}
}
}


// Test implicit conversions getting in the way
@available(SwiftStdlib 5.1, *)
extension MyActor {
func f(_: Any) { }
func g(_: () -> Void) { }
}

@available(SwiftStdlib 5.1, *)
func testConversionsAndSendable(a: MyActor, s: any Sendable, f: @Sendable () -> Void) async {
await a.f(s)
await a.g(f)
}