It seems if there are different types of futures they need to be boxed (or some other kind of unifying container).
Trying Box<> itself didn't work for me... had to do the following. Is this right (it does work, just not 100% sure)?
(can't put on playground since it doesn't support futures 0.3 yet)
#![feature(async_await)]
use futures::{Future, executor};
use futures::future::{self, join_all, FutureExt};
use core::pin::Pin;
type StringResult = Result<String, String>;
// Attempt 1: impl Future
// fails because the match arms are different types
/*
fn get_future(key:&str) -> impl Future<Output = StringResult> {
let key_owned = key.to_owned();
match key {
"hello" => future::ok(key_owned),
"world" => future::lazy(|_| Ok(key_owned)),
_ => future::err(format!("bad key: {}", key)),
}
}
*/
//Attempt 2: Box<dyn Future>
//fails because... Pin requirements?
/*
fn get_future(key:&str) -> Box<dyn Future<Output = StringResult>> {
let key_owned = key.to_owned();
match key {
"hello" => Box::new(future::ok(key_owned)),
"world" => Box::new(future::lazy(|_| Ok(key_owned))),
_ => Box::new(future::err(format!("bad key: {}", key))),
}
}
*/
//Attempt 3: Pin<Box<Future>> (via future.boxed())
//It works! Requires the FutureExt trait be in scope
fn get_future(key:&str) -> Pin<Box<dyn Future<Output = StringResult>>> {
let key_owned = key.to_owned();
match key {
"hello" => future::ok(key_owned).boxed(),
"world" => future::lazy(|_| Ok(key_owned)).boxed(),
_ => future::err(format!("bad key: {}", key)).boxed(),
}
}
fn main() {
executor::block_on(async {
let results = join_all(vec![get_future("hello"), get_future("world"), get_future("!")]).await;
for result in results.iter() {
match result {
Ok(happy) => println!("happy: {}", happy),
Err(sad) => println!("sad: {}", sad)
}
}
});
}