Repository: rust
Issue: Problem with GATs, async, and Send-bounds
Labels: A-lifetimes,A-trait-system,A-associated-items,T-compiler,A-async-await,AsyncAwait-Triaged,requires-nightly,GATs-triaged,A-GATs

I have experienced problems with `Send` bounds on GATs. The original code where the problem occurred uses the [`async-trait`](https://crates.io/crates/async-trait) crate and looks as follows:

```rust
#![feature(generic_associated_types)]

use async_trait::async_trait;
use std::ops::Deref;

async fn some_async_task() {}

#[async_trait]
trait Source {
    type T;
    type Wrapper<'a>: Deref<Target = Self::T> + Send
    where
        Self: 'a;
    async fn retrieve(&mut self) -> Self::Wrapper<'_>;
}

struct S {
    state: i32,
}

impl S {
    fn new() -> Self {
        S { state: 0 }
    }
}

#[async_trait]
impl Source for S {
    type T = i32;
    type Wrapper<'a> = &'a Self::T;
    async fn retrieve(&mut self) -> Self::Wrapper<'_> {
        self.state += 1;
        &self.state
    }
}

#[async_trait]
trait User {
    // After updating nightly rustc, this won't work anymore:
    async fn process<'a, 'b, S>(
        &'a self,
        source: &'b mut S,
    ) -> S::Wrapper<'b>
    where
        S: Source + Send,
    {
        let result = source.retrieve().await;
        some_async_task().await;
        result
    }
}

struct U {}

#[async_trait]
impl User for U {}

#[tokio::main]
async fn main() {
    let mut s = S::new();
    let u = U {};
    let value: &i32 = u.process(&mut s).await;
    println!("Result = {}", value);
}
```

Using the Rust playground with Nightly version: 1.58.0-nightly (2021-11-07 46b8e7488eae11672219), I get:

```text
   Compiling playground v0.0.1 (/playground)
error[E0311]: the parameter type `S` may not live long enough
  --> src/main.rs:46:5
   |
40 |       async fn process<'a, 'b, S>(
   |                                - help: consider adding an explicit lifetime bound...: `S: 'c`
...
46 | /     {
47 | |         let result = source.retrieve().await;
48 | |         some_async_task().await;
49 | |         result
50 | |     }
   | |_____^ ...so that the type `S` will meet its required lifetime bounds

error: could not compile `playground` due to previous error
```

If I follow the compiler's advice literally, then of course I'll get:

```text
error[E0261]: use of undeclared lifetime name `'c`
```

If I declare 'c as a lifetime parameter, then the compiler demands I should add a bound S: 'd, and so on.

This code worked with some earlier version of nightly Rust (without the `where Self: 'a` bound, and before `where Self: 'a` was required in the GAT). Unfortunately I do not remember which version that was (a few weeks ago).

However, even before the update of rustc, I had difficulties to remove the `Send` bound from the GATs definition and to include a bound in another method that uses the GATs. This problem still persists and can be demonstrated with the following code:

```rust
#![feature(generic_associated_types)]

use async_trait::async_trait;
use std::ops::Deref;

async fn some_async_task() {}

#[async_trait]
trait Source {
    type T;
    // I removed the `Send` bound here:
    type Wrapper<'a>: Deref<Target = Self::T>
    where
        Self: 'a;
    async fn retrieve(&mut self) -> Self::Wrapper<'_>;
}

struct S {
    state: i32,
}

impl S {
    fn new() -> Self {
        S { state: 0 }
    }
}

#[async_trait]
impl Source for S {
    type T = i32;
    type Wrapper<'a> = &'a Self::T;
    async fn retrieve(&mut self) -> Self::Wrapper<'_> {
        self.state += 1;
        &self.state
    }
}

#[async_trait]
trait User {
    async fn process<'a, 'b, S>(
        &'a self,
        source: &'b mut S,
    ) -> S::Wrapper<'b>
    where
        S: Source + Send + 'static,
        // And added it here:
        <S as Source>::Wrapper<'b>: Send,
    {
        let result = source.retrieve().await;
        some_async_task().await;
        result
    }
}

struct U {}

#[async_trait]
impl User for U {}

#[tokio::main]
async fn main() {
    let mut s = S::new();
    let u = U {};
    let value: &i32 = u.process(&mut s).await;
    println!("Result = {}", value);
}
```

Using again Rust playground with Nightly version: 1.58.0-nightly (2021-11-07 46b8e7488eae11672219), I get:

```text
   Compiling playground v0.0.1 (/playground)
error: implementation of `Send` is not general enough
  --> src/main.rs:48:5
   |
48 | /     {
49 | |         let result = source.retrieve().await;
50 | |         some_async_task().await;
51 | |         result
52 | |     }
   | |_____^ implementation of `Send` is not general enough
   |
   = note: `<S as Source>::Wrapper<'0>` must implement `Send`, for any lifetime `'0`...
   = note: ...but `Send` is actually implemented for the type `<S as Source>::Wrapper<'b>`

error: could not compile `playground` due to previous error
```

If I try to use a HRTB (`for<'z> <S as Source>::Wrapper<'z>: Send`), then I get:

```text
   Compiling playground v0.0.1 (/playground)
error[E0277]: `<_ as Source>::Wrapper<'z>` cannot be sent between threads safely
  --> src/main.rs:64:25
   |
64 |     let value: &i32 = u.process(&mut s).await;
   |                         ^^^^^^^ `<_ as Source>::Wrapper<'z>` cannot be sent between threads safely
   |
   = help: the trait `for<'z> Send` is not implemented for `<_ as Source>::Wrapper<'z>`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `playground` due to previous error
```

I'm not sure if these problems are related, but there seem to be a link. There has been a discussion on the Rust users forum where [another smaller example](https://users.rust-lang.org/t/problem-with-gats-in-an-async-trait-after-updating-nightly-rust/66983/14?u=jbe) (without `async-trait` macros) was created:

```rust
#![feature(generic_associated_types)]
use std::{future::Future, marker::PhantomData};

trait Trait {
    type Associated<'a>: Send
    where
        Self: 'a;
}

fn future<'a, S: Trait + 'a, F>(f: F) -> F
where
    F: Future<Output = ()> + Send,
{
    f
}

fn foo<'a, S: Trait + 'a>() {
    future::<'a, S, _>(async move {
        let result: PhantomData<S::Associated<'a>> = PhantomData;
        async {}.await;
    });
}
```

This results (using the same compiler version) in:

```text
   Compiling playground v0.0.1 (/playground)
error[E0311]: the parameter type `S` may not live long enough
  --> src/lib.rs:18:5
   |
17 | fn foo<'a, S: Trait + 'a>() {
   |            -- help: consider adding an explicit lifetime bound...: `S: 'b +`
18 |     future::<'a, S, _>(async move {
   |     ^^^^^^^^^^^^^^^^^^ ...so that the type `S` will meet its required lifetime bounds...
   |
note: ...that is required by this bound
  --> src/lib.rs:12:30
   |
12 |     F: Future<Output = ()> + Send,
   |                              ^^^^

error: could not compile `playground` due to previous error
```

If I replace `Send` with `SomeTrait` with `impl<T> SomeTrait for T {}`, the code will compile. We guessed the problem might be auto-trait related?

See also:

* The previously mentioned [discussion on the Rust users forum](https://users.rust-lang.org/t/problem-with-gats-in-an-async-trait-after-updating-nightly-rust/66983)
* #89970
* #87479