Skip to content

Commit 44d83ae

Browse files
committed
[CSApply] Start marking closures that require dynamic isolation checking
If a closure is passed as an argument to a not-fully concurrency checked callee - require dynamic isolation checking. This information is going to be used by SILGen to inject expected executor precondition when necessary.
1 parent a4d9b3b commit 44d83ae

File tree

1 file changed

+41
-10
lines changed

1 file changed

+41
-10
lines changed

lib/Sema/CSApply.cpp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@
5858
using namespace swift;
5959
using namespace constraints;
6060

61+
static bool isClosureLiteralExpr(Expr *expr) {
62+
expr = expr->getSemanticsProvidingExpr();
63+
return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr));
64+
}
65+
6166
bool Solution::hasFixedType(TypeVariableType *typeVar) const {
6267
auto knownBinding = typeBindings.find(typeVar);
6368
return knownBinding != typeBindings.end();
@@ -5963,24 +5968,29 @@ static bool hasCurriedSelf(ConstraintSystem &cs, ConcreteDeclRef callee,
59635968
/// Apply the contextually Sendable flag to the given expression,
59645969
static void applyContextualClosureFlags(Expr *expr, bool implicitSelfCapture,
59655970
bool inheritActorContext,
5966-
bool isPassedToSendingParameter) {
5971+
bool isPassedToSendingParameter,
5972+
bool requiresDynamicIsolationChecking) {
59675973
if (auto closure = dyn_cast<ClosureExpr>(expr)) {
59685974
closure->setAllowsImplicitSelfCapture(implicitSelfCapture);
59695975
closure->setInheritsActorContext(inheritActorContext);
59705976
closure->setIsPassedToSendingParameter(isPassedToSendingParameter);
5977+
closure->setRequiresDynamicIsolationChecking(
5978+
requiresDynamicIsolationChecking);
59715979
return;
59725980
}
59735981

59745982
if (auto captureList = dyn_cast<CaptureListExpr>(expr)) {
59755983
applyContextualClosureFlags(captureList->getClosureBody(),
59765984
implicitSelfCapture, inheritActorContext,
5977-
isPassedToSendingParameter);
5985+
isPassedToSendingParameter,
5986+
requiresDynamicIsolationChecking);
59785987
}
59795988

59805989
if (auto identity = dyn_cast<IdentityExpr>(expr)) {
59815990
applyContextualClosureFlags(identity->getSubExpr(), implicitSelfCapture,
59825991
inheritActorContext,
5983-
isPassedToSendingParameter);
5992+
isPassedToSendingParameter,
5993+
requiresDynamicIsolationChecking);
59845994
}
59855995
}
59865996

@@ -6084,14 +6094,40 @@ ArgumentList *ExprRewriter::coerceCallArguments(
60846094
return placeholder;
60856095
};
60866096

6087-
auto applyFlagsToArgument = [&paramInfo](unsigned paramIdx, Expr *argument) {
6097+
bool closuresRequireDynamicIsolationChecking = [&]() {
6098+
auto *decl = callee.getDecl();
6099+
// If this is something like `{ @MainActor in ... }()`, let's consider
6100+
// callee as concurrency checked.
6101+
if (!decl)
6102+
return false;
6103+
6104+
if (auto declaredIn = decl->findImport(dc))
6105+
return !declaredIn->module.importedModule->isConcurrencyChecked();
6106+
6107+
// Both the caller and the allee are in the same module.
6108+
if (dc->getParentModule() == decl->getModuleContext()) {
6109+
return !dc->getASTContext().isSwiftVersionAtLeast(6);
6110+
}
6111+
6112+
// If we cannot figure out where the callee came from, let's conservatively
6113+
// assume that closure arguments require dynamic isolation checks.
6114+
return true;
6115+
}();
6116+
6117+
auto applyFlagsToArgument = [&paramInfo,
6118+
&closuresRequireDynamicIsolationChecking](
6119+
unsigned paramIdx, Expr *argument) {
6120+
if (!isClosureLiteralExpr(argument))
6121+
return;
6122+
60886123
bool isImplicitSelfCapture = paramInfo.isImplicitSelfCapture(paramIdx);
60896124
bool inheritsActorContext = paramInfo.inheritsActorContext(paramIdx);
60906125
bool isPassedToSendingParameter = paramInfo.isSendingParameter(paramIdx);
60916126

60926127
applyContextualClosureFlags(argument, isImplicitSelfCapture,
60936128
inheritsActorContext,
6094-
isPassedToSendingParameter);
6129+
isPassedToSendingParameter,
6130+
closuresRequireDynamicIsolationChecking);
60956131
};
60966132

60976133
// Quickly test if any further fix-ups for the argument types are necessary.
@@ -6363,11 +6399,6 @@ ArgumentList *ExprRewriter::coerceCallArguments(
63636399
return ArgumentList::createTypeChecked(ctx, args, newArgs);
63646400
}
63656401

6366-
static bool isClosureLiteralExpr(Expr *expr) {
6367-
expr = expr->getSemanticsProvidingExpr();
6368-
return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr));
6369-
}
6370-
63716402
/// Whether the given expression is a closure that should inherit
63726403
/// the actor context from where it was formed.
63736404
static bool closureInheritsActorContext(Expr *expr) {

0 commit comments

Comments
 (0)