MainActor closure type

let asyncClosure1: @MainActor () async -> Void
let ayncClosure2: @MainActor () -> Void

are these two function signatures different?

Yes, they have different types:

    // assuming `var` instead `let`…
    asyncClosure1 = asyncClosure2
    // ok
    asyncClosure2 = asyncClosure1
    // error: Invalid conversion from 'async' function of 
    // type '@MainActor () async -> Void' to synchronous 
    // function type '@MainActor () -> Void'

They're indistinguishable at the call site, but asyncClosure1 can itself suspend, while asyncClosure2 cannot.

Is there any practical difference? Well…

  • You can't write any async calls in the body of a non-async closure, so asyncClosure2 is more limited on what closures it can store.

  • If called from a @MainActor context, asyncClosure1 requires an await, but asyncClosure2 doesn't. The await can be an issue due to actor reentrancy.