@@ -2543,7 +2543,8 @@ namespace {
25432543 // / Determine whether code in the given use context might execute
25442544 // / concurrently with code in the definition context.
25452545 bool mayExecuteConcurrentlyWith (
2546- const DeclContext *useContext, const DeclContext *defContext);
2546+ const DeclContext *useContext, const DeclContext *defContext,
2547+ bool includeSending = false );
25472548
25482549 // / If the subexpression is a reference to a mutable local variable from a
25492550 // / different context, record its parent. We'll query this as part of
@@ -3051,12 +3052,9 @@ namespace {
30513052 }
30523053 }
30533054
3054- // FIXME: When passing to a sending parameter, should this be handled
3055- // by region isolation? Or should it always be handled by region
3056- // isolation?
30573055 if (mayExecuteConcurrentlyWith (
3058- localFunc.getAsDeclContext (), getDeclContext ()) ||
3059- (explicitClosure && explicitClosure-> isPassedToSendingParameter () )) {
3056+ localFunc.getAsDeclContext (), getDeclContext (),
3057+ /* includeSending */ true )) {
30603058 auto innermostGenericDC = localFunc.getAsDeclContext ();
30613059 while (innermostGenericDC && !innermostGenericDC->isGenericContext ())
30623060 innermostGenericDC = innermostGenericDC->getParent ();
@@ -4816,13 +4814,12 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
48164814}
48174815
48184816bool ActorIsolationChecker::mayExecuteConcurrentlyWith (
4819- const DeclContext *useContext, const DeclContext *defContext) {
4817+ const DeclContext *useContext, const DeclContext *defContext,
4818+ bool includeSending) {
48204819 // Fast path for when the use and definition contexts are the same.
48214820 if (useContext == defContext)
48224821 return false ;
48234822
4824- bool isolatedStateMayEscape = false ;
4825-
48264823 auto useIsolation = getActorIsolationOfContext (
48274824 const_cast <DeclContext *>(useContext), getClosureActorIsolation);
48284825 if (useIsolation.isActorIsolated ()) {
@@ -4840,16 +4837,6 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
48404837 if (ctx.LangOpts .hasFeature (Feature::GlobalActorIsolatedTypesUsability) &&
48414838 regionIsolationEnabled && useIsolation.isGlobalActor ())
48424839 return false ;
4843-
4844- // If the local function is not Sendable, its isolation differs
4845- // from that of the context, and both contexts are actor isolated,
4846- // then capturing non-Sendable values allows the closure to stash
4847- // those values into actor-isolated state. The original context
4848- // may also stash those values into isolated state, enabling concurrent
4849- // access later on.
4850- isolatedStateMayEscape =
4851- (!regionIsolationEnabled &&
4852- useIsolation.isActorIsolated () && defIsolation.isActorIsolated ());
48534840 }
48544841
48554842 // Walk the context chain from the use to the definition.
@@ -4859,18 +4846,17 @@ bool ActorIsolationChecker::mayExecuteConcurrentlyWith(
48594846 if (closure->isSendable ())
48604847 return true ;
48614848
4862- if (isolatedStateMayEscape)
4863- return true ;
4849+ if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure)) {
4850+ if (includeSending && explicitClosure->isPassedToSendingParameter ())
4851+ return true ;
4852+ }
48644853 }
48654854
48664855 if (auto func = dyn_cast<FuncDecl>(useContext)) {
48674856 if (func->isLocalCapture ()) {
48684857 // If the function is @Sendable... it can be run concurrently.
48694858 if (func->isSendable ())
48704859 return true ;
4871-
4872- if (isolatedStateMayEscape)
4873- return true ;
48744860 }
48754861 }
48764862
0 commit comments