[Pitch #2] Async/await

There isn't a difference between async actor methods and normal async methods. Both can have inout parameters. The restrictions we need are on which arguments you can provide, to ensure that you have exclusive access to the argument to the inout even across a suspension. The actor proposal states the restriction for actor-isolated instance members:

Actor-isolated stored properties can be passed into synchronous functions via inout parameters, but it is ill-formed to pass them to asynchronous functions via inout parameters. For example:

func modifiesSynchronously(_: inout Double) { }
func modifiesAsynchronously(_: inout Double) async { }

extension BankAccount {
  func wildcardBalance() async {
    modifiesSynchronously(&balance)        // okay
    await modifiesAsynchronously(&balance) // error: actor-isolated property 'balance' cannot be passed 'inout' to an asynchronous function
  }
}  

This restriction prevents exclusivity violations where the modification of the actor-isolated balance is initiated by passing it as inout to a call that is then suspended, and another task executed on the same actor then fails with an exclusivity violation in trying to access balance itself.

It doesn't matter whether modifiesAsynchronously is on an actor or not; you still can't pass &self.balance to it.

However, it would be fine to pass &myLocalVariable to it so long as we've already ensured that myLocalVariable doesn't have captures that can run concurrently. That's partially implemented as a warning in the experimental concurrency mode, and I promised (somewhere these threads) to bring that into one of the proposals... but haven't done so yet.

Doug

2 Likes