|
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