Skip to content

Commit cf535d8

Browse files
authored
Merge pull request #85603 from xedin/rdar-163792371
[Concurrency] Allow transferring `nonisolated(nonsending)` to isolati…
2 parents 7d4f45b + 2335293 commit cf535d8

File tree

3 files changed

+40
-11
lines changed

3 files changed

+40
-11
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5013,6 +5013,10 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
50135013
auto normalIsolation = computeClosureIsolationFromParent(
50145014
closure, parentIsolation, checkIsolatedCapture);
50155015

5016+
bool isIsolationBoundary =
5017+
isIsolationInferenceBoundaryClosure(closure,
5018+
/*canInheritActorContext=*/true);
5019+
50165020
// The solver has to be conservative and produce a conversion to
50175021
// `nonisolated(nonsending)` because at solution application time
50185022
// we don't yet know whether there are any captures which would
@@ -5023,7 +5027,7 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
50235027
// isolated parameters. If our closure is nonisolated and we have a
50245028
// conversion to nonisolated(nonsending), then we should respect that.
50255029
if (auto *explicitClosure = dyn_cast<ClosureExpr>(closure);
5026-
!normalIsolation.isGlobalActor()) {
5030+
isIsolationBoundary || !normalIsolation.isGlobalActor()) {
50275031
if (auto *fce =
50285032
dyn_cast_or_null<FunctionConversionExpr>(Parent.getAsExpr())) {
50295033
auto expectedIsolation =
@@ -5042,8 +5046,7 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
50425046
// NOTE: Since we already checked for global actor isolated things, we
50435047
// know that all Sendable closures must be nonisolated. That is why it is
50445048
// safe to rely on this path to handle Sendable closures.
5045-
if (isIsolationInferenceBoundaryClosure(closure,
5046-
/*canInheritActorContext=*/true))
5049+
if (isIsolationBoundary)
50475050
return ActorIsolation::forNonisolated(/*unsafe=*/false);
50485051

50495052
return normalIsolation;

test/Concurrency/attr_execution/conversions_silgen.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -659,3 +659,29 @@ func testSendableToSendableConversionWithNonisilatedNonsending() {
659659
nonisolated(nonsending) @escaping (String) async throws -> String
660660
) async throws -> Void = test
661661
}
662+
663+
func testNonisolatedNonsendingClosureInGlobalActorContext() {
664+
class NonSendable {
665+
var state = ""
666+
}
667+
668+
struct S {
669+
static func compute(closure: nonisolated(nonsending) @Sendable @escaping (sending NonSendable) async -> Void) async {}
670+
}
671+
672+
// CHECK-LABEL: sil private [ossa] @$s21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF0D0L_yyYaF : $@convention(thin) @async () -> ()
673+
// CHECK: [[CLOSURE:%.*]] = function_ref @$s21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF0D0L_yyYaFyAaByyF11NonSendableL_CYuYaYbYCcfU_ : $@convention(thin) @Sendable @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @sil_sending @guaranteed NonSendable) -> ()
674+
// CHECK: [[THICK_CLOSURE:%.*]] = thin_to_thick_function [[CLOSURE]] to $@Sendable @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @sil_sending @guaranteed NonSendable) -> ()
675+
// CHECK: [[CLOSURE_THUNK:%.*]] = function_ref @$sBA21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF11NonSendableL_CIeghHgILgT_BAADIeghHgILxT_TR : $@convention(thin) @Sendable @async (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @sil_sending @owned NonSendable, @guaranteed @Sendable @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @sil_sending @guaranteed NonSendable) -> ()) -> ()
676+
// CHECK: [[THUNKED_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_THUNK]]([[THICK_CLOSURE]])
677+
// CHECK: [[COMPUTE:%.*]] = function_ref @$s21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF1SL_V7compute7closureyyAaByyF11NonSendableL_CnYuYaYbYCc_tYaFZ : $@convention(method) @async (@guaranteed @Sendable @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @sil_sending @owned NonSendable) -> (), @thin S.Type) -> ()
678+
// CHECK: apply [[COMPUTE]]([[THUNKED_CLOSURE]], {{.*}}) : $@convention(method) @async (@guaranteed @Sendable @async @callee_guaranteed (@sil_isolated @sil_implicit_leading_param @guaranteed Builtin.ImplicitActor, @sil_sending @owned NonSendable) -> (), @thin S.Type) -> ()
679+
// CHECK: } // end sil function '$s21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF0D0L_yyYaF'
680+
@MainActor
681+
func test() async {
682+
// CHECK: // closure #1 in test #1 () in testNonisolatedNonsendingClosureInGlobalActorContext()
683+
// CHECK: // Isolation: caller_isolation_inheriting
684+
await S.compute { _ in
685+
}
686+
}
687+
}

test/Concurrency/transfernonsendable_closureliterals_isolationinference.swift

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,11 @@ func test_CallerSyncNormal_CalleeAsyncNonIsolated() async {
143143
normalAcceptsAsyncClosure { }
144144

145145
// CHECK-LABEL: closure #2 in test_CallerSyncNormal_CalleeAsyncNonIsolated()
146-
// CHECK-NEXT: Isolation: nonisolated
146+
// CHECK-NEXT: Isolation: {{nonisolated|caller_isolation_inheriting}}
147147
normalAcceptsSendingAsyncClosure { }
148148

149149
// CHECK-LABEL: // closure #3 in test_CallerSyncNormal_CalleeAsyncNonIsolated()
150-
// CHECK-NEXT: // Isolation: nonisolated
150+
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
151151
normalAcceptsSendableAsyncClosure { }
152152
}
153153

@@ -177,11 +177,11 @@ func test_CallerSyncNormal_CalleeAsyncMainActorIsolated() async {
177177
// expected-ni-ns-note @-4 {{sending global actor 'CustomActor'-isolated value of non-Sendable type '@concurrent () async -> ()' to main actor-isolated global function 'normalGlobalActorAcceptsAsyncClosure' risks causing races in between global actor 'CustomActor'-isolated and main actor-isolated uses}}
178178

179179
// CHECK-LABEL: // closure #2 in test_CallerSyncNormal_CalleeAsyncMainActorIsolated()
180-
// CHECK-NEXT: // Isolation: nonisolated
180+
// CHECK-NEXT: Isolation: {{nonisolated|caller_isolation_inheriting}}
181181
await normalGlobalActorAcceptsSendingAsyncClosure { }
182182

183183
// CHECK-LABEL: // closure #3 in test_CallerSyncNormal_CalleeAsyncMainActorIsolated()
184-
// CHECK-NEXT: // Isolation: nonisolated
184+
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
185185
await normalGlobalActorAcceptsSendableAsyncClosure { }
186186
}
187187

@@ -254,11 +254,11 @@ func test_CallerAsyncNormal_CalleeAsyncNonIsolated() async {
254254
// expected-ni-note @-1 {{sending global actor 'CustomActor'-isolated value of non-Sendable type '() async -> ()' to nonisolated global function 'asyncNormalAcceptsAsyncClosure' risks causing races in between global actor 'CustomActor'-isolated and nonisolated uses}}
255255

256256
// CHECK-LABEL: closure #2 in test_CallerAsyncNormal_CalleeAsyncNonIsolated()
257-
// CHECK-NEXT: Isolation: nonisolated
257+
// CHECK-NEXT: Isolation: {{nonisolated|caller_isolation_inheriting}}
258258
await asyncNormalAcceptsSendingAsyncClosure { }
259259

260260
// CHECK-LABEL: // closure #3 in test_CallerAsyncNormal_CalleeAsyncNonIsolated()
261-
// CHECK-NEXT: // Isolation: nonisolated
261+
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
262262
await asyncNormalAcceptsSendableAsyncClosure { }
263263
}
264264

@@ -296,11 +296,11 @@ func test_CallerAsyncNormal_CalleeAsyncMainActorIsolated() async {
296296
// expected-ni-ns-note @-4 {{sending global actor 'CustomActor'-isolated value of non-Sendable type '@concurrent () async -> ()' to main actor-isolated global function 'asyncNormalGlobalActorAcceptsAsyncClosure' risks causing races in between global actor 'CustomActor'-isolated and main actor-isolated uses}}
297297

298298
// CHECK-LABEL: // closure #2 in test_CallerAsyncNormal_CalleeAsyncMainActorIsolated()
299-
// CHECK-NEXT: // Isolation: nonisolated
299+
// CHECK-NEXT: Isolation: {{nonisolated|caller_isolation_inheriting}}
300300
await asyncNormalGlobalActorAcceptsSendingAsyncClosure { }
301301

302302
// CHECK-LABEL: // closure #3 in test_CallerAsyncNormal_CalleeAsyncMainActorIsolated()
303-
// CHECK-NEXT: // Isolation: nonisolated
303+
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
304304
await asyncNormalGlobalActorAcceptsSendableAsyncClosure { }
305305
}
306306

0 commit comments

Comments
 (0)