Hi,
I'm trying to understand the compiler errors I'm getting when trying to store an async function callback in a struct.
In some cases, I'm getting an error of type "one type is more general than the other", and can't find a workaround.
Here's a simplified example (Rust Playground):
async fn test(arg: &u32) {
println!("test {}", arg);
}
struct AsyncFn<F>
{
func: F,
}
impl<F, AsyncResult> AsyncFn<F>
where
F: FnMut(&u32) -> AsyncResult,
AsyncResult: std::future::Future,
{
fn new(func: F) -> Self {
Self {
func,
}
}
}
fn main() {
let mut async_fn = AsyncFn::new(test);
}
which generates the following error:
error[E0308]: mismatched types
--> src/lib.rs:23:24
|
23 | let mut async_fn = AsyncFn::new(test);
| ^^^^^^^^^^^^ one type is more general than the other
|
= note: expected associated type `<for<'_> fn(&u32) -> impl for<'_> Future {test} as FnOnce<(&u32,)>>::Output`
found associated type `<for<'_> fn(&u32) -> impl for<'_> Future {test} as FnOnce<(&u32,)>>::Output`
I think it's related to the lifetime of the Future, as it relates to the argument passed in...
I tried adding HRTBs to the FnMut constraint, but it didn't change anything... maybe I did it wrong?
What I find confusing, is that if I remove the reference on the u32 argument (and change the FnMut signature accordingly), then the code compiles without errors (playground).
p.s. I'm able to write a working version of this code by introducing another generic type argument (playground), but this approach doesn't work in my actual use-case, so I would really like to find a fix that keeps the FnMut signature as close as possible to the initial example.