BoxFuture vs impl Future & lifetime

Compiling the following code (playground fails:

use std::future::Future;
use std::pin::Pin;

pub type BoxFuture<'a, T> = Pin<Box<dyn Future<Output = T> + Send + 'a>>;

#[derive(Clone)]
struct A;

trait I {
    fn foo(&self, a: &A) -> BoxFuture<'static, ()>;
    fn bar(&self, a: &A) -> impl 'static + Future<Output = ()> + Send;
}

impl I for () {
    fn foo(&self, _a: &A) -> BoxFuture<'static, ()> {
        Box::pin(async move {})
    }

    fn bar(&self, _a: &A) -> impl 'static + Future<Output = ()> + Send {
        async move {}
    }
}

fn baz<F, FR>(_f: F)
where
    F: Fn(&A) -> FR,
    FR: 'static + Future<Output = ()> + Send,
{
}

fn main() {
    baz(|a| ().foo(a)); //OK
    baz(|a| ().bar(a)); //lifetime error
}

It gives the error:

error: lifetime may not live long enough
  --> src/main.rs:33:13
   |
33 |     baz(|a| ().bar(a));
   |          -- ^^^^^^^^^ returning this value requires that `'1` must outlive `'2`
   |          ||
   |          |return type of closure `impl Future<Output = ()> + Send + 'static` contains a lifetime `'2`
   |          has type `&'1 A`

which does't make sense to me, since both foo() and bar() have 'static return types.
Does anyone have an explanation?

It's overcapturing in RPIT(IT). Solution by TAIT.
Also see full replies for this thread for more discussions/contexts that may help you.

3 Likes