Hi, I'm trying to implement a HTTP router and register an async function to HashMap, but it doesn't work. This is a minimal reproduction. I may be wrong in my understanding of async function and future to begin with, but can anyone help me with how to solve this?
use core::future::Future;
use core::pin::Pin;
use std::error::Error;
use std::collections::HashMap;
pub trait Handler<Req, E> {
fn call(&self, req: Req) -> Pin<Box<dyn Future<Output = Result<(), E>> + Send + Sync>>;
}
impl<F: Send + Sync + 'static, Ret, Req, E> Handler<Req, E> for F
where
F: Fn(Req) -> Ret + Send + Sync + 'static,
Ret: Future<Output = Result<(), E>> + Send + Sync + 'static,
E: Into<Box<dyn Error + Send + Sync>>,
{
fn call(
&self,
req: Req,
) -> Pin<Box<dyn Future<Output = Result<(), E>> + Send + Sync>> {
Box::pin(self(req))
}
}
struct Map<Req, E: Into<Box<dyn Error + Send + Sync>> + 'static> {
inner: HashMap<String, Box<dyn Handler<Req, E>>>,
}
impl<Req, E: Into<Box<dyn Error + Send + Sync>> + 'static> Map<Req, E> {
fn add<H>(&mut self, k: String, h: H)
where
H: Fn(Req) -> Pin<Box<dyn Future<Output = Result<(), E>> + Send + Sync>>
+ Send
+ Sync
+ 'static,
{
self.inner.insert(k, Box::new(h));
}
}
fn main() {
let mut map = Map { inner: HashMap::new() };
map.add("/index".to_string(), index);
}
async fn index(_: String) -> Result<(), std::convert::Infallible>{
Ok(())
}
Compiling playground v0.0.1 (/playground)
error[E0271]: type mismatch resolving `<fn(String) -> impl Future {index} as FnOnce<(String,)>>::Output == Pin<Box<(dyn Future<Output = Result<(), _>> + Send + Sync + 'static)>>`
--> src/main.rs:42:9
|
42 | map.add("/index".to_string(), index);
| ^^^ expected opaque type, found struct `Pin`
...
45 | async fn index(_: String) -> Result<(), std::convert::Infallible>{
| ------------------------------------ checked the `Output` of this `async fn`, expected opaque type
|
= note: while checking the return type of the `async fn`
= note: expected opaque type `impl Future`
found struct `Pin<Box<(dyn Future<Output = Result<(), _>> + Send + Sync + 'static)>>`
error: aborting due to previous error
For more information about this error, try `rustc --explain E0271`.
error: could not compile `playground`
To learn more, run the command again with --verbose.