I love this proposal so much. Much of it is exactly how I’ve thought Swift’s concurrency model should look over the last year.
Making async a return attribute just like throws
seems like the right solution to me. Building on top of callbacks (rather than introducing futures/promises) is also the right approach for swift. I think this proposal nails the problem right on the head: callbacks don't work well with the rest of Swift's error handling, is awkward, error prone, and yes, looks ugly.
One point that I've gone back and forth on is how strictly to enforce excecution order. For instance, in this example. it would make sense to allow the first 2 lines to excecute in parallel and excecute the third line once they both complete:
let a = await foo()