--- /dev/null
+use tests_build::tokio;
+
+#[tokio::main]
+async fn main() {
+ // do not leak `RotatorSelect`
+ let _ = tokio::join!(async {
+ fn foo(_: impl RotatorSelect) {}
+ });
+
+ // do not leak `std::task::Poll::Pending`
+ let _ = tokio::join!(async { Pending });
+
+ // do not leak `std::task::Poll::Ready`
+ let _ = tokio::join!(async { Ready(0) });
+
+ // do not leak `std::future::Future`
+ let _ = tokio::join!(async {
+ struct MyFuture;
+
+ impl Future for MyFuture {
+ type Output = ();
+
+ fn poll(
+ self: std::pin::Pin<&mut Self>,
+ _cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Self::Output> {
+ todo!()
+ }
+ }
+ });
+
+ // do not leak `std::pin::Pin`
+ let _ = tokio::join!(async {
+ let mut x = 5;
+ let _ = Pin::new(&mut x);
+ });
+
+ // do not leak `std::future::poll_fn`
+ let _ = tokio::join!(async {
+ let _ = poll_fn(|_cx| todo!());
+ });
+}
--- /dev/null
+error[E0405]: cannot find trait `RotatorSelect` in this scope
+ --> tests/fail/macros_join.rs:7:24
+ |
+7 | fn foo(_: impl RotatorSelect) {}
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `Pending` in this scope
+ --> tests/fail/macros_join.rs:11:34
+ |
+11 | let _ = tokio::join!(async { Pending });
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this unit variant
+ |
+ 1 + use std::task::Poll::Pending;
+ |
+
+error[E0425]: cannot find function, tuple struct or tuple variant `Ready` in this scope
+ --> tests/fail/macros_join.rs:14:34
+ |
+14 | let _ = tokio::join!(async { Ready(0) });
+ | ^^^^^ not found in this scope
+ |
+help: consider importing this tuple variant
+ |
+ 1 + use std::task::Poll::Ready;
+ |
+
+error[E0405]: cannot find trait `Future` in this scope
+ --> tests/fail/macros_join.rs:20:14
+ |
+20 | impl Future for MyFuture {
+ | ^^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+ 1 + use std::future::Future;
+ |
+
+error[E0433]: failed to resolve: use of undeclared type `Pin`
+ --> tests/fail/macros_join.rs:35:17
+ |
+35 | let _ = Pin::new(&mut x);
+ | ^^^ use of undeclared type `Pin`
+ |
+help: consider importing this struct
+ |
+ 1 + use std::pin::Pin;
+ |
+
+error[E0425]: cannot find function `poll_fn` in this scope
+ --> tests/fail/macros_join.rs:40:17
+ |
+40 | let _ = poll_fn(|_cx| todo!());
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this function
+ |
+ 1 + use std::future::poll_fn;
+ |
--- /dev/null
+use tests_build::tokio;
+
+#[tokio::main]
+async fn main() {
+ // do not leak `RotatorSelect`
+ let _ = tokio::try_join!(async {
+ fn foo(_: impl RotatorSelect) {}
+ });
+
+ // do not leak `std::task::Poll::Pending`
+ let _ = tokio::try_join!(async { Pending });
+
+ // do not leak `std::task::Poll::Ready`
+ let _ = tokio::try_join!(async { Ready(0) });
+
+ // do not leak `std::future::Future`
+ let _ = tokio::try_join!(async {
+ struct MyFuture;
+
+ impl Future for MyFuture {
+ type Output = ();
+
+ fn poll(
+ self: std::pin::Pin<&mut Self>,
+ _cx: &mut std::task::Context<'_>,
+ ) -> std::task::Poll<Self::Output> {
+ todo!()
+ }
+ }
+ });
+
+ // do not leak `std::pin::Pin`
+ let _ = tokio::try_join!(async {
+ let mut x = 5;
+ let _ = Pin::new(&mut x);
+ });
+
+ // do not leak `std::future::poll_fn`
+ let _ = tokio::try_join!(async {
+ let _ = poll_fn(|_cx| todo!());
+ });
+}
--- /dev/null
+error[E0405]: cannot find trait `RotatorSelect` in this scope
+ --> tests/fail/macros_try_join.rs:7:24
+ |
+7 | fn foo(_: impl RotatorSelect) {}
+ | ^^^^^^^^^^^^^ not found in this scope
+
+error[E0425]: cannot find value `Pending` in this scope
+ --> tests/fail/macros_try_join.rs:11:38
+ |
+11 | let _ = tokio::try_join!(async { Pending });
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this unit variant
+ |
+ 1 + use std::task::Poll::Pending;
+ |
+
+error[E0425]: cannot find function, tuple struct or tuple variant `Ready` in this scope
+ --> tests/fail/macros_try_join.rs:14:38
+ |
+14 | let _ = tokio::try_join!(async { Ready(0) });
+ | ^^^^^ not found in this scope
+ |
+help: consider importing this tuple variant
+ |
+ 1 + use std::task::Poll::Ready;
+ |
+
+error[E0405]: cannot find trait `Future` in this scope
+ --> tests/fail/macros_try_join.rs:20:14
+ |
+20 | impl Future for MyFuture {
+ | ^^^^^^ not found in this scope
+ |
+help: consider importing this trait
+ |
+ 1 + use std::future::Future;
+ |
+
+error[E0433]: failed to resolve: use of undeclared type `Pin`
+ --> tests/fail/macros_try_join.rs:35:17
+ |
+35 | let _ = Pin::new(&mut x);
+ | ^^^ use of undeclared type `Pin`
+ |
+help: consider importing this struct
+ |
+ 1 + use std::pin::Pin;
+ |
+
+error[E0425]: cannot find function `poll_fn` in this scope
+ --> tests/fail/macros_try_join.rs:40:17
+ |
+40 | let _ = poll_fn(|_cx| todo!());
+ | ^^^^^^^ not found in this scope
+ |
+help: consider importing this function
+ |
+ 1 + use std::future::poll_fn;
+ |
#[cfg(feature = "full")]
t.compile_fail("tests/fail/macros_dead_code.rs");
+ #[cfg(feature = "full")]
+ t.compile_fail("tests/fail/macros_join.rs");
+
+ #[cfg(feature = "full")]
+ t.compile_fail("tests/fail/macros_try_join.rs");
+
#[cfg(feature = "full")]
t.compile_fail("tests/fail/macros_type_mismatch.rs");
$( ( $($skip:tt)* ) $e:expr, )*
}) => {{
- use $crate::macros::support::{maybe_done, poll_fn, Future, Pin, RotatorSelect};
- use $crate::macros::support::Poll::{Ready, Pending};
-
// Safety: nothing must be moved out of `futures`. This is to satisfy
// the requirement of `Pin::new_unchecked` called below.
//
// We can't use the `pin!` macro for this because `futures` is a tuple
// and the standard library provides no way to pin-project to the fields
// of a tuple.
- let mut futures = ( $( maybe_done($e), )* );
+ let mut futures = ( $( $crate::macros::support::maybe_done($e), )* );
// This assignment makes sure that the `poll_fn` closure only has a
// reference to the futures, instead of taking ownership of them. This
// Each time the future created by poll_fn is polled, if not using biased mode,
// a different future is polled first to ensure every future passed to join!
// can make progress even if one of the futures consumes the whole budget.
- let mut rotator = <$rotator_select as RotatorSelect>::Rotator::<{$($total)*}>::default();
+ let mut rotator = <$rotator_select as $crate::macros::support::RotatorSelect>::Rotator::<{$($total)*}>::default();
- poll_fn(move |cx| {
+ $crate::macros::support::poll_fn(move |cx| {
const COUNT: u32 = $($total)*;
let mut is_pending = false;
// Safety: future is stored on the stack above
// and never moved.
- let mut fut = unsafe { Pin::new_unchecked(fut) };
+ let mut fut = unsafe { $crate::macros::support::Pin::new_unchecked(fut) };
// Try polling
- if fut.poll(cx).is_pending() {
+ if $crate::macros::support::Future::poll(fut.as_mut(), cx).is_pending() {
is_pending = true;
}
} else {
}
if is_pending {
- Pending
+ $crate::macros::support::Poll::Pending
} else {
- Ready(($({
+ $crate::macros::support::Poll::Ready(($({
// Extract the future for this branch from the tuple.
let ( $($skip,)* fut, .. ) = &mut futures;
// Safety: future is stored on the stack above
// and never moved.
- let mut fut = unsafe { Pin::new_unchecked(fut) };
+ let mut fut = unsafe { $crate::macros::support::Pin::new_unchecked(fut) };
fut.take_output().expect("expected completed future")
},)*))
$( ( $($skip:tt)* ) $e:expr, )*
}) => {{
- use $crate::macros::support::{maybe_done, poll_fn, Future, Pin, RotatorSelect};
- use $crate::macros::support::Poll::{Ready, Pending};
-
// Safety: nothing must be moved out of `futures`. This is to satisfy
// the requirement of `Pin::new_unchecked` called below.
//
// We can't use the `pin!` macro for this because `futures` is a tuple
// and the standard library provides no way to pin-project to the fields
// of a tuple.
- let mut futures = ( $( maybe_done($e), )* );
+ let mut futures = ( $( $crate::macros::support::maybe_done($e), )* );
// This assignment makes sure that the `poll_fn` closure only has a
// reference to the futures, instead of taking ownership of them. This
// Each time the future created by poll_fn is polled, if not using biased mode,
// a different future is polled first to ensure every future passed to try_join!
// can make progress even if one of the futures consumes the whole budget.
- let mut rotator = <$rotator_select as RotatorSelect>::Rotator::<{$($total)*}>::default();
+ let mut rotator = <$rotator_select as $crate::macros::support::RotatorSelect>::Rotator::<{$($total)*}>::default();
- poll_fn(move |cx| {
+ $crate::macros::support::poll_fn(move |cx| {
const COUNT: u32 = $($total)*;
let mut is_pending = false;
// Safety: future is stored on the stack above
// and never moved.
- let mut fut = unsafe { Pin::new_unchecked(fut) };
+ let mut fut = unsafe { $crate::macros::support::Pin::new_unchecked(fut) };
// Try polling
- if fut.as_mut().poll(cx).is_pending() {
+ if $crate::macros::support::Future::poll(fut.as_mut(), cx).is_pending() {
is_pending = true;
} else if fut.as_mut().output_mut().expect("expected completed future").is_err() {
- return Ready(Err(fut.take_output().expect("expected completed future").err().unwrap()))
+ return $crate::macros::support::Poll::Ready(Err(fut.take_output().expect("expected completed future").err().unwrap()))
}
} else {
// Future skipped, one less future to skip in the next iteration
}
if is_pending {
- Pending
+ $crate::macros::support::Poll::Pending
} else {
- Ready(Ok(($({
+ $crate::macros::support::Poll::Ready(Ok(($({
// Extract the future for this branch from the tuple.
let ( $($skip,)* fut, .. ) = &mut futures;
// Safety: future is stored on the stack above
// and never moved.
- let mut fut = unsafe { Pin::new_unchecked(fut) };
+ let mut fut = unsafe { $crate::macros::support::Pin::new_unchecked(fut) };
fut
.take_output()