"Linker shenanigans." I'm not the best person to explain it, @dtolnay would be the one who understands how the linkme implementation works the best.
But the short version, as I understand it, is:
With linker shenanigans:
- In creating a distributed slice "registry" called NAME, we set up three linker sections, the exact name and method of which are platform dependent, but we'll call
__linkme_NAME,__linkme_start_NAME, and__linkme_end_NAME. - We ask the linker to lay these sections out such that
__linkme_start_NAMEis directly followed by__linkme_NAMEwhich is then directly followed by__linkme_end_NAME. - Each item put in the distributed slice is (of known, verified type and) placed as a
staticin the__linkme_NAMEsection. - Again through platform/linker-specific tricks, we define
statics that reside in the__linkme_start_NAMEand__linkme_end_NAMEsections. - We at runtime use those two
statics to create our slice; we effectively have a "first before the start" and "first past the end" pointer from which to derive our linker-assembled slice.
This is almost certainly actually UB in a strict sense, as the Rust Abstract Machine doesn't have a concept of what we're doing here. In practice, this is closer to platform-defined behavior.
With compiler support, it would work much the same way, except that because the compiler itself knows about it, it wouldn't require platform linker support, just rustc linker support. At a high level,
- The registry crate defines a distributed slice as a
static. - Any
staticwhich is placed in the distributed slice is marked specially in the rlib as being part of the distributed slice. - When rustc is invoked to link together the rlibs into an executable, it first finds all of the statics marked as part of the distributed slice, and orchestrates the platform-specific operations to put them in a continuous statically allocated slice. This may be linker directives on some platforms (e.g. the ones linkme already supports), or it may be in directly reässembling the individual static sections into one static section (and references from the children back to the parent) before handing it off to the platform linker.
- Notably, the Abstract Machine is now dealing with an actual slice of linktime determined size, rather than seeing you accessing outside of these
statics you've defined, so it's no longer strictly speaking UB, and there's no danger of future optimizations breaking the behavior.
All of this of course only works with static linking.