Hello,
I'm struggling to pass async function/closure which accepts a parameter with a lifetime to other async function as a parameter. Please review a code snippet below. How to pass callback
to listen
?
use std::future::Future;
pub struct Response<'a> {
body: &'a mut [u8],
}
impl<'a> Response<'a> {
pub fn new(body: &'a mut [u8]) -> Self {
Self { body }
}
pub fn send(&self) {}
}
pub struct Server {}
impl Server {
pub async fn listen<F, T>(&self, cb: F)
where
F: Fn(Response) -> T,
T: Future<Output = ()>,
{
let mut buf = [0_u8, 8];
let response = Response::new(&mut buf);
cb(response).await;
}
}
async fn callback(res: Response<'_>) {
res.send();
}
#[async_std::main]
async fn main() {
let server = Server{};
server.listen(callback).await;
}
This code doesn't compile with mismatched types error:
error[E0308]: mismatched types
--> src/main.rs:35:5
|
35 | server.listen(callback);
| ^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected opaque type `impl for<'a> Future<Output = ()>`
found opaque type `impl Future<Output = ()>`
= 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:20:28
|
20 | F: Fn(Response) -> T,
| ^
If I pass a closure with async body instead then I get another error:
#[async_std::main]
async fn main() {
let server = Server{};
server.listen(|res| async {
res.send();
});
}
error: lifetime may not live long enough
--> src/main.rs:40:25
|
40 | server.listen(|res| async {
| ____________________----_^
| | | |
| | | return type of closure `[async block@src/main.rs:40:25: 42:6]` contains a lifetime `'2`
| | has type `Response<'1>`
41 | | res.send();
42 | | });
| |_____^ returning this value requires that `'1` must outlive `'2`
error[E0373]: async block may outlive the current function, but it borrows `res`, which is owned by the current function
--> src/main.rs:40:25
|
40 | server.listen(|res| async {
| _________________________^
41 | | res.send();
| | --- `res` is borrowed here
42 | | });
| |_____^ may outlive borrowed value `res`
|
note: async block is returned here
--> src/main.rs:40:25
|
40 | server.listen(|res| async {
| _________________________^
41 | | res.send();
42 | | });
| |_____^
Playground without async_std
but the error is the same:
I understand that I should set up the lifetimes but I don't understand how to do this in terms of syntax. How can I specify the lifetimes for such case?