IMHO the biggest Rust async annoyance is exactly this:
> Tokio's default choice of making `spawn` take Send/Sync futures
... combined with lack of structured concurrency.
This means async tasks look like threads in every respect, causing you to end up using Arc<> and other concurrency constructs all over the place where they ought not be necessary. This harms efficiency and adds verbosity.
It's not too hard to do tokio without Send/Sync futures. See the example in https://docs.rs/tokio/latest/tokio/task/struct.LocalSet.html... It's kind of annoying that the current_thread flavor of the executor doesn't automatically enter a LocalSet and make spawn_local work out of the box but it's easy enough to do at the beginning of your program.
> Tokio's default choice of making `spawn` take Send/Sync futures
... combined with lack of structured concurrency.
This means async tasks look like threads in every respect, causing you to end up using Arc<> and other concurrency constructs all over the place where they ought not be necessary. This harms efficiency and adds verbosity.