Skip to content

Commit e72589e

Browse files
committed
Support reexport for select!/select_biased! macros
1 parent 8772c18 commit e72589e

File tree

6 files changed

+106
-89
lines changed

6 files changed

+106
-89
lines changed

futures-macro/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ pub fn try_join_internal(input: TokenStream) -> TokenStream {
3535

3636
/// The `select!` macro.
3737
#[proc_macro_hack]
38-
pub fn select(input: TokenStream) -> TokenStream {
38+
pub fn select_internal(input: TokenStream) -> TokenStream {
3939
crate::select::select(input)
4040
}
4141

4242
/// The `select_biased!` macro.
4343
#[proc_macro_hack]
44-
pub fn select_biased(input: TokenStream) -> TokenStream {
44+
pub fn select_biased_internal(input: TokenStream) -> TokenStream {
4545
crate::select::select_biased(input)
4646
}

futures-macro/src/select.rs

+20-35
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,14 @@
33
use proc_macro::TokenStream;
44
use proc_macro2::Span;
55
use quote::{format_ident, quote};
6-
use syn::{parenthesized, parse_quote, Expr, Ident, Pat, Token};
6+
use syn::{parse_quote, Expr, Ident, Pat, Token};
77
use syn::parse::{Parse, ParseStream};
88

99
mod kw {
1010
syn::custom_keyword!(complete);
11-
syn::custom_keyword!(futures_crate_path);
1211
}
1312

1413
struct Select {
15-
futures_crate_path: Option<syn::Path>,
1614
// span of `complete`, then expression after `=> ...`
1715
complete: Option<Expr>,
1816
default: Option<Expr>,
@@ -30,23 +28,12 @@ enum CaseKind {
3028
impl Parse for Select {
3129
fn parse(input: ParseStream<'_>) -> syn::Result<Self> {
3230
let mut select = Select {
33-
futures_crate_path: None,
3431
complete: None,
3532
default: None,
3633
normal_fut_exprs: vec![],
3734
normal_fut_handlers: vec![],
3835
};
3936

40-
// When `futures_crate_path(::path::to::futures::lib)` is provided,
41-
// it sets the path through which futures library functions will be
42-
// accessed.
43-
if input.peek(kw::futures_crate_path) {
44-
input.parse::<kw::futures_crate_path>()?;
45-
let content;
46-
parenthesized!(content in input);
47-
select.futures_crate_path = Some(content.parse()?);
48-
}
49-
5037
while !input.is_empty() {
5138
let case_kind = if input.peek(kw::complete) {
5239
// `complete`
@@ -147,8 +134,6 @@ pub(crate) fn select_biased(input: TokenStream) -> TokenStream {
147134
fn select_inner(input: TokenStream, random: bool) -> TokenStream {
148135
let parsed = syn::parse_macro_input!(input as Select);
149136

150-
let futures_crate: syn::Path = parsed.futures_crate_path.unwrap_or_else(|| parse_quote!(::futures_util));
151-
152137
// should be def_site, but that's unstable
153138
let span = Span::call_site();
154139

@@ -175,8 +160,8 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
175160
// We check for this condition here in order to be able to
176161
// safely use Pin::new_unchecked(&mut #path) later on.
177162
future_let_bindings.push(quote! {
178-
#futures_crate::async_await::assert_fused_future(&#path);
179-
#futures_crate::async_await::assert_unpin(&#path);
163+
__futures_crate::async_await::assert_fused_future(&#path);
164+
__futures_crate::async_await::assert_unpin(&#path);
180165
});
181166
path
182167
},
@@ -214,28 +199,28 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
214199
// 2. The Future is created in scope of the select! function and will
215200
// not be moved for the duration of it. It is thereby stack-pinned
216201
quote! {
217-
let mut #variant_name = |__cx: &mut #futures_crate::task::Context<'_>| {
202+
let mut #variant_name = |__cx: &mut __futures_crate::task::Context<'_>| {
218203
let mut #bound_future_name = unsafe {
219204
::core::pin::Pin::new_unchecked(&mut #bound_future_name)
220205
};
221-
if #futures_crate::future::FusedFuture::is_terminated(&#bound_future_name) {
206+
if __futures_crate::future::FusedFuture::is_terminated(&#bound_future_name) {
222207
None
223208
} else {
224-
Some(#futures_crate::future::FutureExt::poll_unpin(
209+
Some(__futures_crate::future::FutureExt::poll_unpin(
225210
&mut #bound_future_name,
226211
__cx,
227212
).map(#enum_ident::#variant_name))
228213
}
229214
};
230215
let #variant_name: &mut dyn FnMut(
231-
&mut #futures_crate::task::Context<'_>
232-
) -> Option<#futures_crate::task::Poll<_>> = &mut #variant_name;
216+
&mut __futures_crate::task::Context<'_>
217+
) -> Option<__futures_crate::task::Poll<_>> = &mut #variant_name;
233218
}
234219
});
235220

236221
let none_polled = if parsed.complete.is_some() {
237222
quote! {
238-
#futures_crate::task::Poll::Ready(#enum_ident::Complete)
223+
__futures_crate::task::Poll::Ready(#enum_ident::Complete)
239224
}
240225
} else {
241226
quote! {
@@ -267,21 +252,21 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
267252
let await_select_fut = if parsed.default.is_some() {
268253
// For select! with default this returns the Poll result
269254
quote! {
270-
__poll_fn(&mut #futures_crate::task::Context::from_waker(
271-
#futures_crate::task::noop_waker_ref()
255+
__poll_fn(&mut __futures_crate::task::Context::from_waker(
256+
__futures_crate::task::noop_waker_ref()
272257
))
273258
}
274259
} else {
275260
quote! {
276-
#futures_crate::future::poll_fn(__poll_fn).await
261+
__futures_crate::future::poll_fn(__poll_fn).await
277262
}
278263
};
279264

280265
let execute_result_expr = if let Some(default_expr) = &parsed.default {
281266
// For select! with default __select_result is a Poll, otherwise not
282267
quote! {
283268
match __select_result {
284-
#futures_crate::task::Poll::Ready(result) => match result {
269+
__futures_crate::task::Poll::Ready(result) => match result {
285270
#branches
286271
},
287272
_ => #default_expr
@@ -297,7 +282,7 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
297282

298283
let shuffle = if random {
299284
quote! {
300-
#futures_crate::async_await::shuffle(&mut __select_arr);
285+
__futures_crate::async_await::shuffle(&mut __select_arr);
301286
}
302287
} else {
303288
quote!()
@@ -309,7 +294,7 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
309294
let __select_result = {
310295
#( #future_let_bindings )*
311296

312-
let mut __poll_fn = |__cx: &mut #futures_crate::task::Context<'_>| {
297+
let mut __poll_fn = |__cx: &mut __futures_crate::task::Context<'_>| {
313298
let mut __any_polled = false;
314299

315300
#( #poll_functions )*
@@ -318,12 +303,12 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
318303
#shuffle
319304
for poller in &mut __select_arr {
320305
let poller: &mut &mut dyn FnMut(
321-
&mut #futures_crate::task::Context<'_>
322-
) -> Option<#futures_crate::task::Poll<_>> = poller;
306+
&mut __futures_crate::task::Context<'_>
307+
) -> Option<__futures_crate::task::Poll<_>> = poller;
323308
match poller(__cx) {
324-
Some(x @ #futures_crate::task::Poll::Ready(_)) =>
309+
Some(x @ __futures_crate::task::Poll::Ready(_)) =>
325310
return x,
326-
Some(#futures_crate::task::Poll::Pending) => {
311+
Some(__futures_crate::task::Poll::Pending) => {
327312
__any_polled = true;
328313
}
329314
None => {}
@@ -333,7 +318,7 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
333318
if !__any_polled {
334319
#none_polled
335320
} else {
336-
#futures_crate::task::Poll::Pending
321+
__futures_crate::task::Poll::Pending
337322
}
338323
};
339324

futures-util/src/async_await/select_mod.rs

+28-7
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
33
use proc_macro_hack::proc_macro_hack;
44

5-
#[doc(hidden)]
6-
#[macro_export]
75
macro_rules! document_select_macro {
86
// This branch is required for `futures 0.3.1`, from before select_biased was introduced
97
($select:item) => {
@@ -158,7 +156,7 @@ macro_rules! document_select_macro {
158156
};
159157

160158
($select:item $select_biased:item) => {
161-
$crate::document_select_macro!($select);
159+
document_select_macro!($select);
162160

163161
/// Polls multiple futures and streams simultaneously, executing the branch
164162
/// for the future that finishes first. Unlike [`select!`], if multiple futures are ready,
@@ -310,11 +308,34 @@ macro_rules! document_select_macro {
310308
};
311309
}
312310

311+
#[cfg(feature = "std")]
312+
#[doc(hidden)]
313+
#[proc_macro_hack(support_nested)]
314+
pub use futures_macro::select_internal;
315+
316+
#[doc(hidden)]
317+
#[proc_macro_hack(support_nested)]
318+
pub use futures_macro::select_biased_internal;
319+
313320
document_select_macro! {
314321
#[cfg(feature = "std")]
315-
#[proc_macro_hack(support_nested)]
316-
pub use futures_macro::select;
322+
#[macro_export]
323+
macro_rules! select {
324+
($($tokens:tt)*) => {{
325+
use $crate::__reexport as __futures_crate;
326+
$crate::select_internal! {
327+
$( $tokens )*
328+
}
329+
}}
330+
}
317331

318-
#[proc_macro_hack(support_nested)]
319-
pub use futures_macro::select_biased;
332+
#[macro_export]
333+
macro_rules! select_biased {
334+
($($tokens:tt)*) => {{
335+
use $crate::__reexport as __futures_crate;
336+
$crate::select_biased_internal! {
337+
$( $tokens )*
338+
}
339+
}}
340+
}
320341
}

futures/src/lib.rs

+3-41
Original file line numberDiff line numberDiff line change
@@ -537,47 +537,9 @@ pub mod never {
537537

538538
// proc-macro re-export --------------------------------------
539539

540-
// Not public API.
541-
#[doc(hidden)]
542-
pub use futures_core::core_reexport;
543-
544-
// Not public API.
545-
#[cfg(feature = "async-await")]
546-
#[doc(hidden)]
547-
pub use futures_util::async_await;
548-
549-
// Not public API.
550-
#[cfg(feature = "async-await")]
551-
#[doc(hidden)]
552-
pub mod inner_macro {
553-
#[cfg(feature = "std")]
554-
pub use futures_util::select;
555-
pub use futures_util::select_biased;
556-
}
557-
558540
#[cfg(feature = "async-await")]
559541
pub use futures_util::{join, try_join};
560-
542+
#[cfg(feature = "std")]
543+
pub use futures_util::select;
561544
#[cfg(feature = "async-await")]
562-
futures_util::document_select_macro! {
563-
#[cfg(feature = "std")]
564-
#[macro_export]
565-
macro_rules! select { // replace `::futures_util` with `::futures` as the crate path
566-
($($tokens:tt)*) => {
567-
$crate::inner_macro::select! {
568-
futures_crate_path ( ::futures )
569-
$( $tokens )*
570-
}
571-
}
572-
}
573-
574-
#[macro_export]
575-
macro_rules! select_biased { // replace `::futures_util` with `::futures` as the crate path
576-
($($tokens:tt)*) => {
577-
$crate::inner_macro::select_biased! {
578-
futures_crate_path ( ::futures )
579-
$( $tokens )*
580-
}
581-
}
582-
}
583-
}
545+
pub use futures_util::select_biased;
+5-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
// normal reexport
2-
pub use futures03::{join, try_join};
2+
pub use futures03::{join, try_join, select, select_biased};
33

44
// reexport + rename
5-
pub use futures03::{join as join2, try_join as try_join2};
5+
pub use futures03::{
6+
join as join2, try_join as try_join2,
7+
select as select2, select_biased as select_biased2,
8+
};

futures/tests/macro-tests/src/main.rs

+48-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Check that it works even if proc-macros are reexported.
22

33
fn main() {
4-
use futures03::executor::block_on;
4+
use futures03::{executor::block_on, future};
55

66
// join! macro
77
let _ = block_on(async {
@@ -18,6 +18,52 @@ fn main() {
1818
Ok::<(), ()>(())
1919
});
2020

21-
// TODO: add select! and select_biased!
21+
// select! macro
22+
let _ = block_on(async {
23+
let mut a = future::ready(());
24+
let mut b = future::pending::<()>();
25+
let _ = futures03::select! {
26+
_ = a => {},
27+
_ = b => unreachable!(),
28+
};
29+
30+
let mut a = future::ready(());
31+
let mut b = future::pending::<()>();
32+
let _ = macro_reexport::select! {
33+
_ = a => {},
34+
_ = b => unreachable!(),
35+
};
36+
37+
let mut a = future::ready(());
38+
let mut b = future::pending::<()>();
39+
let _ = macro_reexport::select2! {
40+
_ = a => {},
41+
_ = b => unreachable!(),
42+
};
43+
});
44+
45+
// select_biased! macro
46+
let _ = block_on(async {
47+
let mut a = future::ready(());
48+
let mut b = future::pending::<()>();
49+
let _ = futures03::select_biased! {
50+
_ = a => {},
51+
_ = b => unreachable!(),
52+
};
53+
54+
let mut a = future::ready(());
55+
let mut b = future::pending::<()>();
56+
let _ = macro_reexport::select_biased! {
57+
_ = a => {},
58+
_ = b => unreachable!(),
59+
};
60+
61+
let mut a = future::ready(());
62+
let mut b = future::pending::<()>();
63+
let _ = macro_reexport::select_biased2! {
64+
_ = a => {},
65+
_ = b => unreachable!(),
66+
};
67+
});
2268

2369
}

0 commit comments

Comments
 (0)