Lin Lee
Lin Lee

Reputation: 253

In a Rust macro, How to follow a symbol to get the token stream of another function's definition?

A macro-decorated function calls another, how to get the callee function's token stream in the macro?

decorated function:

#[follow]
fn caller(){
  return callee();
}

callee:

fn callee(){
  ... // some implementation
}

macro:

#[proc_macro_attribute]
pub fn follow(_metadata: TokenStream, _input: TokenStream) -> TokenStream {
   // how to get callee's token stream here? 
}

Upvotes: 0

Views: 636

Answers (1)

Peter Hall
Peter Hall

Reputation: 58805

Macros can only access the tokens that are provided as input, so this is usually going to be impossible in the general case.

If you are prepared to restructure your code into a module, you could write a set of macros that could be used like this:

#[exec_follow]
mod my_mod {
    #[follow]
    fn caller(){
        return callee();
    }

    fn callee() {
        ... // some implementation
    }
}

The outer macro, exec_follow would receive the entire module as input and rewrite the call to the follow macro to provide the information it needs. For example, exec_follow could output this:

mod my_mod {
    #[follow(source = r"mod my_mod {
    #[follow]
    fn caller(){
        return callee();
    }

    fn callee() {
        ... // some implementation
    }
}")]
    fn caller() {
        return callee();
    }

    fn callee() {
        ... // some implementation
    }
}

This can only work if all of the items are declared in the same module, which needs to be a sub-module of the current one.

There is an open issue to add support for inner attributes as macros, but it is not yet available in stable Rust. This would let you use #![exec_follow] at the top of your file, instead of adding a nested module.

Upvotes: 1

Related Questions