Hi all,
I'm new to learning Rust and I'm having some issues writing a future factory.
I'm trying to create a future factory that will store the last created future for it to be able to be polled. For this, I'm not able to use dynamic dispatch due to requirements; though, I've previously had a working solution using it. The general flow of what I'm trying to do is:
- Initialise the future factory with some provided arguments that it uses to create new futures.
- When required, poll the factory's latest future
3.1. If the future returns OK, then finish.
3.2. If it fails, create a new future and set the factory's latest to this instance. Outside of what I've posted here, it will do some other work to retry it in a different way.
Calling the factory to create a new instance if the future fails is done externally to all of this and that system is working fine with the dynamic dispatch approach. The problem that I'm having here is doing this without dynamic dispatch - the reason for this is that it's a super hot area in the code.
enum FutureError {}
#[pin_project]
pub struct Factory<F, Func> {
func: Func,
#[pin]
s: Wrapper<F>,
}
impl<F, Func> Future for Factory<F, Func>
where F: Future<Output=Result<(), FutureError>>
{
type Output = Result<(), FutureError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.project().s.poll(cx)
}
}
impl<F> Future for Wrapper<F>
where F: Future<Output=Result<(), FutureError>>
{
type Output = Result<(), FutureError>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
self.project().fut.poll(cx)
}
}
#[pin_project]
pub struct Wrapper<F> {
#[pin]
fut: F,
}
impl<F> Wrapper<F> {
pub fn new(f: F) -> Self {
Wrapper { fut: f }
}
}
impl<F, Func> Factory<F, Func>
where
F: Future<Output=Result<(), FutureError>>,
Func: Fn() -> F,
{
pub fn wrap() -> Factory<F, Func> {
let func = || get_future();
let f = func();
Factory {
func,
s: Wrapper::new(f),
}
}
}
async fn get_future() -> Result<(), FutureError> {
// Dore more interesting stuff but that's not important
Ok(())
}
The error that I'm receiving with my last iteration on this is:
error[E0308]: mismatched types
--> src/second.rs:49:13
|
39 | impl<F, Func> Factory<F, Func>
| ---- this type parameter
...
45 | let func = || get_future();
| --------------- the found closure
...
49 | func,
| ^^^^ expected type parameter `Func`, found closure
...
55 | async fn get_future() -> Result<(),FutureError> {
| ---------------------- the `Output` of this `async fn`'s found opaque type
|
= note: expected type parameter `Func`
found closure `[closure@src/second.rs:45:20: 45:35]`
I've tried using fn
, Fn
s and other versions but I cannot see a solution to this. This last iteration is only using Fn
s are I thought I got close to a solution. I'm not sure how to do it with or without them!
Any help would be greatly appreciated!