1#[allow(unused_extern_crates)]
5extern crate proc_macro;
6
7use proc_macro::TokenStream;
8use proc_macro2::Span;
9use quote::{quote, ToTokens};
10use syn::{parse_macro_input, ItemFn};
11
12#[proc_macro_attribute]
32pub fn future(_args: TokenStream, item: TokenStream) -> TokenStream {
33 let mut input = parse_macro_input!(item as ItemFn);
34
35 if input.sig.asyncness.is_none() {
36 let msg = "only used with `async` function";
37 return syn::Error::new(Span::call_site(), msg)
38 .into_compile_error()
39 .into();
40 }
41
42 make_send_future(&mut input)
43}
44
45fn make_send_future(input: &mut ItemFn) -> TokenStream {
46 let body = input.block.to_token_stream();
47
48 let body_tokens: TokenStream = quote!({
49 let future = unsafe { ::hirun::runtime::SendFuture::new(async move { #body }) };
50 future.await
51 })
52 .into();
53
54 let wrapper = parse_macro_input!(body_tokens as syn::Stmt);
55 input.block.stmts.clear();
56 input.block.stmts.push(wrapper);
57
58 input.to_token_stream().into()
59}
60