diff --git a/futures-util/src/async_await/join.rs b/futures-util/src/async_await/join.rs index 3e3f536ff9..06883d6991 100644 --- a/futures-util/src/async_await/join.rs +++ b/futures-util/src/async_await/join.rs @@ -28,23 +28,21 @@ macro_rules! join { let mut $fut = $crate::future::maybe_done($fut); $crate::pin_mut!($fut); )* - loop { + await!($crate::future::poll_fn(move |cx| { let mut all_done = true; $( - if $crate::poll!($fut.reborrow()).is_pending() { + if $crate::core_reexport::future::Future::poll($fut.reborrow(), cx).is_pending() { all_done = false; } )* if all_done { - break; + $crate::core_reexport::task::Poll::Ready(($( + $fut.reborrow().take_output().unwrap(), + )*)) } else { - $crate::pending!(); + $crate::core_reexport::task::Poll::Pending } - } - - ($( - $fut.reborrow().take_output().unwrap(), - )*) + })) } } } @@ -94,30 +92,35 @@ macro_rules! try_join { let mut $fut = $crate::future::maybe_done($fut); $crate::pin_mut!($fut); )* - let res: $crate::core_reexport::result::Result<(), _> = loop { + + let res: $crate::core_reexport::result::Result<_, _> = await!($crate::future::poll_fn(move |cx| { let mut all_done = true; $( - if $crate::poll!($fut.reborrow()).is_pending() { + if $crate::core_reexport::future::Future::poll($fut.reborrow(), cx).is_pending() { all_done = false; } else if $fut.reborrow().output_mut().unwrap().is_err() { // `.err().unwrap()` rather than `.unwrap_err()` so that we don't introduce // a `T: Debug` bound. - break $crate::core_reexport::result::Result::Err( - $fut.reborrow().take_output().unwrap().err().unwrap() + return $crate::core_reexport::task::Poll::Ready( + $crate::core_reexport::result::Result::Err( + $fut.reborrow().take_output().unwrap().err().unwrap() + ) ); } )* if all_done { - break $crate::core_reexport::result::Result::Ok(()); + $crate::core_reexport::task::Poll::Ready( + $crate::core_reexport::result::Result::Ok(($( + // `.ok().unwrap()` rather than `.unwrap()` so that we don't introduce + // an `E: Debug` bound. + $fut.reborrow().take_output().unwrap().ok().unwrap(), + )*)) + ) } else { - $crate::pending!(); + $crate::core_reexport::task::Poll::Pending } - }; + })); - res.map(|()| ($( - // `.ok().unwrap()` rather than `.unwrap()` so that we don't introduce - // an `E: Debug` bound. - $fut.reborrow().take_output().unwrap().ok().unwrap(), - )*)) + res } } } diff --git a/futures-util/src/async_await/mod.rs b/futures-util/src/async_await/mod.rs index 1dcc5f01b5..307e254024 100644 --- a/futures-util/src/async_await/mod.rs +++ b/futures-util/src/async_await/mod.rs @@ -21,4 +21,5 @@ mod join; mod select; #[doc(hidden)] +#[inline(always)] pub fn assert_unpin(_: &T) {} diff --git a/futures-util/src/async_await/select.rs b/futures-util/src/async_await/select.rs index ae86c4a85c..8b84d2fd5d 100644 --- a/futures-util/src/async_await/select.rs +++ b/futures-util/src/async_await/select.rs @@ -47,16 +47,18 @@ macro_rules! select { )* } - let __priv_res = loop { + let __priv_res = await!($crate::future::poll_fn(|cx| { $( - let poll_res = $crate::poll!($crate::core_reexport::mem::PinMut::new( - &mut $name)); - if let $crate::core_reexport::task::Poll::Ready(x) = poll_res { - break __PrivResult::$name(x); + match $crate::core_reexport::future::Future::poll( + $crate::core_reexport::mem::PinMut::new(&mut $name), cx) + { + $crate::core_reexport::task::Poll::Ready(x) => + return $crate::core_reexport::task::Poll::Ready(__PrivResult::$name(x)), + $crate::core_reexport::task::Poll::Pending => {}, } )* - $crate::pending!(); - }; + $crate::core_reexport::task::Poll::Pending + })); match __priv_res { $( __PrivResult::$name($name) => { diff --git a/futures/tests/async_await_macros.rs b/futures/tests/async_await_macros.rs index 706d4d23df..b74d56a8e0 100644 --- a/futures/tests/async_await_macros.rs +++ b/futures/tests/async_await_macros.rs @@ -1,6 +1,6 @@ #![feature(async_await, await_macro, pin, arbitrary_self_types, futures_api)] -use futures::{Poll, pending, poll, pin_mut, join, select}; +use futures::{Poll, future, pending, poll, pin_mut, join, try_join, select}; use futures::channel::oneshot; use futures::executor::block_on; @@ -75,3 +75,56 @@ fn select_can_move_uncompleted_futures() { }); assert!(ran); } + +#[test] +fn select_size() { + let fut = async { + let mut ready = future::ready(0i32); + select! { + ready => {}, + } + }; + assert_eq!(::std::mem::size_of_val(&fut), 40); + + let fut = async { + let mut ready1 = future::ready(0i32); + let mut ready2 = future::ready(0i32); + select! { + ready1 => {}, + ready2 => {}, + } + }; + assert_eq!(::std::mem::size_of_val(&fut), 56); +} + +#[test] +fn join_size() { + let fut = async { + let ready = future::ready(0i32); + join!(ready) + }; + assert_eq!(::std::mem::size_of_val(&fut), 40); + + let fut = async { + let ready1 = future::ready(0i32); + let ready2 = future::ready(0i32); + join!(ready1, ready2) + }; + assert_eq!(::std::mem::size_of_val(&fut), 64); +} + +#[test] +fn try_join_size() { + let fut = async { + let ready = future::ready(Ok::(0)); + try_join!(ready) + }; + assert_eq!(::std::mem::size_of_val(&fut), 40); + + let fut = async { + let ready1 = future::ready(Ok::(0)); + let ready2 = future::ready(Ok::(0)); + try_join!(ready1, ready2) + }; + assert_eq!(::std::mem::size_of_val(&fut), 64); +}