How to fix: cannot infer an appropriate lifetime f

2019-02-18 00:22发布

问题:

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

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.

回答1:

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



标签: rust lifetime