how to store Futures from 2 different async functions with equal signatures in vector?
i have 2 functions in different crates:
crate 1:
pub async fn resolve(
client: &String,
site: &String,
id: &String,
) -> Result<String, Box<dyn std::error::Error>> {
...
return Ok("".parse().unwrap());
}
crate 2:
pub async fn resolve(
client: &String,
site: &String,
id: &String,
) -> Result<String, Box<dyn std::error::Error>> {
...
return Ok("".parse().unwrap());
}
and i tried to aggregate results of functions calls like so:
let mut futures : Vec<_> = Vec::new();
for i in 0..self.settings.count {
futures.push(
crate1::resolve(
&self.settings.filed1,
&self.settings.filed2,
&product.id,
)
);
futures.push(
crate2::resolve(
&self.settings.filed1,
&self.settings.filed2,
&product.id,
)
);
}
but i got this:
error[E0308]: mismatched types
--> src\client.rs:124:17
|
124 | / crate2::resolve(
125 | | &self.settings.filed1,
126 | | &self.settings.filed2,
127 | | &product.id,
128 | | )
| |_________________^ expected opaque type, found a different opaque type
|
note: while checking the return type of the `async fn`
--> src\crate1.rs:97:6
|
97 | ) -> Result<String, Box<dyn std::error::Error>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, expected opaque type
note: while checking the return type of the `async fn`
--> src\crate2.rs:17:6
|
17 | ) -> Result<String, Box<dyn std::error::Error>> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ checked the `Output` of this `async fn`, found opaque type
= note: expected opaque type `impl futures::Future` (opaque type at <src\crate1.rs:97:6>)
found opaque type `impl futures::Future` (opaque type at <src\crate2.rs:17:6>)
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
why rust can't deduce type?
Rust can deduce the type, it just considers any 2 uses of impl Future
(which is what async fn
desugars to) to be different types.
To illustrate, consider the following functions:
async fn f1() {
println!("f1");
}
async fn f2() {
let a: Foo = another_future().await;
let b: Bar = anoter_future_2().await;
println!("f2: {} {}", a, b);
}
Rust will (very roughly speaking) rewrite these as state machines:
enum f1_StateMachine {
Done // only one state because no await points
}
enum f2_StateMachine {
AfterFirstAwait(a: Foo),
AfterSecondFuture(b: Bar),
Done,
}
impl Future for f1_StateMachine { ... }
impl Future for f2_StateMachine { ... }
These are clearly not the same type, so can't be used inside a Vec
together. As with any time you want to have a Vec
contain multiple different types that all implement the same trait, you can use a trait object, and put the futures in a Box
.
Note, boxed futures can be a little tricky, this SO answer might be helpful reading: How can one await a result of a boxed future?