Open
Description
The following is a minimal repro.
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!()
}
}
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.
- 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:
impl<A, B> Stream for T<A, B>
- where
- A: Fn() -> B,
{
type Item = B;
}
or:
- Box::new(async { new(|| async { f().await }).await })
+ Box::new(async { new(|| f()).await })
or:
- 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.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status
On deck