I'm curious if the team ever considered an inverted approach. I've read through many of the discussions, and don't think I ever saw this suggested. I'm sure there must be a reason not to do it, but my Rust isn't advanced enough to tell.
It seems to me that you'll generally await futures in high-level code. Keeping values around as futures is the minority case. So instead of asking to await one could automatically insert awaiting code whenever a future needs to be converted to a real value. Instead of this:
async fn process() -> Image {
await process_image(await fetch("http://example.com/foo.jpg"))
}
...you could simply have this: async fn process() -> Image {
process_image(fetch("http://example.com/foo.jpg"))
}
...which would await both the inner and outer futures: process_image() expects an Image, and fetch() returns a Future<Image>, so it can be automatically awaited and coerced.Sometimes you do want a future when you don't want to wait right away, e.g. when storing a bunch of pending operations or something. For that, one could tell Rust not to automatically coerce futures:
let pending: HashMap<string, Future<Image>>
// ...
async fn process() {
pending[key] = defer process_image(fetch("http://example.com/foo.jpg"))
}
...although this, too, could presumably be done transparently for you, since Rust knows you're assigning to a future.