Environment:
Swift 6.3.2, Swift 6 Language Mode, Default Actor Isolation (nonisolated), NonisolatedNonsendingByDefault enabled
It’s been my understanding that @Sendable closures are inferred to be nonisolated. That said, the following code yields an unexpected result: the @Sendable closure inherits MainActor isolation.
func callSendableClosure(_ closure: @Sendable () async -> Void) async {
let isolation = #isolation
print("\(isolation, default: "nonisolated")") // Swift.MainActor
await closure()
}
@main
struct ClosureIsolation {
// implicitly isolated to @MainActor
static func main() async {
await callSendableClosure {
let isolation = #isolation
print("\(isolation, default: "nonisolated")") // Swift.MainActor
}
}
}
This behavior isn’t explicitly called out in SE-0461, although it’s possible it was implied or I simply misread something. Can someone kindly confirm if this is intended behavior?
Interestingly enough, disabling NonisolatedNonsendingByDefault and explicitly marking the function nonisolated(nonsending) results in the behavior I originally expected: the @Sendable closure executes on the GCE.
nonisolated(nonsending)
func callSendableClosure(_ closure: @Sendable () async -> Void) async {
let isolation = #isolation
print("\(isolation, default: "nonisolated")") // Swift.MainActor
await closure()
}
@main
struct ClosureIsolation {
// implicitly isolated to @MainActor
static func main() async {
await callSendableClosure {
let isolation = #isolation
print("\(isolation, default: "nonisolated")") // nonisolated
}
}
}