How to fix: expected concrete lifetime, but found

2020-05-01 08:41发布

I'm currently pulling my hear out over this one. I tried to shrink it down to a minimal reproducible example.

struct Request;

struct ResponseWriter<'a> { 
    dummy: &'a () 
}

#[deriving(Clone)]
pub struct RouteStore{
    pub routes: Vec<Route>,
}

#[deriving(Clone)]
struct Route {
    path: String,
    handler: fn(request: &Request, response: &mut ResponseWriter)
}

impl RouteStore {
    pub fn new () -> RouteStore {
        RouteStore {
            routes: Vec::new()
        }
    }

    fn add_route (&mut self, path: String, handler: fn(request: &Request, response: &mut ResponseWriter)) -> () {
        let route = Route {
            path: path,
            handler: handler
        };
        self.routes.push(route);
    }
}

fn main () {

}

This leaves me with:

error: mismatched types: expected `fn(&http::server::request::Request, &mut http::server::response::ResponseWriter<>)` but found `fn(&http::server::request::Request, &mut http::server::response::ResponseWriter<>)` (expected concrete lifetime, but found bound lifetime parameter )
src/so.rs:12     handler: fn(request: &Request, response: &mut ResponseWriter)
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

enter image description here

Previously I stored my fn in a HashMap like this HashMap<String, fn(request: &Request, response: &mut ResponseWriter)>. This worked fine.

But now I want to refactor things a bit and introduced a Route struct and store things as Vec<Route>. But suddenly hell breaks loose and I don't know how to fix it :-/

For the curious ones, this is part of my effort to write an expressjs inspired web framework for Rust called Floor

标签: rust lifetime
1条回答
成全新的幸福
2楼-- · 2020-05-01 08:57

After making your example a bit more minimal (getting rid of the http dependency), and some suggestions on IRC (namely someone pointing out that the problem goes away if you remove the deriving(Clone) from the Route), you can see a fixed version below (--cfg v2)

#[deriving(Clone)]
pub struct RouteStore{
    pub routes: Vec<Route>,
}

#[cfg(v1)]
#[deriving(Clone)]
struct Route {
    path: String,
    handler: fn(response: &mut ())
}

#[cfg(v2)]
struct Route {
    path: String,
    handler: fn(response: &mut ())
}

#[cfg(v2)]
impl Clone for Route {
    fn clone(&self) -> Route {
        Route { path: self.path.clone(), handler: self.handler }
    }
}
impl RouteStore {
    pub fn new () -> RouteStore {
        RouteStore {
            routes: Vec::new()
        }
    }

    fn add_route (&mut self, path: String, handler: fn(response: &mut ())) -> () {
        let route = Route {
            path: path,
            handler: handler
        };
        self.routes.push(route);
    }
}

fn main () {

}

The issue here is that an fn does not implement Clone. (edit: Well, it does have a clone method, but the returned value does not seem compatible with what that field needs. The v2 version above just side-steps the whole issue.)

So I suspect the error you are seeing is coming from the auto-generated clone implementation that deriving(Clone) injects.

查看更多
登录 后发表回答