Hi,
I'm migrating to new futures - in couple of places in old solution I used trait objects (as different path of program returned future resolving to same results, but actually being of different type). And I hit interesting problem demonstrated by following code:
use futures::{future::{ready}, prelude::*};// 0.3.4
use tokio; // 0.2.11
#[tokio::main]
async fn main() {
let f: Box<dyn Future<Output=u32>> = Box::new(ready(1));
let f = f.map(|v| {
println!("Got value {}", v);
v+1
}
);
//Alternate approach
// let f = async {
// f.await + 1
// };
let x = f.await;
println!("DONE {:?}", x);
}
Code available also here.
Codefailed to compile with this error:
error: the `map` method cannot be invoked on a trait object
--> src/main.rs:8:15
|
8 | let f = f.map(|v| {
| ^^^
|
::: /playground/.cargo/registry/src/github.com-1ecc6299db9ec823/futures-util-0.3.4/src/future/future/mod.rs:111:15
|
111 | Self: Sized,
| ----- this has a `Sized` requirement
|
help: another candidate was found in the following trait, perhaps add a `use` for it:
|
1 | use futures_util::future::future::FutureExt;
|
I was quite confused by this error - FutureExt does have this Sized
requirement, but I thought that trait object is Sized?
Actually I've solved this problem (with help of alternate approach, which is commented in the code). It's enough to add Unpin to trait object definition like this:
let f: Box<dyn Future<Output=u32>+Unpin> = Box::new(ready(1));
But this still leaves me bit confused, so I have couple of questions:
-
How Unpin relates to Sized in this case?
-
I'm still bit struggling with Pin and Unpin in new futures. Is there some more detailed tutorial /explanation - I've read through pin module in std documentation - theoretically it loosk fine, but still have problem to apply it to practical cases.
-
Does this mean that is I'll have future which is not Unpin, I cannot use it in trait object because I'll not be able to use methods from FutureExt neither use await?
-
As I said I used future trait objects in my past project, with new futures is it still good option? Or is there something better ( and do not look at sample code, because it's simplified, in real code there are more complex cases - like match where each branch returns different futures) ?
Thanks a lot
Ivan