> Is async in Rust really this bad?
No, it's not. It works. Perfect? No, absolutely not. There is plenty you could improve, plenty of rough edges you could smooth out. Stuff that caused us problems at the job I had writing low-ish level machine control services. But it's totally workable and we were able to ship working devices, especially compared to doing async stuff in other most other languages, especially the memory-unmanaged ones.
Kind of like Rust itself, a ton of people have tried it and bounced off it because they couldn't get it working in 10 minutes, and in doing so have declared it impossible/for geniuses only/broken/ecosystem-destroying. The narrative around async Rust is probably 70% meme/bad PR, 30% real, actual issues that could be improved.
I hope this comes off as fair. I don't want to excuse any of the shortcomings, but it's a working, useful tool.
100% agree with your take, speaking as a professional async rust writer for like five years now.
I’ll add to it that structured concurrency patterns in async Rust can be legitimately awesome and very fun, once you’ve bounced off the traits in the futures crate enough times to use it in anger. The type system can be annoying, but as usual, it’s almost always technically right, and once you understand the ownership flow required for your nifty chain of future combinators, is not too too bad.
Funny... I started off with very little knowledge, totally cheated with what I wanted to do by cloning everything crossing various library boundaries and it still worked surprisingly well. Then I learned about (A)RC, Box etc... and I still kinda really hate the lifetime syntax.
Note: most of what I've used it for has been relatively simple... API's with tokio and axum in rust are emphatically not much more difficult than say C# with FastEndpoints, or JS/TS with Hono. It's a bit different.
I think part of it is that most of Rust sets a really high standard for polish and good design; developers new to the language are often quite impressed by its expressiveness and by the breadth of bug classes it protects you from, once you get over the initial learning curve. (Not always—some developers never grow to like it, either because it's a bad fit for their use case or because they happen to find its particular forms of ceremony especially off-putting—but the success cases are striking.)
And then you start using async, which is less polished and has more awkward design compromises and more footguns that you only find out about at runtime, and it's a bit of a disappointment by comparison, even if some of the problems aren't worse than what you find in competing languages. This is the vibe you get in the Oxide RFDs about things like futurelock, for example.