rust

Why does Rust complain "borrowed value does not live long enough" when returning an async future from a method?


I'm trying to return an async future from a method on a struct that implements a trait. Here's a simplified version of my Rust code:

use std::future::Future;

fn main() {}

fn sleep() -> impl Future + 'static {
    let scheduler = Tokio;
    scheduler.sleep()
}

trait Scheduler {
    fn sleep<'a>(&'a self) -> impl Future + 'static;
}

struct Tokio;

impl Scheduler for Tokio {
    fn sleep<'a>(&'a self) -> impl Future + 'static {
        async {}
    }
}

This fails to compile with the following error:

error[E0597]: `scheduler` does not live long enough
 --> src/main.rs:5:5
  |
4 |     let scheduler = Tokio;
  |         --------- binding `scheduler` declared here
5 |     scheduler.sleep()
  |     ^^^^^^^^^--------
  |     |
  |     borrowed value does not live long enough
  |     argument requires that `scheduler` is borrowed for `'static`
6 | }
  | - `scheduler` dropped here while still borrowed

I don't understand why this happens. The future returned from sleep() is 'static, and scheduler is just a local variable. But Rust says it's borrowed for 'static.

How can I fix this? My goal is for sleep() to return a future that's 'static so it can be spawned or used elsewhere.


Solution

  • impl Trait always captures all lifetime (and type) parameters in scope. Saying + 'static doesn't help, unfortunately.

    The real fix will be to use the use<> syntax, which was created precisely for this:

    trait Scheduler {
        fn sleep<'a>(&'a self) -> impl Future + use<Self>;
    }
    
    struct Tokio;
    
    impl Scheduler for Tokio {
        fn sleep<'a>(&'a self) -> impl Future + use<> {
            async {}
        }
    }