Can you explain "this is less overhead than immediately suspending"? AFAICT Rust's approach is as low-overhead as it gets, since the inherent separation between future creation and future execution means that future creation doesn't need to have any cost at all. I'm also not sure it makes sense to refer to Rust's behavior as "immediately suspending", since it's not suspending anything: until someone chooses to start executing the async function, there's no state to suspend?
As for the rationale for why Rust is aiming for this behavior, I think this comment buried in the RFC discussion (https://github.com/rust-lang/rfcs/pull/2394#issuecomment-382...) sums it up (and makes note of Dart 2.0 as a contrasting example):
"A fundamental difference between Rust's futures and those from other languages is that Rust's futures do not do anything unless polled. The whole system is built around this: for example, cancellation is dropping the future for precisely this reason. In contrast, in other languages, calling an async fn spins up a future that starts executing immediately."
"A point about this is that async & await in Rust are not inherently concurrent constructions. If you have a program that only uses async & await and no concurrency primitives, the code in your program will execute in a defined, statically known, linear order. Obviously, most programs will use some kind of concurrency to schedule multiple, concurrent tasks on the event loop, but they don't have to. What this means is that you can - trivially - locally guarantee the ordering of certain events, even if there is nonblocking IO performed in between them that you want to be asynchronous with some larger set of nonlocal events (e.g. you can strictly control ordering of events inside of a request handler, while being concurrent with many other request handlers, even on two sides of an await point)."
"This property gives Rust's async/await syntax the kind of local reasoning & low-level control that makes Rust what it is. Running up to the first await point would not inherently violate that - you'd still know when the code executed, it would just execute in two different places depending on whether it came before or after an await. However, I think the decision made by other languages to start executing immediately largely stems from their systems which immediately schedule a task concurrently when you call an async fn (for example, that's the impression of the underlying problem I got from the Dart 2.0 document)."