Repository: rust
Issue: Higher ranked lifetime error when tryng to see that a future is send.
Labels: T-compiler,C-bug,A-async-await,AsyncAwait-Triaged,T-types,A-higher-ranked

<!--
Thank you for filing a bug report! 🐛 Please provide a short summary of the bug,
along with any information you feel relevant to replicating the bug.
-->

I tried this code:

```rust
use std::marker::PhantomData;

trait Callable<'a>: Send + Sync {
    fn callable(data: &'a [u8]);
}

trait Getter<'a>: Send + Sync {
    type ItemSize: Send + Sync;

    fn get(data: &'a [u8]);
}

struct List<'a, A: Getter<'a>> {
    data: &'a [u8],
    item_size: A::ItemSize, // Removing this member causes the code to compile
    phantom: PhantomData<A>,
}

struct GetterImpl<'a, T: Callable<'a> + 'a> {
    p: PhantomData<&'a T>,
}

impl<'a, T: Callable<'a> + 'a> Getter<'a> for GetterImpl<'a, T> {
    type ItemSize = ();

    fn get(data: &'a [u8]) {
        <T>::callable(data);
    }
}

struct ConstructableImpl<'a> {
    _data: &'a [u8],
}

impl<'a> Callable<'a> for ConstructableImpl<'a> {
    fn callable(_: &'a [u8]) {}
}

struct StructWithLifetime<'a> {
    marker: &'a PhantomData<u8>,
}

async fn async_method() {}

fn assert_send(_: impl Send + Sync) {}

// This async method ought to be send, but is not
async fn my_send_async_method(_struct_with_lifetime: &mut StructWithLifetime<'_>, data: &Vec<u8>) {
    let _named = List::<'_, GetterImpl<ConstructableImpl<'_>>> {
        data,
        item_size: (),
        phantom: PhantomData,
    };
    assert_send(_named);
    // Moving the await point above the constructed of _named, causes
    // the method to become send, even though _named is Send + Sync
    async_method().await;
}

fn dummy(struct_with_lifetime: &mut StructWithLifetime<'_>, data: &Vec<u8>) {
    assert_send(my_send_async_method(struct_with_lifetime, data));
}

fn main() {}
```
I expect this code to compile successfully. However the compiler fails to infer that `my_send_async_method` is SEND, even though it is.

I get the following error message:

```
$ rustc --version
rustc 1.71.0 (8ede3aae2 2023-07-12)

$ RUST_BACKTRACE=1 cargo build
   Compiling minimal v0.1.0 (/home/jakobt/dev/minimal)
error: implementation of `Getter` is not general enough
  --> src/main.rs:63:5
   |
63 |     assert_send(my_send_async_method(struct_with_lifetime, data));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough
   |
   = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`...
   = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2`

error: implementation of `Callable` is not general enough
  --> src/main.rs:63:5
   |
63 |     assert_send(my_send_async_method(struct_with_lifetime, data));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Callable` is not general enough
   |
   = note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`...
   = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1`

error: higher-ranked lifetime error
  --> src/main.rs:63:5
   |
63 |     assert_send(my_send_async_method(struct_with_lifetime, data));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: could not prove `impl Future<Output = ()>: Sync`

error: could not compile `minimal` (bin "minimal") due to 3 previous errors
```
This does not make sense, GetterImpl (and ConstructableImpl) cannot possible be constructed with two different lifetimes since that goes against the definition.

If we remove the call to `async_method().await` The `assert_send(_named)` show that _named is indeed `Send` and `Sync`, so the method should also me.

I have minimized this example as much as I can, removing any of the current parts resolves the issue. Removing the lifetime on `StructWithLifetime`, does not resolve the issue but changes the error message to
```
error: higher-ranked lifetime error
  --> src/main.rs:61:5
   |
61 |     assert_send(my_send_async_method(struct_with_lifetime, data));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: could not prove `impl Future<Output = ()>: Send`

error: higher-ranked lifetime error
  --> src/main.rs:61:5
   |
61 |     assert_send(my_send_async_method(struct_with_lifetime, data));
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   |
   = note: could not prove `impl Future<Output = ()>: Sync`
```