I don't want to "well actually" the "well actually", but I think you missed the word syntactically.
> C#'s Task/Task<T> are based on background execution. Once something is awaited, control is returned to the caller.
Async/await in any language happens in the background.
What happens during a Task.Yield() (C#)? The task is yielded to the another awaiting task in the work queue. Same as Rust.
> OTOH, Rust's Future<T> is, by default, based on polling/stepping,
The await syntax abstracts over Future/Stream polling. The real difference is that Rust introduced the Future type/concept of polling at all (which is a result of not having a standard async runtime). There is a concept of "is this task available to proceed on" in C# too, it's just not exposed to the user and handled by the CLR.