How to call `ItemFn` inside attribute macro?

#[proc_macro_attribute]
pub fn rust_decorator(attr: TokenStream, input: TokenStream) -> TokenStream {
    let func = parse_macro_input!(input as syn::ItemFn);
    // here how to run or call func, like func()

I write a macro and convert input to syn::ItemFn, but I don't know how to run or call func inside rust_decorator function.

Based on the documentation, func.sig.ident is the name of the function, so you can just write something like

let fn_name = &func.sig.ident;

quote!{
    #fn_name();
}

It doesn't work :joy: :joy:

In what way does it not work?

If you actually want to call the function during compile time, that simply isn't possible.

In the attribute macro you only get the tokens etc. that make up the function, but the function cannot be called.

1 Like

I was assuming OP knows that and by "calling" the function s/he meant "emitting code that calls the function". At least that's the behavior I would expect based on the "decorator" in the name of the macro.

You could try this code, is here some problem?

Well obviously:

  1. You are ignoring and discading the result of quote!{}. You have to return the resulting token stream if you want it to be emitted in the macro output. Currently, the return value of your macro is the function itself verbatim, so your macro doesn't actually do anything.
  2. You can't just arbitrarily paste expressions at the top level (the macro output has to be valid Rust code). If you place a bare function call at the top level, it won't compile, just like it wouldn't if you wrote the identical code by hand. So you have to decide how/where exactly you want to perform the call and emit code accordingly.

I'm assuming you want to write a decorator that does the println!("aaaa"); but otherwise it just invokes the function unmodified. You can do that in two ways:

  • you can insert the println!() statement into the beginning of the block of the function. This is a quick hack but it works for such a simple decorator.
  • or you have to change the name of the original function, emit the decorator with the original name, and generate the decorator's body in a way that it first performs the printing, and then invokes the function with its original arguments.
1 Like

I got it! :+1:

Thank you! :+1:

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.