What a milestone! This was the most impressive work in open source decision-making that I have ever followed (in my limited experience). People have contributed thousands of comments discussing this for over a year. It has even caused the team to rethink how discussions like this should be guided in the future beyond comments on GitHub issues. I cannot imagine how difficult it has been to manage it all, and I applaud and thank the Rust team for their hard work in fielding comments, weighing trade-offs, and ultimately making a decision in order to move the project forward.
> This was the most impressive work in open source decision-making that I have ever followed...
You'd be blown away by Linux Kernel development then. Multiple magnitudes above any measurement of an await syntax bikeshedding. /u/Perceptes puts it best than I ever could in this top voted comment on /r/rust [1]:
"...I personally don't care at all about the await syntax, and have been very unhappy with that bikeshed being such a focus of time and discussion. The real problems I have with the unstable async system are how difficult it is to reason about. Compiler errors are still largely indecipherable. impl Trait didn't really help here. Documentation is still sparse, so I spend a lot of time banging my head against the wall, trying many formulations of my programs to get just the right incantation of futures wrapped in futures wrapped in futures to get things to compile, only to get page-long type mismatch errors that are near impossible to read, and multiple closures/functions deep of nested futures being returned where any of them could be the culprit. I'm also very frustrated by the lack of progress on "abstract types" that are required for using async functions (and returning impl Trait) from trait methods. Traits are the cornerstone of Rust's type system and yet I haven't seen any activity on this for months. And now we're talking stabilization with this glaring hole. Async streams are another thing I've seen almost no progress on, aside from a blog post from withoutboats on how to deal with the ? operator within async for loops..."
The nuances in this case went well beyond what I was expecting - it's actually more than just syntax, this heavily crosses over into semantics. It's been a very impressive process, and I was surprised at the power of the solution they landed on.
- Rust has to find a syntax that can work with different underlying libraries (Rust can compile to lots of different targets, some will have capability to accommodate larger libraries than others)
- The abstraction can't incur undue overhead (callback-based solutions may cause allocations that are hard to keep under control and will split the language if it spreads too much)
- The syntax should be pleasant to write for at least the majority of people (modeling your entire application as a state machine around async computation is pretty unpleasant)
- The compiler has to be able to give helpful error messages (this was a problem early on I think)
- Language authors had to think about how the borrow checker would work across async points, and whether to invest in changing the language to make that possible.
- and so on and so on
I really loved this talk by Without Boats (the author of the friendly article) going over all this stuff, really gave me a good sense of what they were up against https://www.youtube.com/watch?v=skos4B5x7qE