Help needed with higher-ranked lifetime errors

Hi, I'm implementing a proxy handlers chain with both hudsucker and axum. Getting three similar lifetime errors:

error: higher-ranked lifetime error
   --> src/proxy/chain.rs:89:9
    |
89  | /         async move {
90  | |             match chain.process_request(request).await {
91  | |                 Ok(HttpResult::Request(request)) => RequestOrResponse::Request(request),
92  | |                 Ok(HttpResult::Response(response)) => RequestOrResponse::Response(response),
93  | |                 Err(_) => RequestOrResponse::Response(Response::new(ForwardBody::empty())),
94  | |             }
95  | |         }
    | |_________^

error: higher-ranked lifetime error
   --> src/proxy/chain.rs:104:9
    |
104 | /         async move {
105 | |             chain.process_response(response).await.unwrap_or_else(|_| Response::new(ForwardBody::empty()))
106 | |         }
    | |_________^

error: higher-ranked lifetime error
   --> src/proxy/chain.rs:116:9
    |
116 | /         Box::pin(async move {
117 | |             let response = match chain.process_request(request).await {
118 | |                 Ok(HttpResult::Request(request)) => match client.request(request).await {
119 | |                     Ok(response) => response.into_response(),
...   |
126 | |             chain.process_response(response).await.unwrap_or_else(|_| Response::new(ReverseBody::empty()))
127 | |         })
    | |__________^
    |
    = note: could not prove `Pin<Box<{async block@src/proxy/chain.rs:116:18: 116:28}>>: CoerceUnsized<Pin<Box<(dyn futures::Future<Output = http::Response<axum::body::Body>> + std::marker::Send + 'b)>>>`

The errors occur in both hudsucker::HttpHandler and axum::handler::Handler implementations for my Chain type.

Here is my project: GitHub - airycanon/higher-ranked-lifetime-demo

How can I properly implement both handler traits? Thanks for any help!

1 Like

Crosspost https://www.reddit.com/r/rust/comments/1ikj2lf/help_needed_with_higherranked_lifetime_errors/.

Hi @airycanon ,

The error is a bit cryptic. I believe the problem lies in your Chain::process_request and Chain::process_response functions.

To elicit a slightly clearer error message, I first tested if the future in ForwardChain::handle_request was Send:

fn handle_request(&mut self, _ctx: &HttpContext, request: Request<ForwardBody>) -> impl Future<Output = RequestOrResponse> + Send {
        fn is_send<T: Send>(x: T) -> T { x }                                                                                                                                                                                                                                             

        let r = async move {
            // Async block contents...
        };

        is_send(r)
    }

This leads to the error:

could not prove {async block@src/proxy/chain.rs:92:17: 92:27}: std::marker::Send.

The culprit is Chain::process_request (the only await point in our async block). If we modify the method from:

async fn process_request(&self, request: Request<B>) -> Result<HttpResult<B>> {
   /// Function body...
}

...to:

fn process_request(&self, request: Request<B>) -> impl Future<Output = Result<HttpResult<B>>> + Send + '_ {
        async move {
           // Function body...
   }
}

The error is gone! Do the same for Chain::process_response and your project compiles. Oddly, clippy suggests going back to the previous version, that causes the compile errors...

3 Likes