Rust’s async makes some design decisions that make it a unique feature: no other language has zero allocations to do async, for example. (In C++’s version you can get it to do no allocations if you do certain things, like making the required allocator a no-op, in my understanding, but it conceptually requires a call to an allocator)
This makes it suitable for a much wider variety of tasks than other languages with similar features, but does mean that there are more details that you need to care about than in other languages that are higher level.
This means it is controversial: some people would prefer a higher level experience, but for those who do use it for its full range of tasks, it’s great.
There are some rough edges, but it’s just a feature that, even outside of Rust, some people just fundamentally dislike. So it draws a lot of heat from all sides.
It is also probably the single largest driver of adoption of the language. Rust started truly taking off once it landed.
"it’s just a feature that, even outside of Rust, some people just fundamentally dislike" is why I have a hard time gauging this. I know Python users whine about it endlessly just because it's a feature from JS, even though Python's existing concurrency features were the worst of both worlds.
The Rust-specific async sounds interesting. I should give it a try.
I can only speak for myself, but I kind of refused to get started with Rust until async landed... only because it's kind of a core of scalable services. I think it's pretty great in that you can use an async runtime, but still launce native threads if you want/need to for specific scenarios. It's pretty great and for most high level tasks, I wouldn't classify it as significantly more difficult than C#.
A few other things I've done with it have been written by AI as much as myself... which has similarly been pretty nice... Rust code can be very easy to reason with (lifetime syntax not withstanding). For some reason Rust lifetimes burn my soul.