Async function `Send` bound not satisfied while I think it should

#![feature(generic_associated_types)]

trait Foo<'ctx, 'env> {
    type X: Send + Sync + 'env
    where
        'env: 'ctx;
}

fn foo<'ctx, 'env: 'ctx, T: Foo<'ctx, 'env>>(x: T::X) -> impl Send + 'env + 'ctx {
    async move {
        let x = x;  // x has type T::X which is Send + Sync
        std::future::ready(()).await;  // remove this line then it compiles ok.
    }
}

I think it's a bug and filed a issue. But got no reply for really long time.

1 Like

In case it helps anyone, the foo function desugars to HIR equivalent to this:

#![feature(generators)]
#![feature(generic_associated_types)]
#![feature(gen_future)]

use std::{
    future::{self, Future, ResumeTy},
    pin::Pin,
    task::Poll,
};

fn foo<'ctx, 'env: 'ctx, T: Foo<'ctx, 'env>>(x: T::X) -> impl Send + 'env + 'ctx {
    future::from_generator(|mut gen_cx: ResumeTy| {
        let _x = x;
        let mut pinned = future::ready(());
        loop {
            let pin = unsafe { Pin::new_unchecked(&mut pinned) };
            let cx = unsafe { future::get_context(gen_cx) };
            match pin.poll(cx) {
                Poll::Ready(result) => break result,
                Poll::Pending => {}
            }
            gen_cx = yield ();
        }
    })
}

And it can be further reduced to this; it seems that the generated Generator type isn't Send, even though x is:

#![feature(generators)]
#![feature(generic_associated_types)]

fn foo<'ctx, 'env: 'ctx, T: Foo<'ctx, 'env>>(x: T::X) {
    fn assert_send<T: Send + ?Sized>(_: &T) {}
    assert_send(&x);
    let gen = || {
        let _x = x;
        yield ()
    };
    //assert_send(&gen);
    //error[E0478]: lifetime bound not satisfied
}
1 Like

Also, I've found an even clearer example of this issue with 'static:

#![feature(generators)]
#![feature(generic_associated_types)]

pub trait Trait<'a> {
    type Type: Send
    where
        'a: 'static;
}

pub fn foo<T: Trait<'static>>(x: <T as Trait<'static>>::Type) {
    fn assert_send<T: Send + ?Sized>(_: &T) {}
    assert_send(&x);
    let _gen = || {
        let _x = x;
        yield
    };
    //assert_send(&_gen);
    // error[E0478]: lifetime bound not satisfied
    // note: but lifetime parameter must outlive the static lifetime
}

The partial note in the error message could point to something weird happening between the generator type (created only in the MIR) and the associated diagnostics.

1 Like

Even simpler example, which I think should be the same issue.

#![feature(generators)]

use std::marker::PhantomData;
pub struct T<'a>(PhantomData<*mut &'a ()>);
unsafe impl Send for T<'static> {}

pub fn foo(x: T<'static>) {
    fn assert_send<T: Send + ?Sized>(_: &T) {}
    assert_send(&x);

    let _gen = move || {
        let _x = x;
        yield
    };
    assert_send(&_gen);
    // error: implementation of `Send` is not general enough
    // note: `T<'0>` must implement `Send`, for any lifetime `'0`...
    // note: ...but `Send` is actually implemented for the type `T<'static>`
}

Seems it's related to this issue.

1 Like