Shared futures and compiler errors

Hi,

I have a set of async tasks where some of them depend on each other, and critically many of them may depend on the same ones. I.e. effectively I have a sort of DAG.

However, to keep the code simple I though I'd avoid having to spell all of that out in code, simply having a common struct 'Calculator' that has a lot of fields, each representing a "maybe finsihed" "maybe pending" future. In that way they can await each other and I can write "linear code" for the logic.

I have found futures::Shared that seems to support that particular usecase (though the types becomes very verbose) - but I'm struggling to get it to even compile.

Any pointers to help me understand the compiler error message for the following minified example (and what to do about it) would be apprechiated.

Rust Playground (rust-lang.org)

Regards

error[E0308]: mismatched types
  --> src/main.rs:16:5
   |
7  | fn resolve() -> Shared<Pin<Box<dyn Future<Output = std::result::Result<String, String>>>>> {
   |                 -------------------------------------------------------------------------- expected `Shared<Pin<Box<(dyn futures::Future<Output = Result<String, String>> + 'static)>>>` because of return type
...
16 |     jh.boxed().shared()
   |     ^^^^^^^^^^^^^^^^^^^ expected trait `futures::Future<Output = Result<String, String>>`, found trait `futures::Future<Output = Result<_, String>> + std::marker::Send`
   |
   = note: expected struct `Shared<Pin<Box<(dyn futures::Future<Output = Result<String, String>> + 'static)>>>`
              found struct `Shared<Pin<Box<dyn futures::Future<Output = Result<_, String>> + std::marker::Send>>>`
-Shared<Pin<Box<dyn Future<...
+Shared<Pin<Box<dyn Send + Future<...

According to the error, the Send bound is missing. https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=2c92f9e7de84ef528b479432ac45bbc4

I recommend using the futures::BoxFuture alias instead of Pin<Box<dyn Future...

3 Likes

Thank you! The error miselad me since it said that it "found" something that was send.

jh.boxed().shared() returns the Future with Send bound which derives from the async block and .boxed(). So the compile found it and reported that. But your return type didn't carry the bound, thus the error.

Also note that though dyn Trait + Send can coerce to dyn Trait, it doesn't happen in nested contexts:

BoxFuture in futures::future - Rust can help. Rust Playground

-Shared<Pin<Box<dyn Send + Future<Output = Result<String, String>>>>> 
+Shared<BoxFuture<'static, Result<String, String>>>