Repository: rust
Issue: RPITIT "captures lifetime that does not appear in bounds"
Labels: A-diagnostics,A-trait-system,T-compiler,A-impl-trait,C-bug,T-types,A-trait-objects

<!--
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: [playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=9f87601f00e11e3123406c8024e7422b)

```rust
trait MyTrait {
    fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32>;
}

trait ErasedMyTrait {
    fn foo<'life0, 'life1, 'dynosaur>(&'life0 self, x: &'life1 i32)
    -> Pin<Box<dyn Future<Output = i32> + 'dynosaur>>
    where
    'life0: 'dynosaur,
    'life1: 'dynosaur;
}

struct DynMyTrait<T: ErasedMyTrait> {
    ptr: T,
}

impl<T: ErasedMyTrait> MyTrait for DynMyTrait<T> {
    fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
        self.ptr.foo(x)
    }
}
```

## Diagnostics

I got a nonsensical error message:

```
error[E0700]: hidden type for `impl Future<Output = i32>` captures lifetime that does not appear in bounds
  --> src/lib.rs:22:9
   |
21 |     fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> {
   |                --                           ------------------------- opaque type defined here
   |                |
   |                hidden type `Pin<Box<(dyn Future<Output = i32> + 'b)>>` captures the lifetime `'b` as defined here
22 |         self.ptr.foo(x)
   |         ^^^^^^^^^^^^^^^
   |
help: to declare that `impl Future<Output = i32>` captures `'b`, you can add an explicit `'b` lifetime bound
   |
21 |     fn foo<'a, 'b>(&'a self, x: &'b i32) -> impl Future<Output = i32> + 'b {
   |                                                                       ++++
```

This is an RPITIT so the lifetime should not have to appear in the bounds to be captured. As you might expect, adding the `+ 'b` leads to a different error, and using the `Captures` trick does not work either (in fact, it is quite a mess of surprising errors: [playground](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=2c8b194d3d1c6bb1faf54eb68d15f1dd)).

## Should this compile?

Diagnostics aside, it's understandable that this wouldn't compile, because the compiler doesn't know what to do with the extra `'dynosaur` lifetime in `ErasedMyTrait::foo`. It would have to generate an intersection lifetime to get the full return type of that method (the `'dynosaur` in `Pin<Box<dyn Future<Output = i32> + 'dynosaur>>`.

Adding a lifetime that corresponds to `'dynosaur` to the original trait [does the trick](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=08e61464fc97947ac93fce0cedbc0375):

```rust
trait MyTrait {
    fn foo<'a, 'b, 'd>(&'a self, x: &'b i32) -> impl Future<Output = i32>
    where 'a: 'd, 'b: 'd;
}
```

As I alluded to above, I don't think have we to know which lifetime `'dynosaur` corresponds to to know that the original program is sound. Representing it as the intersection of `'a` and `'b` should be enough to see that our `Pin<Box<dyn Future>>` satisfies `-> impl Future` in the signature of the method we're implementing.

Through some magic it isn't necessary if we use async fn directly; this impl [compiles fine](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2024&gist=04ae3f07f30d78bbca397b2d04564b2f):

```rust
impl<T: ErasedMyTrait> MyTrait for DynMyTrait<T> {
    async fn foo<'a, 'b>(&'a self, x: &'b i32) -> i32 {
        self.ptr.foo(x).await
    }
}
```

I'm pretty much expecting to hear that this is too hard to support now, but the async fn chicanery gives me hope that it can be supported sooner.

### Meta
<!--
If you're using the stable version of the compiler, you should also check if the
bug also exists in the beta or nightly versions.
-->

rustc version:

```
1.82.0-nightly
(2024-08-05 e57f3090aec33cdbf660)
```