Reputation: 91
I want to generate a Vec
of .await
s and execute them with join_all
:
use futures::future::join_all; // 0.3.5
use std::future::Future;
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
async fn main() {
let urls = vec!["Peter", "Hans", "Jake"];
let mut requests: Vec<Box<dyn Fn() -> Box<dyn Future<Output = String>>>> = vec![];
for url in urls {
requests.push(Box::new(|| Box::new(hello(&url))));
}
let responses: Vec<String> = join_all(requests).await;
println!("Response: {:?}", responses);
}
I get the error message:
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` cannot be unpinned
--> src/main.rs:15:45
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:83:14
|
83 | I::Item: Future,
| ------ required by this bound in `futures::future::join_all`
|
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
--> src/main.rs:15:45
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^ `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:83:14
|
83 | I::Item: Future,
| ------ required by this bound in `futures::future::join_all`
|
= help: the trait `futures::Future` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` cannot be unpinned
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:28:8
|
28 | F: Future,
| ------ required by this bound in `futures::future::JoinAll`
|
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^ `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.5/src/future/join_all.rs:28:8
|
28 | F: Future,
| ------ required by this bound in `futures::future::JoinAll`
|
= help: the trait `futures::Future` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` cannot be unpinned
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::marker::Unpin` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
|
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
--> src/main.rs:15:36
|
15 | let responses : Vec<String> = join_all(requests).await;
| ^^^^^^^^^^^^^^^^^^^^^^^^ `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>` is not a future
|
= help: the trait `futures::Future` is not implemented for `dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>`
= note: required because of the requirements on the impl of `futures::Future` for `std::boxed::Box<dyn std::ops::Fn() -> std::boxed::Box<dyn futures::Future<Output = std::string::String>>>`
error[E0277]: `main` has invalid return type `impl futures::Future`
--> src/main.rs:9:17
|
9 | async fn main() {
| ^ `main` can only return types that implement `std::process::Termination`
|
= help: consider using `()`, or a `Result`
error[E0752]: `main` function is not allowed to be `async`
--> src/main.rs:9:1
|
9 | async fn main() {
| ^^^^^^^^^^^^^^^ `main` function is not allowed to be `async`
Upvotes: 7
Views: 3313
Reputation: 432239
join_all
requires an iterator of futures, not an iterator of functions returning futures:
pub fn join_all<I>(i: I) -> JoinAll<<I as IntoIterator>::Item>
where
I: IntoIterator,
<I as IntoIterator>::Item: Future,
Additionally, your futures can't be pinned and so join_all
cannot use them.
The shortest fix is to:
use futures::future; // 0.3.5
use std::{future::Future, pin::Pin};
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
pub async fn example() {
let urls = vec!["Peter", "Hans", "Jake"];
let mut requests: Vec<Box<dyn Fn() -> Pin<Box<dyn Future<Output = String>>>>> = vec![];
for url in urls {
requests.push(Box::new(move || Box::pin(hello(&url))));
}
let responses: Vec<String> = future::join_all(requests.into_iter().map(|r| r())).await;
println!("Response: {:?}", responses);
}
This can be written more succinctly as:
use futures::future::{self, FutureExt, LocalBoxFuture}; // 0.3.5
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
pub async fn example() {
let urls = vec!["Peter", "Hans", "Jake"];
let mut requests: Vec<Box<dyn Fn() -> LocalBoxFuture<'static, String>>> = vec![];
for url in urls {
requests.push(Box::new(move || hello(&url).boxed_local()));
}
let responses: Vec<String> = future::join_all(requests.into_iter().map(|r| r())).await;
println!("Response: {:?}", responses);
}
However, none of that is needed for your specific example:
Vec
use futures::future; // 0.3.5
async fn hello(name: &str) -> String {
format!("Hello {}!", name)
}
pub async fn example() {
let urls = vec!["Peter", "Hans", "Jake"];
let hellos = urls.iter().map(|u| hello(u));
let responses = future::join_all(hellos).await;
println!("Response: {:?}", responses);
}
See also:
Upvotes: 3