Skip to content

Commit 641cfe0

Browse files
committed
[Concurrency] Fix @Sendable closures not inferring nonisolated(nonsending)
If there are no explicit concurrency attributes, isolated parameters, or captures associated with the closure it should infer `nonisolated(nonsending)` for the parent conversion injected by the solver (this conversion is injected because the solver cannot check captures to elide it). The change pushes `isIsolationInferenceBoundaryClosure` check down with added benefit of getting preconcurrency context from the parent. (cherry picked from commit 3ae34e8)
1 parent 232511f commit 641cfe0

File tree

4 files changed

+20
-12
lines changed

4 files changed

+20
-12
lines changed

lib/Sema/TypeCheckConcurrency.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5007,16 +5007,6 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
50075007
return ActorIsolation::forActorInstanceCapture(param);
50085008
}
50095009

5010-
// If we have a closure that acts as an isolation inference boundary, then
5011-
// we return that it is non-isolated.
5012-
//
5013-
// NOTE: Since we already checked for global actor isolated things, we
5014-
// know that all Sendable closures must be nonisolated. That is why it is
5015-
// safe to rely on this path to handle Sendable closures.
5016-
if (isIsolationInferenceBoundaryClosure(closure,
5017-
/*canInheritActorContext=*/true))
5018-
return ActorIsolation::forNonisolated(/*unsafe=*/false);
5019-
50205010
// A non-Sendable closure gets its isolation from its context.
50215011
auto parentIsolation = getActorIsolationOfContext(
50225012
closure->getParent(), getClosureActorIsolation);
@@ -5048,6 +5038,16 @@ ActorIsolation ActorIsolationChecker::determineClosureIsolation(
50485038
}
50495039
}
50505040

5041+
// If we have a closure that acts as an isolation inference boundary, then
5042+
// we return that it is non-isolated.
5043+
//
5044+
// NOTE: Since we already checked for global actor isolated things, we
5045+
// know that all Sendable closures must be nonisolated. That is why it is
5046+
// safe to rely on this path to handle Sendable closures.
5047+
if (isIsolationInferenceBoundaryClosure(closure,
5048+
/*canInheritActorContext=*/true))
5049+
return ActorIsolation::forNonisolated(/*unsafe=*/false);
5050+
50515051
return normalIsolation;
50525052
}();
50535053

test/Concurrency/actor_inout_isolation.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ if #available(SwiftStdlib 5.1, *) {
220220
let _ = Task.detached { await { (_ foo: inout Int) async in foo += 1 }(&number) }
221221
// expected-error @-1 {{actor-isolated var 'number' cannot be passed 'inout' to 'async' function call}}
222222
// expected-minimal-error @-2 {{global actor 'MyGlobalActor'-isolated var 'number' can not be used 'inout' from a nonisolated context}}
223-
// expected-complete-tns-error @-3 {{main actor-isolated var 'number' can not be used 'inout' from a nonisolated context}}
223+
// expected-complete-tns-warning @-3 {{main actor-isolated var 'number' can not be used 'inout' from a nonisolated context}}
224224
}
225225

226226
// attempt to pass global state owned by the global actor to another async function

test/Concurrency/attr_execution/conversions_silgen.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,3 +613,11 @@ func testConvertToThrowing(isolation: isolated (any Actor)? = #isolation) async
613613
observe()
614614
}
615615
}
616+
617+
func testSendableClosureNonisolatedNonSendingInference() {
618+
// CHECK-LABEL: sil private [ossa] @$s21attr_execution_silgen49testSendableClosureNonisolatedNonSendingInferenceyyFySiYaYbYCcfU_ : $@convention(thin) @Sendable @async (@sil_isolated @sil_implicit_leading_param @guaranteed Optional<any Actor>, Int) -> ()
619+
// CHECK: bb0([[EXECUTOR:%.*]] : @guaranteed $Optional<any Actor>, %1 : $Int):
620+
// CHECK: hop_to_executor [[EXECUTOR]]
621+
// CHECK: // end sil function '$s21attr_execution_silgen49testSendableClosureNonisolatedNonSendingInferenceyyFySiYaYbYCcfU_'
622+
let _: nonisolated(nonsending) @Sendable (Int) async -> Void = { _ in }
623+
}

test/Concurrency/sendable_checking_captures_swift5.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,5 +92,5 @@ do {
9292

9393
let c: Class
9494
test(c)
95-
// expected-complete-warning@-1:8 {{implicit capture of 'c' requires that 'Class' conforms to 'Sendable'; this is an error in the Swift 6 language mode}}
95+
// expected-complete-warning@-1:8 {{implicit capture of 'c' requires that 'Class' conforms to 'Sendable'}}
9696
}

0 commit comments

Comments
 (0)