diff options
| author | Michael Goulet <michael@errs.io> | 2025-07-13 23:17:21 +0000 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2025-07-15 16:02:26 +0000 |
| commit | 78fa79e7a642c8817b67d1c10d782c4c7b661a00 (patch) | |
| tree | fd15b0d3a45e3d85a7c43204ed6cc9b649fdfb92 | |
| parent | 512cf3ae88b26f50a92ebfcb69c24ca39acd72e6 (diff) | |
| download | rust-78fa79e7a642c8817b67d1c10d782c4c7b661a00.tar.gz rust-78fa79e7a642c8817b67d1c10d782c4c7b661a00.zip | |
Add tests, some of them fail...
38 files changed, 1206 insertions, 0 deletions
diff --git a/tests/ui/async-await/higher-ranked-auto-trait-1.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-1.no_assumptions.stderr new file mode 100644 index 00000000000..b298a3bf215 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-1.no_assumptions.stderr @@ -0,0 +1,38 @@ +error[E0308]: mismatched types + --> $DIR/higher-ranked-auto-trait-1.rs:37:5 + | +LL | / async { +LL | | let _y = &(); +LL | | let _x = filter(FilterMap { +LL | | f: || async move { *_y }, +... | +LL | | drop(_x); +LL | | } + | |_____^ one type is more general than the other + | + = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-1.rs:40:19: 40:29}` + found `async` block `{async block@$DIR/higher-ranked-auto-trait-1.rs:40:19: 40:29}` + = note: no two async blocks, even if identical, have the same type + = help: consider pinning your async block and casting it to a trait object + +error[E0308]: mismatched types + --> $DIR/higher-ranked-auto-trait-1.rs:37:5 + | +LL | / async { +LL | | let _y = &(); +LL | | let _x = filter(FilterMap { +LL | | f: || async move { *_y }, +... | +LL | | drop(_x); +LL | | } + | |_____^ one type is more general than the other + | + = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-1.rs:40:19: 40:29}` + found `async` block `{async block@$DIR/higher-ranked-auto-trait-1.rs:40:19: 40:29}` + = note: no two async blocks, even if identical, have the same type + = help: consider pinning your async block and casting it to a trait object + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/higher-ranked-auto-trait-1.rs b/tests/ui/async-await/higher-ranked-auto-trait-1.rs new file mode 100644 index 00000000000..740f7e29245 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-1.rs @@ -0,0 +1,48 @@ +// Repro for <https://github.com/rust-lang/rust/issues/79648#issuecomment-749127947>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::future::Future; +use std::marker::PhantomData; + +trait Stream { + type Item; +} + +struct Filter<St: Stream> { + pending_item: St::Item, +} + +fn filter<St: Stream>(_: St) -> Filter<St> { + unimplemented!(); +} + +struct FilterMap<Fut, F> { + f: F, + pending: PhantomData<Fut>, +} + +impl<Fut, F> Stream for FilterMap<Fut, F> +where + F: FnMut() -> Fut, + Fut: Future, +{ + type Item = (); +} + +pub fn get_foo() -> impl Future + Send { + async { + let _y = &(); + let _x = filter(FilterMap { + f: || async move { *_y }, + pending: PhantomData, + }); + async {}.await; + drop(_x); + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr new file mode 100644 index 00000000000..6fcf1b1eac1 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr @@ -0,0 +1,21 @@ +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-auto-trait-10.rs:32:5 + | +LL | Box::new(async move { get_foo(x).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` + +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-auto-trait-10.rs:32:5 + | +LL | Box::new(async move { get_foo(x).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr new file mode 100644 index 00000000000..6fcf1b1eac1 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr @@ -0,0 +1,21 @@ +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-auto-trait-10.rs:32:5 + | +LL | Box::new(async move { get_foo(x).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` + +error: implementation of `Foo` is not general enough + --> $DIR/higher-ranked-auto-trait-10.rs:32:5 + | +LL | Box::new(async move { get_foo(x).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | + = note: `Foo<'1>` would have to be implemented for the type `&'0 str`, for any two lifetimes `'0` and `'1`... + = note: ...but `Foo<'2>` is actually implemented for the type `&'2 str`, for some specific lifetime `'2` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.rs b/tests/ui/async-await/higher-ranked-auto-trait-10.rs new file mode 100644 index 00000000000..4bfa27961ab --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-10.rs @@ -0,0 +1,35 @@ +// Repro for <https://github.com/rust-lang/rust/issues/92415#issue-1090723521>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] known-bug: unknown +//@[no_assumptions] known-bug: #110338 + +use std::any::Any; +use std::future::Future; + +trait Foo<'a>: Sized { + type Error; + fn foo(x: &'a str) -> Result<Self, Self::Error>; +} + +impl<'a> Foo<'a> for &'a str { + type Error = (); + + fn foo(x: &'a str) -> Result<Self, Self::Error> { + Ok(x) + } +} + +async fn get_foo<'a, T>(x: &'a str) -> Result<T, <T as Foo<'a>>::Error> +where + T: Foo<'a>, +{ + Foo::foo(x) +} + +fn bar<'a>(x: &'a str) -> Box<dyn Future<Output = Result<&'a str, ()>> + Send + 'a> { + Box::new(async move { get_foo(x).await }) +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr new file mode 100644 index 00000000000..d39843f628c --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/higher-ranked-auto-trait-11.rs:27:9 + | +LL | impl<'a, T> Foo<'a> for MyType<T> + | -- lifetime `'a` defined here +... +LL | Box::pin(async move { <T as Foo<'a>>::foo().await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'a` must outlive `'static` + +error: implementation of `Send` is not general enough + --> $DIR/higher-ranked-auto-trait-11.rs:27:9 + | +LL | Box::pin(async move { <T as Foo<'a>>::foo().await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough + | + = note: `Send` would have to be implemented for the type `<T as Foo<'0>>::Future`, for any lifetime `'0`... + = note: ...but `Send` is actually implemented for the type `<T as Foo<'1>>::Future`, for some specific lifetime `'1` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr new file mode 100644 index 00000000000..d39843f628c --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr @@ -0,0 +1,20 @@ +error: lifetime may not live long enough + --> $DIR/higher-ranked-auto-trait-11.rs:27:9 + | +LL | impl<'a, T> Foo<'a> for MyType<T> + | -- lifetime `'a` defined here +... +LL | Box::pin(async move { <T as Foo<'a>>::foo().await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ coercion requires that `'a` must outlive `'static` + +error: implementation of `Send` is not general enough + --> $DIR/higher-ranked-auto-trait-11.rs:27:9 + | +LL | Box::pin(async move { <T as Foo<'a>>::foo().await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough + | + = note: `Send` would have to be implemented for the type `<T as Foo<'0>>::Future`, for any lifetime `'0`... + = note: ...but `Send` is actually implemented for the type `<T as Foo<'1>>::Future`, for some specific lifetime `'1` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.rs b/tests/ui/async-await/higher-ranked-auto-trait-11.rs new file mode 100644 index 00000000000..3aebdd8224d --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-11.rs @@ -0,0 +1,31 @@ +// Repro for <https://github.com/rust-lang/rust/issues/60658#issuecomment-1509321859>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] known-bug: unknown +//@[no_assumptions] known-bug: #110338 + +use core::pin::Pin; +use std::future::Future; + +pub trait Foo<'a> { + type Future: Future<Output = ()>; + + fn foo() -> Self::Future; +} + +struct MyType<T>(T); + +impl<'a, T> Foo<'a> for MyType<T> +where + T: Foo<'a>, + T::Future: Send, +{ + type Future = Pin<Box<dyn Future<Output = ()> + Send + 'a>>; + + fn foo() -> Self::Future { + Box::pin(async move { <T as Foo<'a>>::foo().await }) + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr new file mode 100644 index 00000000000..63e71cbc40c --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr @@ -0,0 +1,18 @@ +error: implementation of `Robot` is not general enough + --> $DIR/higher-ranked-auto-trait-12.rs:31:20 + | +LL | let _my_task = this_is_send(async move { + | ____________________^ +LL | | let _my_iter = IRobot { +LL | | id: 32, +LL | | robot: source, +LL | | }; +LL | | yield_now().await; +LL | | }); + | |______^ implementation of `Robot` is not general enough + | + = note: `Box<(dyn Robot<Id = u32> + Send + '0)>` must implement `Robot`, for any lifetime `'0`... + = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot<Id = u32> + Send + 'static)>` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.rs b/tests/ui/async-await/higher-ranked-auto-trait-12.rs new file mode 100644 index 00000000000..b1cca5cbb00 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.rs @@ -0,0 +1,40 @@ +// Repro for <https://github.com/rust-lang/rust/issues/71671#issuecomment-848994782>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +pub trait Robot { + type Id; +} + +pub type DynRobot = Box<dyn Robot<Id = u32> + Send>; + +impl Robot for DynRobot { + type Id = u32; +} + +struct IRobot<R: Robot> { + id: R::Id, + robot: R, +} + +// stand-in for tokio::spawn +fn this_is_send<T: Send>(value: T) -> T { + value +} + +async fn yield_now() {} + +fn test(source: DynRobot) { + let _my_task = this_is_send(async move { + let _my_iter = IRobot { + id: 32, + robot: source, + }; + yield_now().await; + }); +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr new file mode 100644 index 00000000000..f69218740dc --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr @@ -0,0 +1,41 @@ +error: implementation of `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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 `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr new file mode 100644 index 00000000000..cfbdaa8ad4b --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -0,0 +1,60 @@ +error: implementation of `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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 `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `Callable` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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: implementation of `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `Getter` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: implementation of `Callable` is not general enough + --> $DIR/higher-ranked-auto-trait-13.rs:65:5 + | +LL | 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` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 6 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.rs b/tests/ui/async-await/higher-ranked-auto-trait-13.rs new file mode 100644 index 00000000000..4bce0f5197f --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.rs @@ -0,0 +1,68 @@ +// Repro for <https://github.com/rust-lang/rust/issues/114046#issue-1819720359>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] known-bug: unknown +//@[no_assumptions] known-bug: #110338 + +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 }; + // Moving the await point above the constructed of _named, causes + // the method to become send, even though _named is Send + Sync + async_method().await; + assert_send(_named); +} + +fn dummy(struct_with_lifetime: &mut StructWithLifetime<'_>, data: &Vec<u8>) { + assert_send(my_send_async_method(struct_with_lifetime, data)); +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr new file mode 100644 index 00000000000..b47db2b19ff --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-14.no_assumptions.stderr @@ -0,0 +1,33 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-14.rs:20:5 + | +LL | / async move { +LL | | let xs = unique_x.union(&cached) +LL | | // .copied() // works +LL | | .map(|x| *x) // error +LL | | ; +LL | | let blah = val.blah(xs.into_iter()).await; +LL | | } + | |_____^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32,)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-14.rs:20:5 + | +LL | / async move { +LL | | let xs = unique_x.union(&cached) +LL | | // .copied() // works +LL | | .map(|x| *x) // error +LL | | ; +LL | | let blah = val.blah(xs.into_iter()).await; +LL | | } + | |_____^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 u32) -> u32` must implement `FnOnce<(&'1 u32,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&u32,)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.rs b/tests/ui/async-await/higher-ranked-auto-trait-14.rs new file mode 100644 index 00000000000..5ed12cd6e38 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-14.rs @@ -0,0 +1,29 @@ +// Repro for <https://github.com/rust-lang/rust/issues/124757#issue-2279603232>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::collections::HashSet; +use std::future::Future; + +trait MyTrait { + fn blah(&self, x: impl Iterator<Item = u32>) -> impl Future<Output = ()> + Send; +} + +fn foo<T: MyTrait + Send + Sync>( + val: T, + unique_x: HashSet<u32>, +) -> impl Future<Output = ()> + Send { + let cached = HashSet::new(); + async move { + let xs = unique_x.union(&cached) + // .copied() // works + .map(|x| *x) // error + ; + let blah = val.blah(xs.into_iter()).await; + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr new file mode 100644 index 00000000000..b4f3570d9f2 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -0,0 +1,21 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-15.rs:20:5 + | +LL | require_send(future); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 Vec<i32>) -> std::slice::Iter<'_, i32>` must implement `FnOnce<(&'1 Vec<i32>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&Vec<i32>,)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-15.rs:20:5 + | +LL | require_send(future); + | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 Vec<i32>) -> std::slice::Iter<'_, i32>` must implement `FnOnce<(&'1 Vec<i32>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&Vec<i32>,)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.rs b/tests/ui/async-await/higher-ranked-auto-trait-15.rs new file mode 100644 index 00000000000..153fcac4c3a --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.rs @@ -0,0 +1,21 @@ +// Repro for <https://github.com/rust-lang/rust/issues/126044#issuecomment-2154313449>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +async fn listen() { + let things: Vec<Vec<i32>> = vec![]; + for _ in things.iter().map(|n| n.iter()).flatten() { + // comment this line and everything compiles + async {}.await; + } +} + +fn require_send<T: Send>(_x: T) {} + +fn main() { + let future = listen(); + require_send(future); +} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr new file mode 100644 index 00000000000..412c31b1bd8 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr @@ -0,0 +1,25 @@ +error: implementation of `AsyncFnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-16.rs:18:5 + | +LL | / assert_send(async { +LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; +LL | | }); + | |______^ implementation of `AsyncFnOnce` is not general enough + | + = note: `{async closure@$DIR/higher-ranked-auto-trait-16.rs:19:33: 19:42}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` + +error: implementation of `AsyncFnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-16.rs:18:5 + | +LL | / assert_send(async { +LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; +LL | | }); + | |______^ implementation of `AsyncFnOnce` is not general enough + | + = note: `{async closure@$DIR/higher-ranked-auto-trait-16.rs:19:33: 19:42}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr new file mode 100644 index 00000000000..412c31b1bd8 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr @@ -0,0 +1,25 @@ +error: implementation of `AsyncFnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-16.rs:18:5 + | +LL | / assert_send(async { +LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; +LL | | }); + | |______^ implementation of `AsyncFnOnce` is not general enough + | + = note: `{async closure@$DIR/higher-ranked-auto-trait-16.rs:19:33: 19:42}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` + +error: implementation of `AsyncFnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-16.rs:18:5 + | +LL | / assert_send(async { +LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; +LL | | }); + | |______^ implementation of `AsyncFnOnce` is not general enough + | + = note: `{async closure@$DIR/higher-ranked-auto-trait-16.rs:19:33: 19:42}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.rs b/tests/ui/async-await/higher-ranked-auto-trait-16.rs new file mode 100644 index 00000000000..2b206f0a4c5 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.rs @@ -0,0 +1,23 @@ +// Repro for <https://github.com/rust-lang/rust/issues/126350#issue-2349492101>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] known-bug: unknown +//@[no_assumptions] known-bug: #110338 + +fn assert_send<T: Send>(_: T) {} + +#[derive(Clone)] +struct Ctxt<'a>(&'a ()); + +async fn commit_if_ok<'a>(ctxt: &mut Ctxt<'a>, f: impl AsyncFnOnce(&mut Ctxt<'a>)) { + f(&mut ctxt.clone()).await; +} + +fn operation(mut ctxt: Ctxt<'_>) { + assert_send(async { + commit_if_ok(&mut ctxt, async |_| todo!()).await; + }); +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-17.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-17.no_assumptions.stderr new file mode 100644 index 00000000000..152900ca1ae --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-17.no_assumptions.stderr @@ -0,0 +1,29 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-17.rs:12:5 + | +LL | / async move { +LL | | let iter = Adaptor::new(a.iter().map(|_: &()| {})); +LL | | std::future::pending::<()>().await; +LL | | drop(iter); +LL | | } + | |_____^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + +error: implementation of `FnOnce` is not general enough + --> $DIR/higher-ranked-auto-trait-17.rs:12:5 + | +LL | / async move { +LL | | let iter = Adaptor::new(a.iter().map(|_: &()| {})); +LL | | std::future::pending::<()>().await; +LL | | drop(iter); +LL | | } + | |_____^ implementation of `FnOnce` is not general enough + | + = note: closure with signature `fn(&'0 ())` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...but it actually implements `FnOnce<(&(),)>` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 2 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-17.rs b/tests/ui/async-await/higher-ranked-auto-trait-17.rs new file mode 100644 index 00000000000..152432466c0 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-17.rs @@ -0,0 +1,30 @@ +// Repro for <https://github.com/rust-lang/rust/issues/114177#issue-1826550174>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +// Using `impl Future` instead of `async to ensure that the Future is Send. +// +// In the original code `a` would be `&[T]`. For more minimization I've removed the reference. +fn foo(a: [(); 0]) -> impl std::future::Future<Output = ()> + Send { + async move { + let iter = Adaptor::new(a.iter().map(|_: &()| {})); + std::future::pending::<()>().await; + drop(iter); + } +} + +struct Adaptor<T: Iterator> { + iter: T, + v: T::Item, +} + +impl<T: Iterator> Adaptor<T> { + pub fn new(_: T) -> Self { + Self { iter: todo!(), v: todo!() } + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr new file mode 100644 index 00000000000..2fc44412b9d --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-2.no_assumptions.stderr @@ -0,0 +1,49 @@ +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-2.rs:16:9 + | +LL | / async move { +LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics +LL | | self.run(t).await; +LL | | } + | |_________^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-2.rs:16:9 + | +LL | / async move { +LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics +LL | | self.run(t).await; +LL | | } + | |_________^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-2.rs:16:9 + | +LL | / async move { +LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics +LL | | self.run(t).await; +LL | | } + | |_________^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-2.rs:16:9 + | +LL | / async move { +LL | | // asks for an unspecified lifetime to outlive itself? weird diagnostics +LL | | self.run(t).await; +LL | | } + | |_________^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.rs b/tests/ui/async-await/higher-ranked-auto-trait-2.rs new file mode 100644 index 00000000000..6c75597265b --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-2.rs @@ -0,0 +1,23 @@ +// Repro for <https://github.com/rust-lang/rust/issues/111105#issue-1692860759>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::future::Future; + +pub trait Foo: Sync { + fn run<'a, 'b: 'a, T: Sync>(&'a self, _: &'b T) -> impl Future<Output = ()> + 'a + Send; +} + +pub trait FooExt: Foo { + fn run_via<'a, 'b: 'a, T: Sync>(&'a self, t: &'b T) -> impl Future<Output = ()> + 'a + Send { + async move { + // asks for an unspecified lifetime to outlive itself? weird diagnostics + self.run(t).await; + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr new file mode 100644 index 00000000000..c5c98ac807e --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.no_assumptions.stderr @@ -0,0 +1,12 @@ +error: lifetime bound not satisfied + --> $DIR/higher-ranked-auto-trait-3.rs:66:9 + | +LL | / async { +LL | | self.fi_2.get_iter(cx).await; +LL | | } + | |_________^ + | + = note: this is a known limitation that will be removed in the future (see issue #100013 <https://github.com/rust-lang/rust/issues/100013> for more information) + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.rs b/tests/ui/async-await/higher-ranked-auto-trait-3.rs new file mode 100644 index 00000000000..d42d4236680 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-3.rs @@ -0,0 +1,72 @@ +// Repro for <https://github.com/rust-lang/rust/issues/100013#issue-1323807923>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +#![feature(impl_trait_in_assoc_type)] + +use std::future::Future; + +pub trait FutureIterator: 'static { + type Iterator; + + type Future<'s, 'cx>: Future<Output = Self::Iterator> + Send + 'cx + where + 's: 'cx; + + fn get_iter<'s, 'cx>(&'s self, info: &'cx ()) -> Self::Future<'s, 'cx>; +} + +trait IterCaller: 'static { + type Future1<'cx>: Future<Output = ()> + Send + 'cx; + type Future2<'cx>: Future<Output = ()> + Send + 'cx; + + fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> + where + 's: 'cx; + fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> + where + 's: 'cx; +} + +struct UseIter<FI1, FI2> { + fi_1: FI1, + fi_2: FI2, +} + +impl<FI1, FI2> IterCaller for UseIter<FI1, FI2> +where + FI1: FutureIterator + 'static + Send + Sync, + for<'s, 'cx> FI1::Future<'s, 'cx>: Send, + FI2: FutureIterator + 'static + Send + Sync, +{ + type Future1<'cx> = impl Future<Output = ()> + Send + 'cx + where + Self: 'cx; + + type Future2<'cx> = impl Future<Output = ()> + Send + 'cx + where + Self: 'cx; + + fn call_1<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future1<'cx> + where + 's: 'cx, + { + async { + self.fi_1.get_iter(cx).await; + } + } + + fn call_2<'s, 'cx>(&'s self, cx: &'cx ()) -> Self::Future2<'cx> + where + 's: 'cx, + { + async { + self.fi_2.get_iter(cx).await; + } + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-4.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-4.no_assumptions.stderr new file mode 100644 index 00000000000..5aa5b83655a --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-4.no_assumptions.stderr @@ -0,0 +1,10 @@ +error: higher-ranked lifetime error + --> $DIR/higher-ranked-auto-trait-4.rs:29:5 + | +LL | / async { +LL | | let _ = evil_function::<dyn BoringTrait, _>().await; +LL | | } + | |_____^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-4.rs b/tests/ui/async-await/higher-ranked-auto-trait-4.rs new file mode 100644 index 00000000000..0586af41e9e --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-4.rs @@ -0,0 +1,34 @@ +// Repro for <https://github.com/rust-lang/rust/issues/102211#issuecomment-2891975128>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::future::Future; + +trait BoringTrait {} + +trait TraitWithAssocType<I> { + type Assoc; +} + +impl<T> TraitWithAssocType<()> for T +where + T: ?Sized + 'static, +{ + type Assoc = (); +} + +fn evil_function<T: TraitWithAssocType<I> + ?Sized, I>() +-> impl Future<Output = Result<(), T::Assoc>> { + async { Ok(()) } +} + +fn fails_to_compile() -> impl std::future::Future<Output = ()> + Send { + async { + let _ = evil_function::<dyn BoringTrait, _>().await; + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr new file mode 100644 index 00000000000..8fa3c7483c8 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -0,0 +1,13 @@ +error: implementation of `Send` is not general enough + --> $DIR/higher-ranked-auto-trait-5.rs:13:5 + | +LL | / assert_send(async { +LL | | call_me.call().await; +LL | | }); + | |______^ implementation of `Send` is not general enough + | + = note: `Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... + = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.rs b/tests/ui/async-await/higher-ranked-auto-trait-5.rs new file mode 100644 index 00000000000..9a8b3f4357c --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.rs @@ -0,0 +1,54 @@ +// Repro for <https://github.com/rust-lang/rust/issues/130113#issue-2512517191>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::future::Future; + +fn main() { + let call_me = Wrap(CallMeImpl { value: "test" }); + + assert_send(async { + call_me.call().await; + }); +} + +pub fn assert_send<F>(_future: F) +where + F: Future + Send, +{ +} + +pub trait CallMe { + fn call(&self) -> impl Future<Output = ()> + Send; +} + +struct Wrap<T>(T); + +impl<S> CallMe for Wrap<S> +where + S: CallMe + Send, +{ + // adding `+ Send` to this RPIT fixes the issue + fn call(&self) -> impl Future<Output = ()> { + self.0.call() + } +} + +#[derive(Debug, Clone, Copy)] +pub struct CallMeImpl<T> { + value: T, +} + +impl<T> CallMe for CallMeImpl<T> +where + // Can replace `Send` by `ToString`, `Clone`, whatever. When removing the + // `Send` bound, the compiler produces a higher-ranked lifetime error. + T: Send + 'static, +{ + fn call(&self) -> impl Future<Output = ()> { + async {} + } +} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr new file mode 100644 index 00000000000..d1f2d9a0753 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr @@ -0,0 +1,50 @@ +error[E0308]: mismatched types + --> $DIR/higher-ranked-auto-trait-6.rs:16:5 + | +LL | Box::new(async { new(|| async { f().await }).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + = note: no two async blocks, even if identical, have the same type + = help: consider pinning your async block and casting it to a trait object + +error[E0308]: mismatched types + --> $DIR/higher-ranked-auto-trait-6.rs:16:5 + | +LL | Box::new(async { new(|| async { f().await }).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + = note: no two async blocks, even if identical, have the same type + = help: consider pinning your async block and casting it to a trait object + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/higher-ranked-auto-trait-6.rs:16:5 + | +LL | Box::new(async { new(|| async { f().await }).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + = note: no two async blocks, even if identical, have the same type + = help: consider pinning your async block and casting it to a trait object + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0308]: mismatched types + --> $DIR/higher-ranked-auto-trait-6.rs:16:5 + | +LL | Box::new(async { new(|| async { f().await }).await }) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + found `async` block `{async block@$DIR/higher-ranked-auto-trait-6.rs:16:29: 16:34}` + = note: no two async blocks, even if identical, have the same type + = help: consider pinning your async block and casting it to a trait object + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.rs b/tests/ui/async-await/higher-ranked-auto-trait-6.rs new file mode 100644 index 00000000000..2c6adf8938d --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-6.rs @@ -0,0 +1,59 @@ +// Repro for <https://github.com/rust-lang/rust/issues/82921#issue-825114180>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +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!() + } +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr new file mode 100644 index 00000000000..dcb8075566e --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-7.no_assumptions.stderr @@ -0,0 +1,8 @@ +error: `S` does not live long enough + --> $DIR/higher-ranked-auto-trait-7.rs:26:5 + | +LL | future::<'a, S, _>(async move { + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.rs b/tests/ui/async-await/higher-ranked-auto-trait-7.rs new file mode 100644 index 00000000000..abded5a88d3 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-7.rs @@ -0,0 +1,33 @@ +// Repro for <https://github.com/rust-lang/rust/issues/90696#issuecomment-963375847>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +#![allow(dropping_copy_types)] + +use std::{future::Future, marker::PhantomData}; + +trait Trait { + type Associated<'a>: Send + where + Self: 'a; +} + +fn future<'a, S: Trait + 'a, F>(f: F) -> F +where + F: Future<Output = ()> + Send, +{ + f +} + +fn foo<'a, S: Trait + 'a>() { + future::<'a, S, _>(async move { + let result: PhantomData<S::Associated<'a>> = PhantomData; + async {}.await; + drop(result); + }); +} + +fn main() {} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-8.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-8.no_assumptions.stderr new file mode 100644 index 00000000000..6208675117b --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-8.no_assumptions.stderr @@ -0,0 +1,10 @@ +error: higher-ranked lifetime error + --> $DIR/higher-ranked-auto-trait-8.rs:26:5 + | +LL | needs_send(use_my_struct(second_struct)); // ERROR + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: could not prove `impl Future<Output = ()>: Send` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-8.rs b/tests/ui/async-await/higher-ranked-auto-trait-8.rs new file mode 100644 index 00000000000..91cef204e44 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-8.rs @@ -0,0 +1,27 @@ +// Repro for <https://github.com/rust-lang/rust/issues/64552#issuecomment-532801232>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +fn needs_send<T: Send>(_val: T) {} +async fn use_async<T>(_val: T) {} + +struct MyStruct<'a, T: 'a> { + val: &'a T, +} + +unsafe impl<'a, T: 'a> Send for MyStruct<'a, T> {} + +async fn use_my_struct(val: MyStruct<'static, &'static u8>) { + use_async(val).await; +} + +fn main() { + let first_struct: MyStruct<'static, &'static u8> = MyStruct { val: &&26 }; + let second_struct: MyStruct<'static, &'static u8> = MyStruct { val: &&27 }; + + needs_send(first_struct); + needs_send(use_my_struct(second_struct)); // ERROR +} diff --git a/tests/ui/async-await/higher-ranked-auto-trait-9.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-9.no_assumptions.stderr new file mode 100644 index 00000000000..809cbcf0cad --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-9.no_assumptions.stderr @@ -0,0 +1,11 @@ +error: implementation of `Debug` is not general enough + --> $DIR/higher-ranked-auto-trait-9.rs:43:50 + | +LL | let fut: &(dyn Future<Output = ()> + Send) = &fut as _; + | ^^^^^^^^^ implementation of `Debug` is not general enough + | + = note: `(dyn Any + '0)` must implement `Debug`, for any lifetime `'0`... + = note: ...but `Debug` is actually implemented for the type `(dyn Any + 'static)` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-9.rs b/tests/ui/async-await/higher-ranked-auto-trait-9.rs new file mode 100644 index 00000000000..66edbf23f2b --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-9.rs @@ -0,0 +1,44 @@ +// Repro for <https://github.com/rust-lang/rust/issues/87425#issue-952059416>. +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::any::Any; +use std::fmt; +use std::future::Future; + +pub trait Foo { + type Item; +} + +impl<F, I> Foo for F +where + Self: FnOnce() -> I, + I: fmt::Debug, +{ + type Item = I; +} + +async fn foo_item<F: Foo>(_: F) -> F::Item { + unimplemented!() +} + +fn main() { + let fut = async { + let callback = || -> Box<dyn Any> { unimplemented!() }; + + // Using plain fn instead of a closure fixes the error, + // though you obviously can't capture any state... + // fn callback() -> Box<dyn Any> { + // todo!() + // } + + foo_item(callback).await; + }; + + // Removing `+ Send` bound also fixes the error, + // though at the cost of loosing `Send`ability... + let fut: &(dyn Future<Output = ()> + Send) = &fut as _; +} |
