Repository: rust
Issue: Async fn disagrees on its own return type ("one of the expected opaque types" vs "one of the found opaque types")
Labels: T-compiler,C-bug,A-async-await,AsyncAwait-Triaged

The following is a minimal repro.

```rust
use core::future::Future;
use core::marker::PhantomData;
use core::pin::Pin;
use core::task::{Context, Poll};

async fn f() {}

pub fn fail<'a>() -> Box<dyn Future<Output = ()> + Send + 'a> {
    Box::new(async { new(|| async { f().await }).await })
}

fn new<A, B>(_a: A) -> F<A, B>
where
    A: Fn() -> B,
{
    F { _i: PhantomData }
}

trait Stream {
    type Item;
}

struct T<A, B> {
    _a: PhantomData<A>,
    _b: PhantomData<B>,
}

impl<A, B> Stream for T<A, B>
where
    A: Fn() -> B,
{
    type Item = B;
}

struct F<A, B>
where
    A: Fn() -> B,
{
    _i: PhantomData<<T<A, B> as Stream>::Item>,
}

impl<A, B> Future for F<A, B>
where
    A: Fn() -> B,
{
    type Output = ();
    fn poll(self: Pin<&mut Self>, _cx: &mut Context) -> Poll<Self::Output> {
        unimplemented!()
    }
}
```

```console
error[E0308]: mismatched types
  --> src/main.rs:9:5
   |
6  | async fn f() {}
   |              -
   |              |
   |              checked the `Output` of this `async fn`, one of the expected opaque types
   |              checked the `Output` of this `async fn`, one of the found opaque types
...
9  |     Box::new(async { new(|| async { f().await }).await })
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
   | 
  ::: .rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/future/mod.rs:61:43
   |
61 | pub const fn from_generator<T>(gen: T) -> impl Future<Output = T::Return>
   |                                           -------------------------------
   |                                           |
   |                                           one of the expected opaque types
   |                                           one of the found opaque types
   |
   = note: while checking the return type of the `async fn`
   = note: while checking the return type of the `async fn`
   = note: expected opaque type `impl Future`
              found opaque type `impl Future`
```

Note that rearranging `fn fail` to the following hides the issue and compiles. But my expectation would be that this does the exact same thing either way, with or without hiding the async block behind a named function.

```diff
-     Box::new(async { new(|| async { f().await }).await })
+     async fn wrap() { new(|| async { f().await }).await }
+     Box::new(wrap())
```

Various other very surprising transformations also hide the issue. For example:

```diff
  impl<A, B> Stream for T<A, B>
- where
-     A: Fn() -> B,
  {
      type Item = B;
  }
```

or:

```diff
-     Box::new(async { new(|| async { f().await }).await })
+     Box::new(async { new(|| f()).await })
```

or:

```diff
- pub fn fail<'a>() -> Box<dyn Future<Output = ()> + Send + 'a> {
+ pub fn fail() -> Box<dyn Future<Output = ()> + Send + 'static> {
```

I believe this is a compiler bug because none of the above transformations should have effect on whether this code compiles.