Search code examples
ruststaticborrow-checkerobject-lifetimerust-warp

What to do if an external crate requires static lifetime explicitly?


I'm using seanmonstar/warp to build my rest service and faced the problem related to lifetimes. Here is how my application starting code looks like:

struct MyModelStruct {
    //...
}

struct Database {
    //...
}

impl Database {
    fn connect(/* ommited */) -> Database {
        //...
    }
}

fn start_app(db: &Database) -> () {
    let route = warp::post()
        .and(warp::path!("action" / u32))
        .and(warp::body::json::<MyModelSctruct>())
        .map(|_, _| {
             //use db
        })
    warp::serve(route).run(/* address */);
}

I got the error:

error[E0621]: explicit lifetime required in the type of `db`
  --> src/application.rs:69:5
   |
46 | fn start_app(db: &Database) -> (){
   |                         -------- help: add explicit lifetime `'static` to the type of `db`: `&'static db::Database`
...
69 |     warp::serve(route);
   |     ^^^^^^^^^^^ lifetime `'static` required

This is because the warp::serve function is defined as

/// Create a `Server` with the provided `Filter`.
pub fn serve<F>(filter: F) -> Server<F>
where
    F: Filter + Clone + Send + Sync + 'static,
    F::Extract: Reply,
    F::Error: IsReject,
{
    Server {
        pipeline: false,
        filter,
    }
}

So the 'static lifetime is required explicitly. The problem is it is used as

let db = Database::connect(...);
start_app(&db);

So the lifetime of db is not static. Is there a way to workaround this?


Solution

  • A 'static lifetime means that the function is guaranteed to not reference any data that could be dropped before the function itself is dropped. Because you are currently passing in a &Database, your function cannot be 'static (unless you were somehow passing a &'static Database, which would require explicitly creating a memory leak).

    The only way around this would be for you to either pass Database or Arc<Database> or something along that would allow access so that the function has a strong reference to the Database and can guarantee that the DB will continue to exist as long as the function does.