summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoel Galenson <jgalenson@google.com>2021-05-19 15:24:01 -0700
committerJoel Galenson <jgalenson@google.com>2021-05-19 15:24:01 -0700
commitb266ecd6f4900b7fb2155e3d70e7422a589dc4b3 (patch)
treeed3bef133f9eb60fe9198597b0ea91adb2c40bfb /src
parent1fbf099cfb309b9d6f353f3a6f33e005d03bbe60 (diff)
downloadfutures-macro-b266ecd6f4900b7fb2155e3d70e7422a589dc4b3.tar.gz
Upgrade rust/crates/futures-macro to 0.3.15
Test: make Change-Id: I545461552c040bb57aab52e2ee9947f05a929f5f
Diffstat (limited to 'src')
-rw-r--r--src/executor.rs55
-rw-r--r--src/join.rs5
-rw-r--r--src/lib.rs21
-rw-r--r--src/select.rs42
4 files changed, 93 insertions, 30 deletions
diff --git a/src/executor.rs b/src/executor.rs
new file mode 100644
index 0000000..40a091f
--- /dev/null
+++ b/src/executor.rs
@@ -0,0 +1,55 @@
+use proc_macro::TokenStream;
+use proc_macro2::Span;
+use quote::{quote, quote_spanned, ToTokens};
+
+pub(crate) fn test(args: TokenStream, item: TokenStream) -> TokenStream {
+ if !args.is_empty() {
+ return syn::Error::new_spanned(proc_macro2::TokenStream::from(args), "invalid argument")
+ .to_compile_error()
+ .into();
+ }
+
+ let mut input = syn::parse_macro_input!(item as syn::ItemFn);
+
+ if input.sig.asyncness.take().is_none() {
+ return syn::Error::new_spanned(input.sig.fn_token, "Only async functions are supported")
+ .to_compile_error()
+ .into();
+ }
+
+ // If type mismatch occurs, the current rustc points to the last statement.
+ let (last_stmt_start_span, last_stmt_end_span) = {
+ let mut last_stmt = input
+ .block
+ .stmts
+ .last()
+ .map(ToTokens::into_token_stream)
+ .unwrap_or_default()
+ .into_iter();
+ // `Span` on stable Rust has a limitation that only points to the first
+ // token, not the whole tokens. We can work around this limitation by
+ // using the first/last span of the tokens like
+ // `syn::Error::new_spanned` does.
+ let start = last_stmt.next().map_or_else(Span::call_site, |t| t.span());
+ let end = last_stmt.last().map_or(start, |t| t.span());
+ (start, end)
+ };
+
+ let path = quote_spanned! {last_stmt_start_span=>
+ ::futures_test::__private
+ };
+ let body = &input.block;
+ input.block.stmts = vec![syn::Stmt::Expr(
+ syn::parse2(quote_spanned! {last_stmt_end_span=>
+ #path::block_on(async #body)
+ })
+ .unwrap(),
+ )];
+
+ let gen = quote! {
+ #[::core::prelude::v1::test]
+ #input
+ };
+
+ gen.into()
+}
diff --git a/src/join.rs b/src/join.rs
index 048b62a..d427da2 100644
--- a/src/join.rs
+++ b/src/join.rs
@@ -27,10 +27,7 @@ impl Parse for Join {
}
}
-fn bind_futures(
- fut_exprs: Vec<Expr>,
- span: Span,
-) -> (Vec<TokenStream2>, Vec<Ident>) {
+fn bind_futures(fut_exprs: Vec<Expr>, span: Span) -> (Vec<TokenStream2>, Vec<Ident>) {
let mut future_let_bindings = Vec::with_capacity(fut_exprs.len());
let future_names: Vec<_> = fut_exprs
.into_iter()
diff --git a/src/lib.rs b/src/lib.rs
index 5f0c47c..8835de4 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -13,31 +13,42 @@
extern crate proc_macro;
use proc_macro::TokenStream;
-use proc_macro_hack::proc_macro_hack;
+mod executor;
mod join;
mod select;
/// The `join!` macro.
-#[proc_macro_hack]
+#[cfg_attr(fn_like_proc_macro, proc_macro)]
+#[cfg_attr(not(fn_like_proc_macro), proc_macro_hack::proc_macro_hack)]
pub fn join_internal(input: TokenStream) -> TokenStream {
crate::join::join(input)
}
/// The `try_join!` macro.
-#[proc_macro_hack]
+#[cfg_attr(fn_like_proc_macro, proc_macro)]
+#[cfg_attr(not(fn_like_proc_macro), proc_macro_hack::proc_macro_hack)]
pub fn try_join_internal(input: TokenStream) -> TokenStream {
crate::join::try_join(input)
}
/// The `select!` macro.
-#[proc_macro_hack]
+#[cfg_attr(fn_like_proc_macro, proc_macro)]
+#[cfg_attr(not(fn_like_proc_macro), proc_macro_hack::proc_macro_hack)]
pub fn select_internal(input: TokenStream) -> TokenStream {
crate::select::select(input)
}
/// The `select_biased!` macro.
-#[proc_macro_hack]
+#[cfg_attr(fn_like_proc_macro, proc_macro)]
+#[cfg_attr(not(fn_like_proc_macro), proc_macro_hack::proc_macro_hack)]
pub fn select_biased_internal(input: TokenStream) -> TokenStream {
crate::select::select_biased(input)
}
+
+// TODO: Change this to doc comment once rustdoc bug fixed.
+// The `test` attribute.
+#[proc_macro_attribute]
+pub fn test_internal(input: TokenStream, item: TokenStream) -> TokenStream {
+ crate::executor::test(input, item)
+}
diff --git a/src/select.rs b/src/select.rs
index 65b3187..0c8e5f1 100644
--- a/src/select.rs
+++ b/src/select.rs
@@ -3,8 +3,8 @@
use proc_macro::TokenStream;
use proc_macro2::Span;
use quote::{format_ident, quote};
-use syn::{parse_quote, Expr, Ident, Pat, Token};
use syn::parse::{Parse, ParseStream};
+use syn::{parse_quote, Expr, Ident, Pat, Token};
mod kw {
syn::custom_keyword!(complete);
@@ -63,7 +63,10 @@ impl Parse for Select {
// Commas after the expression are only optional if it's a `Block`
// or it is the last branch in the `match`.
- let is_block = match expr { Expr::Block(_) => true, _ => false };
+ let is_block = match expr {
+ Expr::Block(_) => true,
+ _ => false,
+ };
if is_block || input.is_empty() {
input.parse::<Option<Token![,]>>()?;
} else {
@@ -76,7 +79,7 @@ impl Parse for Select {
CaseKind::Normal(pat, fut_expr) => {
select.normal_fut_exprs.push(fut_expr);
select.normal_fut_handlers.push((pat, expr));
- },
+ }
}
}
@@ -92,22 +95,16 @@ fn declare_result_enum(
result_ident: Ident,
variants: usize,
complete: bool,
- span: Span
+ span: Span,
) -> (Vec<Ident>, syn::ItemEnum) {
// "_0", "_1", "_2"
let variant_names: Vec<Ident> =
- (0..variants)
- .map(|num| format_ident!("_{}", num, span = span))
- .collect();
+ (0..variants).map(|num| format_ident!("_{}", num, span = span)).collect();
let type_parameters = &variant_names;
let variants = &variant_names;
- let complete_variant = if complete {
- Some(quote!(Complete))
- } else {
- None
- };
+ let complete_variant = if complete { Some(quote!(Complete)) } else { None };
let enum_item = parse_quote! {
enum #result_ident<#(#type_parameters,)*> {
@@ -148,7 +145,9 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
// bind non-`Ident` future exprs w/ `let`
let mut future_let_bindings = Vec::with_capacity(parsed.normal_fut_exprs.len());
- let bound_future_names: Vec<_> = parsed.normal_fut_exprs.into_iter()
+ let bound_future_names: Vec<_> = parsed
+ .normal_fut_exprs
+ .into_iter()
.zip(variant_names.iter())
.map(|(expr, variant_name)| {
match expr {
@@ -164,7 +163,7 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
__futures_crate::async_await::assert_unpin(&#path);
});
path
- },
+ }
_ => {
// Bind and pin the resulting Future on the stack. This is
// necessary to support direct select! calls on !Unpin
@@ -188,8 +187,8 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
// For each future, make an `&mut dyn FnMut(&mut Context<'_>) -> Option<Poll<__PrivResult<...>>`
// to use for polling that individual future. These will then be put in an array.
- let poll_functions = bound_future_names.iter().zip(variant_names.iter())
- .map(|(bound_future_name, variant_name)| {
+ let poll_functions = bound_future_names.iter().zip(variant_names.iter()).map(
+ |(bound_future_name, variant_name)| {
// Below we lazily create the Pin on the Future below.
// This is done in order to avoid allocating memory in the generator
// for the Pin variable.
@@ -216,7 +215,8 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
&mut __futures_crate::task::Context<'_>
) -> __futures_crate::Option<__futures_crate::task::Poll<_>> = &mut #variant_name;
}
- });
+ },
+ );
let none_polled = if parsed.complete.is_some() {
quote! {
@@ -229,13 +229,13 @@ fn select_inner(input: TokenStream, random: bool) -> TokenStream {
}
};
- let branches = parsed.normal_fut_handlers.into_iter()
- .zip(variant_names.iter())
- .map(|((pat, expr), variant_name)| {
+ let branches = parsed.normal_fut_handlers.into_iter().zip(variant_names.iter()).map(
+ |((pat, expr), variant_name)| {
quote! {
#enum_ident::#variant_name(#pat) => { #expr },
}
- });
+ },
+ );
let branches = quote! { #( #branches )* };
let complete_branch = parsed.complete.map(|complete_expr| {