简体   繁体   中英

Is there a consistent compilation context inside a proc_macro_attribute function?

Take the example below:

static COUNT: AtomicUsize = AtomicUsize::new(0);

#[proc_macro_attribute]
pub fn count_usages(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let c = COUNT.fetch_add(1, Ordering::AcqRel);
    println!("Do stuff with c: {}", c);
    item
}

Although the order attributes are processed may differ, will the final count be the same each time for cases such as:

  • Incremental building
  • Registry crates and local crates sharing the same proc_macro library and version
  • Compiler internal parallelism

A practical use case (mine in particular) is generating a compile-time pseudo-static variable memory layout that will be reused in multiple memory managers within a statically linked executable.

While some things might work with the current implementation, procedural macros should not use global variables and expect them to be preserved between calls.

There is currently no official mechanism for storing state between invocations of a procedural macro.

The issue “Crate local state for procedural macros?” mentions some of these points:

  • Proc macros may not be run on every compilation, for instance if incremental compilation is on and they are in a module that is clean
  • There is no guarantee of ordering -- if do_it! needs data from all config! invocations, that's a problem.
  • Properly supporting this feature means adding a new API

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM