Heya, I'm trying to implement a generic async function, which delegates to a passed in subfunction that returns a future. The minimal generic function looks like this (playground):
async fn generic_fn<'f, T, F, Fut>(n: &'f u16, f: F) -> Result<(), AppErr>
where
for<'func> F: FnOnce(&'func Ctx<'f>) -> Fut,
Fut: Future<Output = Result<T, AppErr>>,
T: std::fmt::Display,
{
let ctx = Ctx(n);
let t = f(&ctx).await?;
println!("{t}");
Ok(())
}
so that it can be used like this:
generic_fn(&1, specific_fun_1).await?;
generic_fn(&2, specific_fun_2).await?;
async fn specific_fun_1(ctx: &Ctx<'_>) -> Result<u32, AppErr> {
Ok(u32::from(*ctx.0))
}
async fn specific_fun_2(ctx: &Ctx<'_>) -> Result<u64, AppErr> {
Ok(u64::from(*ctx.0))
}
Error in the minimal example
error[E0308]: mismatched types
--> src/main.rs:14:5
|
14 | generic_fn(&1, specific_fun_1).await?;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected opaque type `impl for<'func> Future<Output = Result<u32, Box<(dyn std::error::Error + 'static)>>>`
found opaque type `impl Future<Output = Result<u32, Box<(dyn std::error::Error + 'static)>>>`
= help: consider `await`ing on both `Future`s
= note: distinct uses of `impl Trait` result in different opaque types
note: the lifetime requirement is introduced here
--> src/main.rs:24:45
|
24 | for<'func> F: FnOnce(&'func Ctx<'f>) -> Fut,
| ^^^
Is there a way to tell Rust that Fut
should be constrained by the 'func
lifetime?
In the real code I actually get something less helpful, but I think solving the minimal example would help:
error: higher-ranked lifetime error
--> examples/app_cycle/src/cmds/env_status_cmd.rs:22:9
|
22 | EnvCmd::run(output, StatesSavedReadCmd::exec).await
| ^^^^^^^^^^^