> having used C++, python+javascript (ahhhh) and Rust concurrency, I found the assurance and debuggabilty the type system gives you very relaxing
Not to say anything about C++, python and pre-async JS, but if you compare with async in modern languages and especially if you compare with Go, async Rust leaves a lot to desire imo, mostly in terms of ergonomics and total system complexity.
> but it's not unnecessarily complicated: basically everything is there for a reason
Yes and no. Let me be careful with my words here. Everything is there for a reason, which is always locally coherent. However, globally speaking, these reasons can get more and more detached from the end goal, including the core principles of Rust such as zero-cost and fearless concurrency. I believe this is exactly what happened to async Rust.
A simple example would be lack of async traits. Traits are one of Rust's best features, and everyone has to work around them, meaning that you have to think differently about the same problem depending on if you're in async vs not.
Another example is implementing the Future trait (implementing a trait is standard practice in Rust). Only this often requires awareness around auto traits like Send, HRTBs and pin projection, (which happens to be one of the most complex things I've done), and all I'm trying to do is wrap some user provided future. These deep topics are more of a convoluted type system puzzle (and if you like those it can be fun). But it has very little to do with concurrency and much less with whatever business logic we're trying to manage.