swiftactorstructured-concurrency

Async call to a func defined in extension from an isolated function in an actor preserves the isolation?


I have this setup:

protocol Foo {
    func foo() async
}

extension Foo {
    func foo() async {
        print("default implementation")
    }
}

final actor Bar: Foo {
    func run() async {
         print("this function is isolated on actor Bar")
         await self.foo()
    }

}

Question: will the foo be run on the actor Bar? Or the actor will be released because it's an async call outside the scope of actor?


Solution

  • No.

    If foo() were really in the same isolation context, then it should be able to access synchronous function without awaiting. And I could define that:

    protocol Foo {
        func foo() async
        func sync()  // Adding a new synchronous requirement
    }
    
    extension Foo {
        func foo() async {
            print("default implementation")
            sync() // And this should be fine
        }
    }
    

    But it is not possible to implement this with an actor within its isolation:

    final actor Bar: Foo {
        func run() async { ... }
    
        func sync() {}
        // -> Actor-isolated instance method 'sync()' cannot be used to satisfy nonisolated protocol requirement
    }
    

    In order for Bar to implement Foo, sync() must be nonisolated:

    // This is fine
    final actor Bar: Foo {
        func run() async { ... }
    
        nonisolated func sync() {}
    }
    

    So the default implementation of foo() cannot synchronously access isolated parts of Bar.