# Get unique identifier inside macro

**URL:** <https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071>\
**Category:** Uncategorized\
**Created:** [July 23, 2022, 2:28pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071 "2022-07-23T14:28:57Z")\
**Posts on this page:** 17\
**Page:** 1

<div class="post-metadata">

**Author:** ![madsmtm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/madsmtm/32/8455_2.png) [@madsmtm](https://internals.rust-lang.org/u/madsmtm)\
**Post date:** [July 23, 2022, 2:28pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/1 "2022-07-23T14:28:57Z")

</div>

Macros that generate statics with special `link_section`s/`export_name`s often need some way to output a unique identifier along with this data (similar to how, if you write `static X: u8 = 2;`, Rust mangles the name to prevent it from clashing with other statics of the same name).

Two examples:

- Objective-C generates statics that start with special names `L_OBJC_METH_VAR_NAME_` and `L_OBJC_SELECTOR_REFERENCES_` and then has a unique identifier afterwards - a crate that wants to emulate this needs to do so as well (see [`objc2`'s implementation](https://github.com/madsmtm/objc2/blob/909bffa361311eab8cc72a75e6a691ac7de9d16e/objc2/src/macros.rs#L239)).
- The popular `defmt` crate needs to output different statics when given the same input, see [knurling-rs/defmt#344](https://github.com/knurling-rs/defmt/issues/344) and [the entry in their book](https://defmt.ferrous-systems.com/duplicates.html)

The current approach in both of these cases is to create a `proc-macro` that hashes the `Debug` output of a `proc_macro::Span` (since that currently includes line/column information), but this is obviously very brittle!

Concretely, it would be nice if there was a way such that the following would work:

```rust
// Input
foo!();
foo!();

// Outputs
{
  #[link_section = ".foo.[SOME_UNIQUE_HEX_1]"]
  static FOO: u8 = 0;
}
{
  #[link_section = ".foo.[SOME_UNIQUE_HEX_2]"]
  static FOO: u8 = 0;
}

```

Regarding the stable-ness of the identifier, I wouldn't expect any guarantees (e.g. it would be allowed to change between compiler invocations), though it _should_ attempt to at the very least be deterministic.

---

<div class="post-metadata">

**Author:** ![madsmtm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/madsmtm/32/8455_2.png) [@madsmtm](https://internals.rust-lang.org/u/madsmtm)\
**Post date:** [July 23, 2022, 2:33pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/2 "2022-07-23T14:33:52Z")

</div>

An `impl Hash for proc_macro::Span` could solve this issue somewhat nicely, in that users can freely chose the format of the identifier (e.g. if it should be in hexadecimal, only integers, UTF-8 unicode, or whatever).

Another idea would be a `unique_int!() -> usize/u128` macro, this would allow `macro_rules!` macros to use the functionality as well (and allowing it to be used within `const` evaluation).

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [July 23, 2022, 3:30pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/3 "2022-07-23T15:30:30Z")

</div>

Hashing spans isn't enough either, unfortunately; consider

```rust
macro_rules! twice {
    ($x:item) => ($x $x);
}

twice!(foo!{});

```

The easiest solution is probably `Ident::fresh() -> Self`.

Or alternatively, def-site hygiene makes the items not conflict, [e.g.](https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=ac13059a02385bcf9469daf895618299). My original intuition was that the two def sites are the same and can share symbols, but that's not the case as implemented; the def site is scoped to the defining item, not the defining scope/module/namespace.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 23, 2022, 7:17pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/4 "2022-07-23T19:17:06Z")

</div>

> [@madsmtm](#):
>
> Another idea would be a `unique_int!() -> usize/u128` macro, this would allow `macro_rules!` macros to use the functionality as well (and allowing it to be used within `const` evaluation).

This seems like the right answer to me as well. The most challenging bit here seems like bikeshedding the name (and to a slight extent the return type). 🙂

There's precedent for this in other languages, as well; for instance, C extensions have ` __COUNTER__ `, and Lisps use `gensym`.

I would propose that we call this `unique_id!()`, and have it return a unique `u64` for each invocation site.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [July 23, 2022, 7:37pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/5 "2022-07-23T19:37:36Z")

</div>

I don't see how a macro would help in the OP usecase? You can't emit something like `#[link_section = concat!(".foo.", unique_int!())]`.

---

<div class="post-metadata">

**Author:** ![josh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/josh/32/5934_2.png) [@josh](https://internals.rust-lang.org/u/josh)\
**Post date:** [July 23, 2022, 8:02pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/6 "2022-07-23T20:02:14Z")

</div>

```rust
/tmp$ cat section_test.rs
#[link_section = concat!("unique_section_", stringify!(123))]
#[used]
static FOO: u8 = 123;
/tmp$ rustc --crate-type staticlib --emit obj section_test.rs
/tmp$ objdump -x section_test.o

section_test.o: file format elf64-x86-64
section_test.o
architecture: i386:x86-64, flags 0x00000010:
HAS_SYMS
start address 0x0000000000000000

Sections:
Idx Name Size VMA LMA File off Algn
  0 .text 00000000 0000000000000000 0000000000000000 00000040 2**2
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 unique_section_123 00000001 0000000000000000 0000000000000000 00000040 2**0
                  CONTENTS, ALLOC, LOAD, READONLY, DATA
  2 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000041 2**0
                  CONTENTS, READONLY
SYMBOL TABLE:
0000000000000000 l df *ABS*	0000000000000000 section_test.d0add785-cgu.0
0000000000000000 l O unique_section_123	0000000000000001 _ZN12section_test3FOO17h5adf25b41a35f966E

```

We just need a unique number to substitute for the `123`.

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [July 23, 2022, 9:37pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/7 "2022-07-23T21:37:41Z")

</div>

But `concat!(".foo.", stringify!(unique_int!()))` will just give `.foo.unique_int ! ()`. That would also need the ability to force early expansion.

EDIT: Also, I don't see any way this could be unique across multiple compilation units, which seems necessary for section names.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [July 24, 2022, 1:37am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/8 "2022-07-24T01:37:12Z")

</div>

Could it be derived from the ABI hash that gets mangled into symbols for the crate? That would also help the reproducible builds story I imagine.

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [July 24, 2022, 2:19am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/9 "2022-07-24T02:19:11Z")

</div>

> [@madsmtm](#):
>
> similar to how, if you write `static X: u8 = 2;`, Rust mangles the name to prevent it from clashing with other statics of the same name

Why not lean further into this? The Rust mangling (esp. v0) is already prepared for handling pretty much everything already, you just don't have a way to combine it with your additional needs.

Plausible bikeshed:

```rust
#[link_section(mangled(prefix = ".foo."))]
static ...

```

This is so much easier to implement, since the compiler has access to the symbol name and can interpret the attribute to generate the unique section, it's much better for debugging, works perfectly wrt deterministic builds, incremental, etc.

Whereas macros that expand to something different every time create a lot more issues than they solve.

I know we don't have incremental macro expansion yet, but we have to be careful not to make it unnecessarily harder, and stateful macros are dangerous for that.

We're still worried about what fallout might occur once we start being able to use one process (or wasm VM instance) per proc macro _invocation_, if there is enough global state in existing proc macros (though for `thread_local!` state, we're only weeks away from starting to test it out).

Thankfully we never guaranteed an order of execution between invocations, or that proc macro invocations share threads/processes, but lack of enforcement for these many years can be misinterpreted as permission.

---

<div class="post-metadata">

**Author:** ![bjorn3](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bjorn3/32/2736_2.png) [@bjorn3](https://internals.rust-lang.org/u/bjorn3)\
**Post date:** [July 24, 2022, 7:45am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/10 "2022-07-24T07:45:01Z")

</div>

> [@mathstuf](#):
>
> Could it be derived from the ABI hash that gets mangled into symbols for the crate? That would also help the reproducible builds story I imagine.

Not for a macro. Macros need to be expanded first before this hash can be calculated. If on the other hand it is an argument to `asm!()`, it would be possible as at codegen time the crate hash is known.

---

<div class="post-metadata">

**Author:** ![Kixunil](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kixunil/32/4110_2.png) [@Kixunil](https://internals.rust-lang.org/u/Kixunil)\
**Post date:** [August 3, 2022, 9:43am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/11 "2022-08-03T09:43:27Z")

</div>

I happened to come across a case where this would be useful but with a bit more guarantees:

- the ids start at 0 and increase by 1, it's just not guaranteed which invocation gets which id
- invocations in distinct places (macros) can share ID. This must not be relied for comparisons between different macros and such but the idea is if you write a macro with a single `unique_int!()` invocation and invoke it e.g. 5 times you're guaranteed to get ids 0, 1, 2, 3, 4 in undefined order. (IOW the counter is not shared among all macros)

Motivation: I'd like the IDs to fit 6 bits. Yes, if the macro is called more than 64 times it should fail to compile. This is not an issue because it's not public, it's just for convenience.

Also `{integer}` is probably better than any specific type.

---

<div class="post-metadata">

**Author:** ![madsmtm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/madsmtm/32/8455_2.png) [@madsmtm](https://internals.rust-lang.org/u/madsmtm)\
**Post date:** [August 10, 2022, 2:01pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/12 "2022-08-10T14:01:57Z")

</div>

> [@eddyb](#):
>
> ```rust
> #[link_section(mangled(prefix = ".foo."))]
> static ...
> 
> ```

Honestly, I feel like this idea is perfect, would solve both of my presented use-cases cleanly, and as you noted, wouldn't run into all the other issues with nondeterministic macros.

I doubt I have the required knowledge, but I could be interested in trying to implemented it. Would it make sense for me to write an RFC or something with the idea first?

---

<div class="post-metadata">

**Author:** ![eddyb](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/eddyb/32/8411_2.png) [@eddyb](https://internals.rust-lang.org/u/eddyb)\
**Post date:** [August 11, 2022, 4:17am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/13 "2022-08-11T04:17:18Z")

</div>

I'm not sure an RFC is needed to start experimenting (some things go through compiler-team "MCPs" nowadays), but it wouldn't hurt, especially from the perspective of having it stabilized sooner than later.

The relevant part of the implementation for `#[link_name]`/`#[export_name]` is this:

> <https://github.com/rust-lang/rust/blob/908fc5b26d15fc96d630ab921e70b2db77a532c4/compiler/rustc_symbol_mangling/src/lib.rs#L207-L216>

If `attrs` indicates anything interesting should happen (that is, `CodegenAttrs` definition/computation elsewhere would need to be adjusted), you can pretty much just call `v0::mangle(tcx, instance, None)` in the code above, and combine that with e.g. a prefix.

The section part is sadly more ad-hoc:

> <https://github.com/rust-lang/rust/blob/f03ce30962cf1b2a5158667eabae8bf6e8d1cb03/compiler/rustc_codegen_llvm/src/base.rs#L143-L149>

So it would likely need to get a query like `symbol_name` (provided by `rustc_symbol_mangling` as well, so that it can actually do any mangling), but for the section.

It's not a huge difference, but I would still suggest first prototyping it for symbol names (e.g. adding the ability of having a mangled symbol with a prefix), and only then move onto section names.

---

<div class="post-metadata">

**Author:** ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)\
**Post date:** [August 11, 2022, 4:33am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/14 "2022-08-11T04:33:46Z")

</div>

I feel both these use cases are actually better served by creating a language equivalent of the linkme crate, instead of writing hacks around linker sections....

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [August 11, 2022, 8:21am UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/15 "2022-08-11T08:21:48Z")

</div>

While this may be true, proper distributed slice support will be much harder to get into the language due to portability of techniques in the face of separate compilation.

Whereas `link_section`'s behavior is inherently platform specific, and "provide this link name" is an extremely portable bit of vocabulary.

I can second that this would be an MCP for roughly permission\[1\] to implement, and that stabilizing could _probably_ be done with just a T-lang FCP.

* * *

1. obviously you can do whatever in your own fork, but talking about possibility of merging

---

<div class="post-metadata">

**Author:** ![madsmtm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/madsmtm/32/8455_2.png) [@madsmtm](https://internals.rust-lang.org/u/madsmtm)\
**Post date:** [August 12, 2022, 12:01pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/16 "2022-08-12T12:01:33Z")

</div>

Thanks for the guidance! Busy times rn, but will try to take a stab at it at some point.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [November 10, 2022, 12:01pm UTC](https://internals.rust-lang.org/t/get-unique-identifier-inside-macro/17071/17 "2022-11-10T12:01:40Z")

</div>

Closed on November 10, 2022, 12:01pm UTC

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