Skip to content

[concurrency] Ensure that we treat closures that are nonisolated(nonsending) via their ActorIsolation as nonisolated(nonsending). #81338

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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
3 changes: 3 additions & 0 deletions lib/SIL/IR/SILFunctionType.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2633,6 +2633,9 @@ static CanSILFunctionType getSILFunctionType(
} else if (decl->getAttrs().hasAttribute<ConcurrentAttr>()) {
actorIsolation = ActorIsolation::forNonisolated(false /*unsafe*/);
}
} else if (auto *closure = constant->getAbstractClosureExpr()) {
if (auto isolation = closure->getActorIsolation())
actorIsolation = isolation;
}

if (!actorIsolation) {
Expand Down
7 changes: 7 additions & 0 deletions lib/SILGen/SILGen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -765,6 +765,13 @@ static ActorIsolation getActorIsolationForFunction(SILFunction &fn) {
return ActorIsolation::forNonisolated(false);
}

// If we have a closure expr, check if our type is
// nonisolated(nonsending). In that case, we use that instead.
if (auto *closureExpr = constant.getAbstractClosureExpr()) {
if (auto actorIsolation = closureExpr->getActorIsolation())
return actorIsolation;
}

// If we have actor isolation for our constant, put the isolation onto the
// function. If the isolation is unspecified, we do not return it.
if (auto isolation =
Expand Down
26 changes: 25 additions & 1 deletion lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1346,8 +1346,32 @@ namespace {
new (ctx) AutoClosureExpr(/*set body later*/ nullptr, thunkTy, dc);
thunk->setParameterList(thunkParamList);
thunk->setThunkKind(AutoClosureExpr::Kind::SingleCurryThunk);

// TODO: We should do this in the ActorIsolation checker but for now it is
// too risky. This is a narrow fix for 6.2.
//
// The problem that this is working around is given an autoclosure that
// returns an autoclosure that partially applies over an instance method,
// we do not visit the inner autoclosure in the ActorIsolation checker
// meaning that we do not properly call setActorIsolation on the
// AbstractClosureExpr that we produce here.
switch (thunkTy->getIsolation().getKind()) {
case FunctionTypeIsolation::Kind::NonIsolated:
case FunctionTypeIsolation::Kind::Parameter:
case FunctionTypeIsolation::Kind::Erased:
break;
case FunctionTypeIsolation::Kind::GlobalActor:
thunk->setActorIsolation(ActorIsolation::forGlobalActor(
thunkTy->getIsolation().getGlobalActorType()));
break;
case FunctionTypeIsolation::Kind::NonIsolatedCaller:
thunk->setActorIsolation(
ActorIsolation::forCallerIsolationInheriting());
break;
}

cs.cacheType(thunk);

// If the `self` type is existential, it must be opened.
OpaqueValueExpr *baseOpened = nullptr;
Expr *origBaseExpr = baseExpr;
Expand Down
10 changes: 10 additions & 0 deletions test/Inputs/clang-importer-sdk/usr/include/ObjCConcurrency.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,16 @@ typedef void (^NonsendableCompletionHandler)(NSString * _Nullable, NSString * _N
__attribute__((swift_async_error(zero_argument, 3)));
- (void)getIceCreamFlavorWithCompletionHandler:
(void (^)(Flavor flavor, NSError *__nullable error))completionHandler;

@property(class, strong, readonly) SlowServer *standardServer;
- (void)getValueWithKey:(NSString *)valueIdentifier
completion:(void (^)(NSString *__nullable value,
NSError *__nullable error))completionHandler;
- (void)getMainActorValueWithKey:(NSString *)valueIdentifier
completion:
(void (^)(NSString *__nullable value,
NSError *__nullable error))completionHandler
MAIN_ACTOR;
@end

@protocol RefrigeratorDelegate<NSObject>
Expand Down
Loading