I'd like to write a function which takes one argument: a pointer to an async function taking a lifetime parameter.
Here's a minimal example:
use std::future::Future;
async fn takes_i32_ref<'a>(r: &'a i32) { }
fn takes_fn<F: Future>(f: for<'a> fn(&'a i32) -> F) { }
fn main() {
takes_fn(takes_i32_ref);
}
When I try to run this I get the message:
error[E0308]: mismatched types
--> src/main.rs:8:14
|
8 | takes_fn(takes_i32_ref);
| -------- ^^^^^^^^^^^^^ one type is more general than the other
| |
| arguments to this function are incorrect
|
= note: expected fn pointer `for<'a> fn(&'a i32) -> _`
found fn item `for<'a> fn(&'a i32) -> impl for<'a> Future<Output = ()> {takes_i32_ref}`
note: function defined here
--> src/main.rs:5:4
|
5 | fn takes_fn<F: Future>(f: for<'a> fn(&'a i32) -> F) { }
| ^^^^^^^^ ---------------------------
I found a question that seemed pretty related: Why isn't `std::mem::drop` exactly the same as the closure |_|() in higher-ranked trait bounds?
I think that question is different from mine though. In that question, a for<'a> FnOnce<(&'a &str,)>
is expected and a FnOnce<(&&str,)>
is provided. The provided type is less general than the expected type because it lacks a for
.
However, my example says that a for<'a> fn(&'a i32) -> _
is expected and a for<'a> fn(&'a i32) -> impl for<'a> Future<Output = ()> {takes_i32_ref}
is provided. The provided type is more general than the expected type because it has a for
.
Why can't Rust do this coercion?
Edit: I should also add that this error doesn't appear when I get rid of the reference in the signature of takes_i32_ref
and f
. That the async function takes a parameter with a lifetime seems to be important.