Skip to content

Instantly share code, notes, and snippets.

@rklaehn
Last active March 4, 2020 13:22
Show Gist options
  • Save rklaehn/7cec8b3faf6902e69b7fbcac4ca2a5c6 to your computer and use it in GitHub Desktop.
Save rklaehn/7cec8b3faf6902e69b7fbcac4ca2a5c6 to your computer and use it in GitHub Desktop.
How the select! macro expands
use futures::{future::FutureExt, select};
async fn a() {}
async fn b() {}
async fn test() {
select! {
a = a().fuse() => println!("a"),
b = b().fuse() => println!("b"),
}
}
#[async_std::main]
async fn main() -> std::io::Result<()> {
Ok(test().await)
}
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
use futures::{future::FutureExt, select};
async fn a() {}
async fn b() {}
async fn test() {
{
enum ProcMacroHack {
Nested = ( "futures_crate_path (:: futures) a = a () . fuse () => println ! (\"a\"), b = b\n() . fuse () => println ! (\"b\")," , 0 ) . 1 , }
{
enum __PrivResult<_0, _1> {
_0(_0),
_1(_1),
}
let __select_result = {
let mut _0 = a().fuse();
let mut _1 = b().fuse();
let mut __poll_fn = |__cx: &mut ::futures::task::Context<'_>| {
let mut __any_polled = false;
let mut _0 = |__cx: &mut ::futures::task::Context<'_>| {
let mut _0 = unsafe { ::core::pin::Pin::new_unchecked(&mut _0) };
if ::futures::future::FusedFuture::is_terminated(&_0) {
None
} else {
Some(
::futures::future::FutureExt::poll_unpin(&mut _0, __cx)
.map(__PrivResult::_0),
)
}
};
let _0: &mut dyn FnMut(
&mut ::futures::task::Context<'_>,
)
-> Option<::futures::task::Poll<_>> = &mut _0;
let mut _1 = |__cx: &mut ::futures::task::Context<'_>| {
let mut _1 = unsafe { ::core::pin::Pin::new_unchecked(&mut _1) };
if ::futures::future::FusedFuture::is_terminated(&_1) {
None
} else {
Some(
::futures::future::FutureExt::poll_unpin(&mut _1, __cx)
.map(__PrivResult::_1),
)
}
};
let _1: &mut dyn FnMut(
&mut ::futures::task::Context<'_>,
)
-> Option<::futures::task::Poll<_>> = &mut _1;
let mut __select_arr = [_0, _1];
::futures::async_await::shuffle(&mut __select_arr);
for poller in &mut __select_arr {
let poller: &mut &mut dyn FnMut(
&mut ::futures::task::Context<'_>,
)
-> Option<::futures::task::Poll<_>> = poller;
match poller(__cx) {
Some(x @ ::futures::task::Poll::Ready(_)) => return x,
Some(::futures::task::Poll::Pending) => {
__any_polled = true;
}
None => {}
}
}
if !__any_polled {
{
::std::rt::begin_panic(
"all futures in select! were completed,\
but no `complete =>` handler was provided",
&("src/main.rs", 8u32, 5u32),
)
}
} else {
::futures::task::Poll::Pending
}
};
::futures::future::poll_fn(__poll_fn).await
};
match __select_result {
__PrivResult::_0(a) => {
::std::io::_print(::core::fmt::Arguments::new_v1(
&["a\n"],
&match () {
() => [],
},
));
}
__PrivResult::_1(b) => {
::std::io::_print(::core::fmt::Arguments::new_v1(
&["b\n"],
&match () {
() => [],
},
));
}
}
}
}
}
fn main() -> std::io::Result<()> {
async fn main() -> std::io::Result<()> {
{
Ok(test().await)
}
}
async_std::task::block_on(async { main().await })
}
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
extern crate std;
use futures::{future::FutureExt, select_biased};
async fn a() {}
async fn b() {}
async fn test() {
{
enum ProcMacroHack {
Nested = ( "futures_crate_path (:: futures) a = a () . fuse () => println ! (\"a\"), b = b\n() . fuse () => println ! (\"b\")," , 0 ) . 1 , }
{
enum __PrivResult<_0, _1> {
_0(_0),
_1(_1),
}
let __select_result = {
let mut _0 = a().fuse();
let mut _1 = b().fuse();
let mut __poll_fn = |__cx: &mut ::futures::task::Context<'_>| {
let mut __any_polled = false;
let mut _0 = |__cx: &mut ::futures::task::Context<'_>| {
let mut _0 = unsafe { ::core::pin::Pin::new_unchecked(&mut _0) };
if ::futures::future::FusedFuture::is_terminated(&_0) {
None
} else {
Some(
::futures::future::FutureExt::poll_unpin(&mut _0, __cx)
.map(__PrivResult::_0),
)
}
};
let _0: &mut dyn FnMut(
&mut ::futures::task::Context<'_>,
)
-> Option<::futures::task::Poll<_>> = &mut _0;
let mut _1 = |__cx: &mut ::futures::task::Context<'_>| {
let mut _1 = unsafe { ::core::pin::Pin::new_unchecked(&mut _1) };
if ::futures::future::FusedFuture::is_terminated(&_1) {
None
} else {
Some(
::futures::future::FutureExt::poll_unpin(&mut _1, __cx)
.map(__PrivResult::_1),
)
}
};
let _1: &mut dyn FnMut(
&mut ::futures::task::Context<'_>,
)
-> Option<::futures::task::Poll<_>> = &mut _1;
let mut __select_arr = [_0, _1];
for poller in &mut __select_arr {
let poller: &mut &mut dyn FnMut(
&mut ::futures::task::Context<'_>,
)
-> Option<::futures::task::Poll<_>> = poller;
match poller(__cx) {
Some(x @ ::futures::task::Poll::Ready(_)) => return x,
Some(::futures::task::Poll::Pending) => {
__any_polled = true;
}
None => {}
}
}
if !__any_polled {
{
::std::rt::begin_panic(
"all futures in select! were completed,\
but no `complete =>` handler was provided",
&("src/main.rs", 8u32, 5u32),
)
}
} else {
::futures::task::Poll::Pending
}
};
::futures::future::poll_fn(__poll_fn).await
};
match __select_result {
__PrivResult::_0(a) => {
::std::io::_print(::core::fmt::Arguments::new_v1(
&["a\n"],
&match () {
() => [],
},
));
}
__PrivResult::_1(b) => {
::std::io::_print(::core::fmt::Arguments::new_v1(
&["b\n"],
&match () {
() => [],
},
));
}
}
}
}
}
fn main() -> std::io::Result<()> {
async fn main() -> std::io::Result<()> {
{
Ok(test().await)
}
}
async_std::task::block_on(async { main().await })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment