Overflow evaluating the requirement with Closures

Hello,

I defined a trait RequestHandlerFn which is an extension of Fn. I had to do this to implement clone for the Struct that holds a variable of dyn trait attached below (Followed some of the posts from this forum and other Rust blogs - not sure if this is the ideal approach but it worked).

pub type RequestFuture = Pin<Box<dyn Future<Output = Result<Response<Body>, Infallible>> + Send>>;

// define a trait that extends Fn(Request<Body>) -> RequestFuture + Send
pub trait RequestHandlerFn: Fn(Request<Body>) -> RequestFuture + Send + Sync {
    // implement clone box for the trait
    fn clone_box(&self) -> Box<dyn RequestHandlerFn>;
}

My struct and the function to generate struct object looks something like below

pub struct RequestHandler {
    callback: Box<dyn RequestHandlerFn>,
}

// define service fn that takes RequestHandlerFn and returns RequestHandler
pub fn RequestHandler_fn(callback: Box<dyn RequestHandlerFn>) -> RequestHandler
{
    RequestHandler::new(callback)
}

Tried calling the RequestHandler_fn like below

let x = http_handler_service::RequestHandler_fn(Box::new(|_req|Box::pin(async {
    Ok(Response::new(Body::from("Hello World!"))
})));

But running into following compiler error

error[E0275]: overflow evaluating the requirement `[closure@src/main.rs:15:62: 15:68]: RequestHandlerFn`
  --> src/main.rs:15:53
   |
15 |       let x = http_handler_service::RequestHandler_fn(Box::new(|_req|Box::pin(async {
   |  _____________________________________________________^
16 | |         Ok(Response::new(Body::from("Hello World!"))
17 | |     })));
   | |_______^
   |
   = note: required for the cast from `[closure@src/main.rs:15:62: 15:68]` to the object type `dyn RequestHandlerFn<Output = Pin<Box<(dyn Future<Output = Result<Response<Body>, Infallible>> + Send + 'static)>>>`

Guessing, it's because of the async closure I have passed to RequestHandler_fn doesn't help compiler to resolve full future type as "Result<Response, Infallible>>" or I might be wrong. Can someone help what I am doing wrong and how I can fix this??

Thanks!!

your trait is defined as a sub-trait of Fn, a closure implelements the said Fn, but doesn't automatically implement the sub-trait. try add a blanket implementation of your trait for types that implement the Fn trait.

impl <F: Fn(Request<Body>) -> RequestFuture + Send + Sync + Clone + 'static> RequestHandlerFn for F {
    fn clone_box(&self) -> Box<dyn RequestHandlerFn> {
        Box::new(self.clone())
    }
}

then it is ok to do this:

    let handler: Box<dyn RequestHandlerFn> = Box::new(|_req| Box::pin(async {
        Ok(Response::new(todo!()))
    }));
3 Likes

@nerditation Thanks, this make sense.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.