4

I have this code:

.and_then(move |key: Option<String>| async {
    let pool = pool.clone();
    let key = key.as_ref().map(|s| &**s);

    match pool.get() {
        Ok(conn) => Ok(Session::from_key(conn, key)),
        Err(e) => {
            error!("Failed to get a db connection");
            Err(warp::reject::not_found())
        }
    }
})
.boxed()

Which I am adapting from this example

But it's giving me the error

lifetime may not live long enough

returning this value requires that `'1` must outlive `'2`

note: closure implements `Fn`, so references to captured variables can't escape the closurerustc
session.rs(131, 19): lifetime `'1` represents this closure's body
session.rs(131, 44): return type of closure is impl core::future::future::Future
session.rs(131, 46): returning this value requires that `'1` must outlive `'2`
async block may outlive the current function, but it borrows `key`, which is owned by the current function

may outlive borrowed value `key`rustc(E0373)
session.rs(131, 52): may outlive borrowed value `key`
session.rs(133, 23): `key` is borrowed here

I had to add the async keyword to the closure to avoid the error:

the trait bound `std::result::Result<session::Session, warp::reject::Rejection>: core::future::future::Future` is not satisfied

the trait `core::future::future::Future` is not implemented for `std::result::Result<session::Session, warp::reject::Rejection>`

note: required because of the requirements on the impl of `futures_core::future::TryFuture` for `std::result::Result<session::Session, warp::reject::Rejection>`rustc(E0277)
session.rs(138, 10): the trait `core::future::future::Future` is not implemented for `std::result::Result<session::Session, warp::reject::Rejection>`

So, now, it appears the closure is returning a feature, but the closure is deallocated, so it tries to deallocate the future before it is used...any ideas on how to remedy this?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
Zane Hitchcox
  • 936
  • 1
  • 9
  • 23

1 Answers1

0

The main thing to understand about this problem is that the parameter to this closure, key is passed by-value, String is an owned string. So when this closure is running, key is owned in the stackframe for this closure, and when the closure returns, this stack frame and everything in it gets drop()ed.

key.as_ref() produces a value which references the key in this stack frame, rustc doesn't let you return something from a function which references values owned by the function as they wont exist once the function returns, this is why the lifetime is limited to the function body.

To remedy this you have 2 options:

  1. Pass key by reference to this function key: Option<&str>, then the Session can be returned back up the stack until where the owned string was borrowed.
  2. Create the Session using the owned string, then the String is owned by the Session and can be passed around by value (moved) without any lifetime restrictions.
MikeB
  • 928
  • 9
  • 24