What's the best way to create arbitrary identifiers for proc macros?

I have a procedural macro where I have a need to generate a number of macro-internal names. I can't just use preselected names because the number of names is dependent on the input, and hashing the involved input, while theoretically possible, is difficult, as the exact spans of source that would be hashed for each generated name is unclear. Plus, syn AST types don't implement Hash (ultimately because proc_macro tokens don't, IIRC), so if I wanted to hash, it'd have to be via re-printing parts of the tree to a string and hashing that.

That might, however, end up being the best principled way of going about creating arbitrary new identifiers, however. (Note: the names are macro-internal so can reasonably be anything.) Important to being a well-behaved proc macro is that the output is deterministic on the inputs to the macro.

My current solution is to use a static atomic to implement roughly

fn Ident::arbitrary() -> Ident {
    format_ident!("__mylib_{}", atomic.fetch_add(1, Relaxed))

This works great, and actually is deterministic for a single-threaded proc macro... but I have no such guarantee. The compiler is perfectly allowed to invoke two copies of my proc macro in parallel.

(Side note: this might end up being ok because since I'm running the proc macro through watt, the wasm runtime may be fully isolating independent invocations.)

(Side note 2: Thankfully, I don't have to worry about names being unique between two separate invocations of the macro, because it inserts a known name into scope anyway which would conflict. So any invocations of the macro have to be from separate modules for known, external reasons.)

Is there some easier principled way of generating arbitrary identifiers for proc macros? Or do I just have to live with jumping through the hoops necessary to hash a quote::ToTokens's token representation into a formally dependent identifier? (Is there some existing library to make this process easier?)

I mean, if you want deterministic names, you could go for a thread local Cell<usize> and reset it on every call.

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.