Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions lib/Sema/TypeCheckConcurrency.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5013,6 +5013,10 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
auto normalIsolation = computeClosureIsolationFromParent(
closure, parentIsolation, checkIsolatedCapture);

bool isIsolationBoundary =
isIsolationInferenceBoundaryClosure(closure,
/*canInheritActorContext=*/true);

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

return normalIsolation;
Expand Down
26 changes: 26 additions & 0 deletions test/Concurrency/attr_execution/conversions_silgen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -659,3 +659,29 @@ func testSendableToSendableConversionWithNonisilatedNonsending() {
nonisolated(nonsending) @escaping (String) async throws -> String
) async throws -> Void = test
}

func testNonisolatedNonsendingClosureInGlobalActorContext() {
class NonSendable {
var state = ""
}

struct S {
static func compute(closure: nonisolated(nonsending) @Sendable @escaping (sending NonSendable) async -> Void) async {}
}

// CHECK-LABEL: sil private [ossa] @$s21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF0D0L_yyYaF : $@convention(thin) @async () -> ()
// 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) -> ()
// 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) -> ()
// 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) -> ()) -> ()
// CHECK: [[THUNKED_CLOSURE:%.*]] = partial_apply [callee_guaranteed] [[CLOSURE_THUNK]]([[THICK_CLOSURE]])
// 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) -> ()
// 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) -> ()
// CHECK: } // end sil function '$s21attr_execution_silgen52testNonisolatedNonsendingClosureInGlobalActorContextyyF0D0L_yyYaF'
@MainActor
func test() async {
// CHECK: // closure #1 in test #1 () in testNonisolatedNonsendingClosureInGlobalActorContext()
// CHECK: // Isolation: caller_isolation_inheriting
await S.compute { _ in
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -143,11 +143,11 @@ func test_CallerSyncNormal_CalleeAsyncNonIsolated() async {
normalAcceptsAsyncClosure { }

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

// CHECK-LABEL: // closure #3 in test_CallerSyncNormal_CalleeAsyncNonIsolated()
// CHECK-NEXT: // Isolation: nonisolated
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
normalAcceptsSendableAsyncClosure { }
}

Expand Down Expand Up @@ -177,11 +177,11 @@ func test_CallerSyncNormal_CalleeAsyncMainActorIsolated() async {
// 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}}

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

// CHECK-LABEL: // closure #3 in test_CallerSyncNormal_CalleeAsyncMainActorIsolated()
// CHECK-NEXT: // Isolation: nonisolated
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
await normalGlobalActorAcceptsSendableAsyncClosure { }
}

Expand Down Expand Up @@ -254,11 +254,11 @@ func test_CallerAsyncNormal_CalleeAsyncNonIsolated() async {
// 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}}

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

// CHECK-LABEL: // closure #3 in test_CallerAsyncNormal_CalleeAsyncNonIsolated()
// CHECK-NEXT: // Isolation: nonisolated
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
await asyncNormalAcceptsSendableAsyncClosure { }
}

Expand Down Expand Up @@ -296,11 +296,11 @@ func test_CallerAsyncNormal_CalleeAsyncMainActorIsolated() async {
// 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}}

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

// CHECK-LABEL: // closure #3 in test_CallerAsyncNormal_CalleeAsyncMainActorIsolated()
// CHECK-NEXT: // Isolation: nonisolated
// CHECK-NEXT: // Isolation: {{nonisolated|caller_isolation_inheriting}}
await asyncNormalGlobalActorAcceptsSendableAsyncClosure { }
}

Expand Down