GAT Self: 'a bounds break some async blocks with impl Trait (original) (raw)

As required by #87479, Self: 'a must be explicitly added for GATs with self lifetimes. But it seems such a bound breaks async blocks with impl Trait sometimes.

Given a trait with a GAT:

trait Client { type Connecting<'a>: Future + Send where Self: 'a;

fn connect(&'_ self) -> Self::Connecting<'_>;

}

Awaiting on Client::connect() in an async block results in a confusing lifeime error on impl ...:

fn call_connect(c: &'_ C) -> impl '_ + Future + Send // removing +Send will compile where C: Client + Send + Sync, { // c.connect().inspect(|_| println!("this compiles")) async move { println!("this does not compile"); c.connect().await } }

error[E0311]: the parameter type `C` may not live long enough
  --> src/lib.rs:19:33
   |
19 | fn call_connect<C>(c: &'_ C) -> impl '_ + Future + Send  // removing +Send will compile
   |                 -               ^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `C` will meet its required lifetime bounds
   |                 |
   |                 help: consider adding an explicit lifetime bound...: `C: 'a`

It also breaks a generic impl on the trait with type_alias_impl_trait:

struct ClientWrapper(T);

impl Client for ClientWrapper where T: Client + Send + Sync, { type Connecting<'a> where T: 'a, = impl Future + Send; // removing +Send here & in the trait will compile

fn connect(&'_ self) -> Self::Connecting<'_> {
    // self.0.connect()  // <- this compiles
    // self.0.connect().inspect(|_| println!("this compiles"))
    async move {
        println!("this does not compile");
        self.0.connect().await
    }
}

}

error[E0311]: the parameter type `T` may not live long enough
  --> src/lib.rs:42:29
   |
33 | impl<T> Client for ClientWrapper<T>
   |      - help: consider adding an explicit lifetime bound...: `T: 'a`
...
42 |     fn connect(&'_ self) -> Self::Connecting<'_> {
   |                             ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds

Full code on the playground: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=15714304b9b5efab401efad8c2e84887

Meta

rustc --version --verbose:

rustc 1.59.0-nightly (7abab1efb 2021-12-17)
binary: rustc
commit-hash: 7abab1efb21617ba6845fa86328dffa16cfcf1dc
commit-date: 2021-12-17
host: x86_64-unknown-linux-gnu
release: 1.59.0-nightly
LLVM version: 13.0.0