Okay, one problem with it is purely syntactic, the compiler will interpret await { as a beginning of an async code block, i.e.:
await {
// some async code
}()
I tried it and indeed it's what the compiler is expecting.
Second problem is let's say cognition-related. When I look at your await { case let ... example my first instinct is that the case labels denote alternatives, i.e. only one of them will be executed, although of course once you look closer you realize that can't be the case. This is because we are all used to the switch syntax which selects only one of the paths.
Thirdly, aren't you trying to reinvent the "zipper" pattern? I have a family of functions in my library that kind of do what you are trying to achieve.
With e.g. two-parameter zip() call you can have:
let (x, y) = await zip {
let x = await f()
// do something with x
return x
} _: {
let y = await g()
// do something with y
return y
}
Eventually you get x and y but you can also do something with them as they become available. Not as elegant as a built-in syntax would be, but does the job.
(These functions are experimental, I still need to figure out if I need to use rethrows and how, but overall they do the job.)
And finally, I'm still struggling with finding a real world example that would require to handle the async results as they arrive but also wait for all of them to finish at the same time. The usage of my zip function family is much simpler most of the time, i.e.:
let (x, y) = await zip(f, g)
where f and g are async functions.