I'm trying to implement a trait for async functions taking a reference. The compiler is happy when the async function is a closure, or a normal function with an async block, but won't accept the async fn declaration, with a mismatch in lifetimes; what's the difference here?
Playground: Rust Playground
Code:
use futures::Future;
use std::pin::Pin;
type ResponseFuture = dyn Future<Output = i32> + Send;
struct Foo;
trait Handler: Sync + Send {
fn handle(&self, context: &Foo) -> Pin<Box<ResponseFuture>>;
}
impl<F, U> Handler for F
where
F: Fn(&Foo) -> U + Send + Sync + 'static,
U: Future<Output = i32> + Send + 'static,
{
fn handle(&self, context: &Foo) -> Pin<Box<ResponseFuture>> {
Box::pin(self(context))
}
}
fn handle_root(ctx: &Foo) -> impl Future<Output=i32> {
async { 0 }
}
async fn handle_root2(ctx: &Foo) -> i32 {
0
}
fn main() {
let h: Box<dyn Handler> = Box::new(|ctx: &Foo| async { 0 });
let g: Box<dyn Handler> = Box::new(handle_root);
let f: Box<dyn Handler> = Box::new(handle_root2);
}
Error:
error[E0271]: type mismatch resolving `for<'r> <for<'_> fn(&Foo) -> impl core::future::future::Future {handle_root2} as std::ops::FnOnce<(&'r Foo,)>>::Output == _`
--> src/main.rs:32:31
|
32 | let f: Box<dyn Handler> = Box::new(handle_root2);
| ^^^^^^^^^^^^^^^^^^^^^^ expected bound lifetime parameter, found concrete lifetime
|
= note: required because of the requirements on the impl of `Handler` for `for<'_> fn(&Foo) -> impl core::future::future::Future {handle_root2}`
= note: required for the cast to the object type `dyn Handler`
In the type it gives, for<'r> <for<'_> fn(&Foo) -> impl core::future::future::Future {handle_root2}
, it seems what it wants is something like for<'r> <for<'a> fn(&'a Foo) -> impl core::future::future::Future {handle_root2}
- that is, for the parameter's lifetime to be bounded by the higher-rank trait bound?