0

I want to do the following

struct Stored<F: Future<Output = ()>> {
    f: Option<F>,
}

impl<F: Future<Output = ()>> Stored<F> {
    fn store(&mut self, f: F) {
        let f = async {};
        self.f = Some(f);
    }
}

But it gives me the error:

expected type parameter `F`
      found opaque type `impl futures::Future<Output = ()>`
type parameters must be constrained to match other types

I could solve it boxing the future, but if the method store was the only place I stored this future, there would be no need to do that, because all the future blocks would be always the same type. How could I do it?

Gabriel Machado
  • 401
  • 3
  • 14

1 Answers1

1

This doesn't work because F is a generic type provided from outside of the Stored type, but the actual type of the future is an unnamed type provided from within the store associated function (created by async {}). There is no possible way that F can be specified to be the correct type.

The way this is usually handled is to create a dedicated, nameable type implementing Future. In this trivial case, that could be std::future::Ready<()>:

struct Stored {
    f: Option<std::future::Ready<()>>,
}

impl Stored {
    fn store(&mut self) {
        self.f = Some(std::future::ready(()));
    }
}

If the type of the future actually does come from outside of the type, then you just need to adjust your code to use f directly instead of discarding it and using async {}:

use std::future::Future;

struct Stored<F> {
    f: Option<F>,
}

impl<F: Future> Stored<F> {
    fn store(&mut self, f: F) {
        self.f = Some(f);
    }
}
cdhowie
  • 158,093
  • 24
  • 286
  • 300