Earlier today I was trying out if static func inherits the actor context of its surrounding type and wrote this bit of code:
import SwiftUI
@MainActor
struct MainActorView: View {
static func doesStaticInheritActorContext() {
definitelyMainActor()
definitelyNetworkActor() // Error: Call to global actor 'NetworkActor'-isolated global function 'definitelyNetworkActor()' in a synchronous main actor-isolated context
definitelyNonisolated()
}
var body: some View { EmptyView() }
}
@MainActor func definitelyMainActor() {}
@NetworkActor func definitelyNetworkActor() {}
nonisolated func definitelyNonisolated() {}
@globalActor
actor NetworkActor {
static let shared = NetworkActor()
}
The error about calling code isolated to a different actor is expected, but what surprised me is that the call to definitelyNonisolated() succeeds, even though we are clearly on the main actor.
What does it mean for a (freestanding) synchronous function to be nonisolated, if anything?
// inherits whatever isolation it is called in
// cannot leave the thread
nonisolated func goodOldSyncFunction() {
}
// ensured to be always called inside isolation - MainActor in that case
// remains synchronous to call within the same isolation
// requires await outside of the isolation only
@MainActor
func isolatedSyncFunction() {
}
// always called on a generic executor
nonisolated func nonisolatedAsyncFunction() async {
}
// isolated to main actor and can suspend
@MainActor
func isolatedAsyncFunction() async {
}
@MainActor
func test() async {
goodOldSyncFunction() // inherits isolation of a caller
isolatedSyncFunction() // has the same isolation as a caller
await nonisolatedAsyncFunction() // will run on a generic executor, suspending current function
await isolatedAsyncFunction() // will run on main actor, but can suspend
}
@NetworkActor
func test2() async {
goodOldSyncFunction() // inherits isolation of a caller
await isolatedSyncFunction() // await as it is in another isolation - main actor
await nonisolatedAsyncFunction() // will run on a generic executor, suspending current function
await isolatedAsyncFunction() // await as it is in another isolation - main actor
}