0
#[derive(Debug, Clone)]
struct Author<T: Persister + Send + Sync + Clone> {
    dao: T,
}

impl<T: Persister + Send + Sync + Clone> Author<T> {
    fn new(dao: T) -> Self {
        Author { dao: dao }
    }
    fn handle_sign_up<'r>(&self, request: &'r Request, data: Data) -> Outcome<'r> {
        Outcome::Success(Response::new())
    }
}

impl<T> Handler for Author<T>
where
    T: Persister + Send + Sync + Clone + 'static,
{
    fn handle<'r>(&self, request: &'r Request, data: Data) -> Outcome<'r> {
        Outcome::Success(Response::new())
    }
}

impl<T: Persister + Send + Sync + Clone + 'static> Into<Vec<Route>> for Author<T> {
    fn into(self) -> Vec<Route> {
        vec![Route::new(rocket::http::Method::Post, "/", self)]
    }
}

fn main() {
    let dao = Dao::new("mysql://user:password@localhost/test".to_owned()).unwrap();
    let author = Author::new(dao);
    rocket::ignite().mount("/", author).launch();
}

I want to use methods of Author(ex. Author::handle_sign_up) as handler for route, but it not works.I have tried to use clouser like below

impl<T: Persister + Send + Sync + Clone + 'static> Into<Vec<Route>> for Author<T> {
    fn into(self) -> Vec<Route> {
        let p = |req, data| self.handle_sign_up(req, data);
        vec![Route::new(rocket::http::Method::Post, "/", p)]
    }
}

, compiler reported an lifetime error

mismatched types expected type for<'r, 's> Fn<(&'r rocket::Request<'s>, rocket::Data)> found type Fn<(&rocket::Request<'_>, rocket::Data)>

Is there any way to implement it?

wangjun
  • 577
  • 1
  • 6
  • 14

1 Answers1

0

The problem with |req, data| self.handle_sign_up(req, data) is that the compiler will infer lifetimes for the arguments' types but gets it wrong here. The relationship between &'r Request and Outcome<'r> is required and lacking.

Unfortunately, you cannot explicitly annotate the lifetimes of a closure.

A workaround (as suggested by one of the answers in the link above) is to use a helper function, which doesn't do anything, but encourages the compiler to infer the correct signature:

fn as_handler_func<F>(f: F) -> F
where
    F: for<'r> Fn(&'r Request, Data) -> Outcome<'r>,
{
    f
}

impl<T: Send + Sync + Clone + 'static> Into<Vec<Route>> for Author<T> {
    fn into(self) -> Vec<Route> {
        let p = as_handler_fn(move |req, data| self.handle_sign_up(req, data));
        vec![Route::new(rocket::http::Method::Post, "/", p)]
    }
}

As a side note: I'm no expert in Rocket, but I believe if you implement Into<Vec<Route>> for Author like this, you probably don't want to impl Handler for it as well.

kmdreko
  • 42,554
  • 6
  • 57
  • 106