Can anyone help me out with opaque type

Can you help me out with opaquer & future issue.

Here is the code

Unable to understand what is wrong.
Thank you

One problem is that the functions/callbacks f1, f2 do not implement Fn(usize). They would if they were declared as regular fn, but since they are async fn their actual return types are anonymous futures—nameless types that implement Future<Output = ()>, because async fn f(args: Args) -> Ret { /* body */ } expands to[1]

fn f(args: Args) -> impl Future<Output = Ret> {
    async { /* body */ }
}

This means that f1 cannot be coerced to dyn Fn(usize), not even behind an indirection. To store type-erased async callbacks in a Vec, you'll need to erase the return types too, like this:

use futures::future::BoxFuture;

struct Store {
    callbacks: Vec<Box<dyn Fn(usize) -> BoxFuture<'static, ()> + Send + Sync + 'static>>,
}

impl Store {
    fn add<Fut, F>(&mut self, cb: F)
    where
        Fut: Future<Output = ()> + Send + 'static,
        F: Fn(usize) -> Fut + Send + Sync + 'static,
    {
        self.callbacks.push(Box::new(move |x| Box::pin(cb(x))));
    }
}

async fn f1(u: usize) {
    println!("Hello {}", u);
}

fn main() {
    let mut store = Store { callbacks: Vec::new() };
    store.add(f1);
}

With that changed, it's straightforward to make your Store::run code work. Note that you don't need to wrap the callbacks in Arc<Mutex<...>> unless you plan to clone the Store and you're actually using FnMut callbacks rather than Fn as in your playground. If you don't need to clone the Store, Box<...> is enough[2], and if you do need to clone the Store but don't need FnMut, then Arc<...> is enough. Working playground.


  1. well, almost: the compiler-generated "expansion" also includes information about what auto traits and lifetime bounds are satisfied by the returned Future ↩︎

  2. or Mutex<Box<...>> if you have FnMut callbacks but need Store::run to take &self rather than &mut self, though in this situation you might also consider using a Mutex<Vec<...>> to collect the callbacks and plain Box<...> for each individual callback ↩︎

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.