A dependency in one of my projects was constantly being rebuilt on CI when using only sccache and no target folder caching. One part of that issue looked like non-determinism of .rmeta files.
Here is a minimal repro: https://github.com/jprochazk/rustc-rmeta-repro
client depends on bridge, and transitively depends on proc-macro foo. There is also a foo_extra crate in the same workspace, which does not participate in the dependency graph of client. When libfoo_extra is in /target/debug/deps, it produces a different libclient-<hash>.rmeta than when it's missing.
Here is what I believe is happening:
When client is built, it depends on bridge, which depends on foo, but rustc is not given a path to foo, so it must locate it as well. It searches through the deps dir for libfoo but only finds the .so, because it's a proc-macro. It then attempts to scan every library whose name starts with libfoo. In our case, the directory it scans also contains libfoo_extra. rustc opens and decodes it, and discards it after checking the crate name doesn't match foo. As a side effect, it also interns the foo_extra symbol.
Symbol hashes the interner index. Doc links are resolved after all the crates are loaded, so when doc_link_resolutions is populated, the indices are all shifted by one. The serialization of doc_link_resolutions depends on the iteration order of the map, which is now different due to there being an extra symbol in the interner. The resulting .rmeta file is no longer identical to the one built previously.
Meta
Repros on 1.97.1 and latest nightly as of posting
rustc --version --verbose:
rustc 1.97.1 (8bab26f4f 2026-07-14)
binary: rustc
commit-hash: 8bab26f4f68e0e26f0bb7960be334d5b520ea452
commit-date: 2026-07-14
host: x86_64-unknown-linux-gnu
release: 1.97.1
LLVM version: 22.1.6
rustc 1.99.0-nightly (87e5904f5 2026-07-20)
binary: rustc
commit-hash: 87e5904f5eb6398af6b22eac2802c78934260c48
commit-date: 2026-07-20
host: x86_64-unknown-linux-gnu
release: 1.99.0-nightly
LLVM version: 22.1.8
Previously reported as:
That was closed because it didn't seem like a bug in rustc
A dependency in one of my projects was constantly being rebuilt on CI when using only
sccacheand notargetfolder caching. One part of that issue looked like non-determinism of.rmetafiles.Here is a minimal repro: https://github.com/jprochazk/rustc-rmeta-repro
clientdepends onbridge, and transitively depends on proc-macrofoo. There is also afoo_extracrate in the same workspace, which does not participate in the dependency graph ofclient. Whenlibfoo_extrais in/target/debug/deps, it produces a differentlibclient-<hash>.rmetathan when it's missing.Here is what I believe is happening:
When
clientis built, it depends onbridge, which depends onfoo, butrustcis not given a path tofoo, so it must locate it as well. It searches through the deps dir forlibfoobut only finds the.so, because it's a proc-macro. It then attempts to scan every library whose name starts withlibfoo. In our case, the directory it scans also containslibfoo_extra.rustcopens and decodes it, and discards it after checking the crate name doesn't matchfoo. As a side effect, it also interns thefoo_extrasymbol.Symbolhashes the interner index. Doc links are resolved after all the crates are loaded, so whendoc_link_resolutionsis populated, the indices are all shifted by one. The serialization ofdoc_link_resolutionsdepends on the iteration order of the map, which is now different due to there being an extra symbol in the interner. The resulting.rmetafile is no longer identical to the one built previously.Meta
Repros on 1.97.1 and latest nightly as of posting
rustc --version --verbose:Previously reported as:
That was closed because it didn't seem like a bug in
rustc