The following code (playground) fails to compile:
async fn wrapper<F, Fut>(func: F)
where
F: FnOnce(&i32) -> Fut,
Fut: Future<Output = ()>,
{
let i = 5;
func(&i).await;
}
async fn myfunc(_: &i32) {}
fn main() {
wrapper(myfunc);
}
The error message is:
error: implementation of `std::ops::FnOnce` is not general enough
--> src/main.rs:15:5
|
15 | wrapper(myfunc);
| ^^^^^^^ implementation of `std::ops::FnOnce` is not general enough
|
= note: `std::ops::FnOnce<(&'0 i32,)>` would have to be implemented for the type `for<'_> fn(&i32) -> impl std::future::Future {myfunc}`, for some specific lifetime `'0`...
= note: ...but `std::ops::FnOnce<(&i32,)>` is actually implemented for the type `for<'_> fn(&i32) -> impl std::future::Future {myfunc}`
I have found a few similar items that mention Higher-Ranked Trait bounds (e.g. this Rust issue and this one), and tried experimenting with for<'a> and additional lifetime bounds, but the error is still not clear to me.
I don't understand why the compiler can't determine the lifetimes, especially since a simpler version without futures compiles just fine:
fn myfunc(_: &i32) {}
fn wrapper<F: FnOnce(&i32)>(func: F) {
let i = 5;
func(&i);
}
fn main() {
wrapper(myfunc);
}
What is the actual problem here? Is there a workaround that can make this compile, e.g. with additional bounds?