rustrust-macrosrust-proc-macros

Is it possible to store state within Rust's procedural macros?


Is it possible to build a macro that doesn't output anything but instead for example stores state to build up a list and then a second macro that will then actually use that data and output some result?

For example:

trait SomeTrait {}

#[derive(mark)]
struct Person {}

impl SomeTrait for Person {}

#[derive(mark)]
struct Item {}

impl SomeTrait for Item  {}

#[derive(mark)]
struct Object {}

impl SomeTrait for Object {}

create_mapper!() // this then outputs the below function
//assuming for the fact that data is loaded correctly before this macro is used

fn select_item(kind: String) -> impl SomeTrait {
    match kind {
        "person" => Person,
        "item" => Item,
        "object" => Object,        
    }
}

Solution

  • Currently there is no officially supported way to store state that can be used by two different proc macro invocations. I created this very related issue where this problem is discussed.

    Storing state is certainly possible, but just in a hacky way. You could, for example, serialize all your state into /tmp/my-state. Or you could try using static global variables. But even if this works now, this is not guaranteed to work in the future. Another problem: due to incremental compilation, it is not guaranteed that all of your proc macro invocations are actually executed. So if you have one macro that generates the state and one that reads it, if the first is not executed, really strange things happen. So it is technically possible to store global state, but it's not advisable.

    In the issue linked above, you can see that MSleepyPanda proposed a possible solution, but we are far from having this implemented.