But that is the whole point, this isn't like a let. Two major differences pointed out upthread:
actor SomeActor {
// async let creates and runs its body in a new task, so its initializer requires sendability for any captured values.
func g(x : NSString) { ... }
func test1(x : NSString) {
let a = g(x: x) // Ok
async let b = g(x: x)+asyncthing() // not ok, because of Sendable check.
}
// async let runs its body in a new task, so actor self promotion happens.
var someString : NSString
func test2() {
let a= g(x: someNSString) // everything is ok
// Error, cannot refer to non-sendable property on isolated actor reference "self".
async let b = g(x: someNSString)+asyncthing()
}
}
Furthermore, the promotion of actor self from a "nonisolated Self" to an "isolated Self" introduces implicit suspend points given the proposed semantics, which is a huge concern from a logic correctness perspective:
func makeString() async -> String {... }
actor Actor2 {
func oneThing() {...}
func twoThing() -> String { ... }
func test2() {
oneThing()
let a = twoThing() + await makeString() // everything is ok
// compiles fine, but is NOT the same.
oneThing()
async let b = twoThing() + makeString()
}
}
Note the footgun that just happened there. If you spell this out explicitly, you can see what happened, because this would not compile:
// Error: cannot invoke doThing synchronously given a cross-task reference to actor 'self'.
@Future let b = { doThing() + await makeString() }
You'd be required to spell it like this, which makes it clear what is going on:
@Future let b = { await self.doThing() + await makeString() }
However, the proposal doesn't achieve this, and claiming that "async let is like a let" makes it extremely difficult to understand these things. The proposed behavior would just silently and unexpectedly introduced a suspension point between oneThing()
and twoThing()
, undermining the goal of the actor proposal which requires marking to make suspensions something we can reason about.
The proposal is not at all like a let
. This is a different beast, and the syntax it is eliminating is load bearing.
-Chris