Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix: cannot infer an appropriate lifetime for automatic coercion

Tags:

rust

lifetime

I managed to run into a lifetime issue again that I seem to be unable to resolve on my own.

The compiler tells me cannot infer an appropriate lifetime for automatic coercion

enter image description here

I tried to follow the compilers suggestion and introduced the lifetime annotations in the handle_request method.

fn handle_request<'a>(&self, req: &Request, res: &'a mut ResponseWriter) {


    fn set_headers(req: &Request, res: &mut ResponseWriter) {
        //probably not important for the example 
    }

    match &req.request_uri {
        &AbsolutePath(ref url) => {
            match self.router.match_route(req.method.clone(), url.clone()) {
                Some(route_result) => { 
                    set_headers(req, res); 

                    let floor_req = request::Request{
                        origin: req,
                        params: route_result.params.clone()
                    };

                    let floor_res = response::Response{
                        origin: res
                    };

                    (route_result.route.handler)(floor_req, &mut floor_res);
                },
                None => {}
            }
        },
        _ => set_headers(req, res)
    }
}

I had the code working before but now I wanted to wrap the http::server::ResponseWriter in my own Response struct. I did exactly the same for the Request before but in terms of lifetimes the case seems to be slightly different. Maybe because it's a &mut instead of just a simple & reference.

This is my ResponseWriter struct.

use http;

///A container for the response
pub struct Response<'a> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'a>,
}

Just incase any Samaritan wants to compile the code locally, I pushed it into the lifetime_crazyness branch here: https://github.com/cburgdorf/Floor/commits/lifetime_craziness

Just run make floor to compile it.

like image 235
Christoph Avatar asked Jun 18 '14 17:06

Christoph


1 Answers

OK, so I pulled down your code to try and compile it. Indeed, if we take a look at the definition of your Response struct, we see this:

pub struct Response<'a> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'a>,
}

From the compiler's perspective, this definition claims that the lifetime of the pointer to a http::server::ResponseWriter is the same as whatever lifetime is inside of http::server::ResponseWriter. I don't see any particular reason why this should be true, and it looks like the compiler can't either. So to fix it, you need to introduce another lifetime parameter so that you allow for the possibility that the lifetimes are distinct:

pub struct Response<'a, 'b> {
    ///the original `http::server::ResponseWriter`
    pub origin: &'a mut http::server::ResponseWriter<'b>,
}

Here's the fix in a PR for you: https://github.com/BurntSushi/Floor/commit/127962b9afc2779c9103c28f37e52e8d292f9ff2

like image 132
BurntSushi5 Avatar answered Sep 26 '22 11:09

BurntSushi5