Should assumeIsolated adopt sending?

I have a setup where an actor (a database) has a method returning non-sendable types using the sending keyword. I need to call that method from elsewhere (inside a transaction struct) which is always run on the actor (database). I've been using assumeIsolated in the Swift 5 language mode, but that is now an error in Swift 6 because the type returned by the actor is not Sendable. I believe this would be resolved if assumeIsolated adopts sending. I'd be happy to get a pull request going if this makes sense.

Is there a workaround I can use in the meantime? I tried using nonisolated(unsafe) in various places but that didn't seem to work.

class Nonsendable { }

actor Actor {
    func newNonsendable() -> sending NonSendable {
        NonSendable()
    }
}

let myActor = Actor()

func alwaysCalledFromActor() -> NonSendable {
    myActor.assumeIsolated { // Type 'Nonsendable' does not conform to the 'Sendable' protocol
        $0.newNonsendable()
    }
}
2 Likes

Have you seen this other thread?

1 Like

Ah thank you! That makes me hopeful.

I wonder if I can propagate isolation statically somehow โ€“ the setup is an actor (the database) which has a transaction method that looks roughly like this:

func transaction(_ body: (TransactionContext) -> Void)

TransactionContext has a reference to the database actor to provide read access inside the transaction closure. Since a transaction is only ever run on the database actor, Iโ€™ve been using assumeIsolated inside TransactionContext to provide synchronous access to the database.

While there isn't a "we know the Context is always on some specific actor so the closure should be as well" there is an upcoming proposal that would improve closure isolation controls over here: swift-evolution/proposals/nnnn-closure-isolation-control.md at closure-isolation ยท sophiapoirier/swift-evolution ยท GitHub

You can have a look at that, using it you could express things { [isolated something] in ... } in closures. It may need even more flexibility to achieve the kind of thing you're asking for ("know that context is always on some of it's member, which is an actor" etc), but that's certainly a step towards more control over isolation of closures.

That proposal didn't make it into Swift 6.0 though, but keep an eye out for it.

1 Like