Why doesn’t `_` identifier compile with async let?

this fails to compile:

actor Stream  
{
    ...
    private 
    var socket:WebSocket? 
    
    private 
    func set(connection socket:WebSocket) 
    {
        self.socket = socket 
    }
    
    nonisolated 
    func messages(timeout:TimeAmount) async -> AsyncStream<String> 
    {
        let socket:WebSocket    = await WebSocket.connect(to: Self.url, on: self.group)
        async let _:Void        = self.set(connection: socket)
        ...
    }
} 

but if i give the async let a name, it compiles fine. why?

1 Like

edit: Given these lines, it should be a compiler bug:

Special attention needs to be given to the async let _ = ... form of declarations. This form is interesting because it creates a child-task of the right-hand-side initializer, however it actively chooses to ignore the result. Such a declaration (and the associated child-task) will run and be awaited-on implicitly, as the scope it was declared in is about to exit — the same way as an unused async let declaration would be.


If you have read SE-0317, you will notice that async let is actually a pure syntactic sugar around Task:

async let myProduct = build()
// …
return await myProduct

works the same as

let myProduct_Task = Task { build() }
// …
return await myProduct_Task.value

While we typically await for the value after async let — if we don’t do so, Swift will call cancel() and wait() on the task. An anonymous async let variable, resulting in an anonymous Task, cannot be referenced. That’s why async let _ fails to compile.

2 Likes