|
58 | 58 | using namespace swift;
|
59 | 59 | using namespace constraints;
|
60 | 60 |
|
| 61 | +static bool isClosureLiteralExpr(Expr *expr) { |
| 62 | + expr = expr->getSemanticsProvidingExpr(); |
| 63 | + return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr)); |
| 64 | +} |
| 65 | + |
61 | 66 | bool Solution::hasFixedType(TypeVariableType *typeVar) const {
|
62 | 67 | auto knownBinding = typeBindings.find(typeVar);
|
63 | 68 | return knownBinding != typeBindings.end();
|
@@ -5963,24 +5968,29 @@ static bool hasCurriedSelf(ConstraintSystem &cs, ConcreteDeclRef callee,
|
5963 | 5968 | /// Apply the contextually Sendable flag to the given expression,
|
5964 | 5969 | static void applyContextualClosureFlags(Expr *expr, bool implicitSelfCapture,
|
5965 | 5970 | bool inheritActorContext,
|
5966 |
| - bool isPassedToSendingParameter) { |
| 5971 | + bool isPassedToSendingParameter, |
| 5972 | + bool requiresDynamicIsolationChecking) { |
5967 | 5973 | if (auto closure = dyn_cast<ClosureExpr>(expr)) {
|
5968 | 5974 | closure->setAllowsImplicitSelfCapture(implicitSelfCapture);
|
5969 | 5975 | closure->setInheritsActorContext(inheritActorContext);
|
5970 | 5976 | closure->setIsPassedToSendingParameter(isPassedToSendingParameter);
|
| 5977 | + closure->setRequiresDynamicIsolationChecking( |
| 5978 | + requiresDynamicIsolationChecking); |
5971 | 5979 | return;
|
5972 | 5980 | }
|
5973 | 5981 |
|
5974 | 5982 | if (auto captureList = dyn_cast<CaptureListExpr>(expr)) {
|
5975 | 5983 | applyContextualClosureFlags(captureList->getClosureBody(),
|
5976 | 5984 | implicitSelfCapture, inheritActorContext,
|
5977 |
| - isPassedToSendingParameter); |
| 5985 | + isPassedToSendingParameter, |
| 5986 | + requiresDynamicIsolationChecking); |
5978 | 5987 | }
|
5979 | 5988 |
|
5980 | 5989 | if (auto identity = dyn_cast<IdentityExpr>(expr)) {
|
5981 | 5990 | applyContextualClosureFlags(identity->getSubExpr(), implicitSelfCapture,
|
5982 | 5991 | inheritActorContext,
|
5983 |
| - isPassedToSendingParameter); |
| 5992 | + isPassedToSendingParameter, |
| 5993 | + requiresDynamicIsolationChecking); |
5984 | 5994 | }
|
5985 | 5995 | }
|
5986 | 5996 |
|
@@ -6084,10 +6094,48 @@ ArgumentList *ExprRewriter::coerceCallArguments(
|
6084 | 6094 | return placeholder;
|
6085 | 6095 | };
|
6086 | 6096 |
|
| 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 = [¶mInfo, |
| 6118 | + &closuresRequireDynamicIsolationChecking]( |
| 6119 | + unsigned paramIdx, Expr *argument) { |
| 6120 | + if (!isClosureLiteralExpr(argument)) |
| 6121 | + return; |
| 6122 | + |
| 6123 | + bool isImplicitSelfCapture = paramInfo.isImplicitSelfCapture(paramIdx); |
| 6124 | + bool inheritsActorContext = paramInfo.inheritsActorContext(paramIdx); |
| 6125 | + bool isPassedToSendingParameter = paramInfo.isSendingParameter(paramIdx); |
| 6126 | + |
| 6127 | + applyContextualClosureFlags(argument, isImplicitSelfCapture, |
| 6128 | + inheritsActorContext, |
| 6129 | + isPassedToSendingParameter, |
| 6130 | + closuresRequireDynamicIsolationChecking); |
| 6131 | + }; |
| 6132 | + |
6087 | 6133 | // Quickly test if any further fix-ups for the argument types are necessary.
|
6088 | 6134 | auto matches = args->matches(params, [&](Expr *E) { return cs.getType(E); });
|
6089 |
| - if (matches && !shouldInjectWrappedValuePlaceholder && |
6090 |
| - !paramInfo.anyContextualInfo()) { |
| 6135 | + if (matches && !shouldInjectWrappedValuePlaceholder) { |
| 6136 | + for (unsigned paramIdx : indices(params)) { |
| 6137 | + applyFlagsToArgument(paramIdx, args->getExpr(paramIdx)); |
| 6138 | + } |
6091 | 6139 | return args;
|
6092 | 6140 | }
|
6093 | 6141 |
|
@@ -6204,15 +6252,10 @@ ArgumentList *ExprRewriter::coerceCallArguments(
|
6204 | 6252 | // for things like trailing closures and args to property wrapper params.
|
6205 | 6253 | arg.setLabel(param.getLabel());
|
6206 | 6254 |
|
6207 |
| - // Determine whether the closure argument should be treated as having |
6208 |
| - // implicit self capture or inheriting actor context. |
6209 |
| - bool isImplicitSelfCapture = paramInfo.isImplicitSelfCapture(paramIdx); |
6210 |
| - bool inheritsActorContext = paramInfo.inheritsActorContext(paramIdx); |
6211 |
| - bool isPassedToSendingParameter = paramInfo.isSendingParameter(paramIdx); |
6212 |
| - |
6213 |
| - applyContextualClosureFlags(argExpr, isImplicitSelfCapture, |
6214 |
| - inheritsActorContext, |
6215 |
| - isPassedToSendingParameter); |
| 6255 | + // Determine whether the argument should be marked as having |
| 6256 | + // implicit self capture, inheriting actor context, is passed to a |
| 6257 | + // `sending` parameter etc. |
| 6258 | + applyFlagsToArgument(paramIdx, argExpr); |
6216 | 6259 |
|
6217 | 6260 | // If the types exactly match, this is easy.
|
6218 | 6261 | auto paramType = param.getOldType();
|
@@ -6356,11 +6399,6 @@ ArgumentList *ExprRewriter::coerceCallArguments(
|
6356 | 6399 | return ArgumentList::createTypeChecked(ctx, args, newArgs);
|
6357 | 6400 | }
|
6358 | 6401 |
|
6359 |
| -static bool isClosureLiteralExpr(Expr *expr) { |
6360 |
| - expr = expr->getSemanticsProvidingExpr(); |
6361 |
| - return (isa<CaptureListExpr>(expr) || isa<ClosureExpr>(expr)); |
6362 |
| -} |
6363 |
| - |
6364 | 6402 | /// Whether the given expression is a closure that should inherit
|
6365 | 6403 | /// the actor context from where it was formed.
|
6366 | 6404 | static bool closureInheritsActorContext(Expr *expr) {
|
|
0 commit comments