summaryrefslogtreecommitdiffstats
path: root/third_party/rust/futures-macro/src/executor.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/futures-macro/src/executor.rs')
-rw-r--r--third_party/rust/futures-macro/src/executor.rs56
1 files changed, 56 insertions, 0 deletions
diff --git a/third_party/rust/futures-macro/src/executor.rs b/third_party/rust/futures-macro/src/executor.rs
new file mode 100644
index 0000000000..7f1d0a93f4
--- /dev/null
+++ b/third_party/rust/futures-macro/src/executor.rs
@@ -0,0 +1,56 @@
+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(),
+ None,
+ )];
+
+ let gen = quote! {
+ #[::core::prelude::v1::test]
+ #input
+ };
+
+ gen.into()
+}