macro_rules! sym {
($sym:ident) => { ... };
($sym:literal) => { ... };
(@impl $sym:expr) => { ... };
}Expand description
Create a literal symbol from a literal identifier or string
Symbols created with the sym!(...) macro are statically
allocated and deduplicated on program startup. This means that there is no
discernible overhead at the point of use, making them suitable even in long
chains of if statements and inner loops.
IMPORTANT: For this macro to work in a particular crate, the
enable!() macro must appear exactly once in the crate’s
root. This creates the global registration table at link-time.
§Safety
This macro is safe (and performant) to use everywhere, with important caveats:
-
If you are using “static initializers” (code that runs before
main(), like through thectorcrate), this macro must NOT be called in such a static initializer function. See https://github.com/mmastrac/rust-ctor/issues/159. UsingSymbol::new()in such a function is fine. -
If you are using C-style dynamic libraries (
cdylibcrate type), those libraries must use thestringleton-dylibcrate instead ofstringleton. -
If you are loading dynamic libraries at runtime (i.e., outside of Cargo’s dependency graph), the host crate must also use the
stringleton-dylibcrate instead ofstringleton.
§Low-level details
This macro creates an entry in a per-crate linkme “distributed slice”, as
well as a static initializer called by the OS when the current crate is
loaded at runtime (before main()), either as part of an executable or as
part of a dynamic library.
On x86-64 and ARM64, this macro is guaranteed to compile into a single
relaxed atomic memory load instruction from an offset in the .bss segment.
On x86, relaxed atomic load instructions have no additional overhead
compared to non-atomic loads.
Internally, this uses the linkme and ctor crates to register this
callsite in static binary memory and initialize it on startup. However, when
running under Miri (or other platforms not supported by linkme), the
implementation falls back on a slower implementation that effectively calls
Symbol::new() every time, which takes a global read-lock.
When the debug-assertions feature is enabled, there is an additional check
that panics if the call site has not been populated by a static ctor. This
assertion will only be triggered if the current platform does not support
static initializers.