I'm trying to run multiple futures in parallel with join_all but I get a different opaque type error and I haven't been able to find why. Can somebody point me in the right direction?
The error I get is
error[E0308]: mismatched types
--> src/main.rs:86:9
|
86 | get_blobs_from_table(pool, &blobs, "TestTable"),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected opaque type, found a different opaque type
...
131 | ) -> Result<ShardBlobCounts, sqlx::Error> {
| ------------------------------------ the `Output` of this `async fn`'s found opaque type
|
= note: expected type `impl core::future::future::Future` (opaque type at <src/main.rs:109:6>)
found opaque type `impl core::future::future::Future` (opaque type at <src/main.rs:131:6>)
= note: distinct uses of `impl Trait` result in different opaque types
Every async function generates a different, unique type. They are not the Future type, but a secret unnameable type that happens to support Future's methods.
It doesn't matter that these functions asynchronously all return the same Result type, because the Future object you get from calling them describes every single step these functions will do internally, not just what they'll return.
This means you can't put mixed types in a Vec, the same way you can't mix integers and strings.
You can use Box::pin(call_async_function()) to have dynamic dispatch that adds a layer of abstraction that makes all future types the same, and these can be put in a Vec.
Alternatively, you can use join!macro that generates type-specific code that waits for a number of futures.
futures::join! works but I wanted a vector because I don't know a priori how many futures I need. I've tried Box::pin and Box::new but both give the same opaque type error. Probably I'm doing something wrong?
let futures = vec![
Box::pin(get_blobs_from_data(pool, &blobs)),
Box::pin(get_blobs_from_table(pool, &blobs, "TestTable")),
];
You need to cast the pinned box to a trait object, because you want Pin<Box<dyn Future>> not Pin<Box<SomeOpaqueFutureType>>.
let futures = vec![
Box::pin(get_blobs_from_data(pool, &blobs)) as Pin<Box<dyn Future<Output = Foo>>>,
// casting the first is enough. The second will be converted due to
// type inference.
Box::pin(get_blobs_from_table(pool, &blobs, "TestTable")),
];