Skip to content

Check reuse and report untracked reads inside rustc; findings 6 and 7 - #18

Merged
zmaril merged 25 commits into
mirth/scalefrom
mirth/verify-reuse
Oct 7, 2026
Merged

zmaril merged 25 commits into
mirth/scalefrom
mirth/verify-reuse

Conversation

@zmaril

@zmaril zmaril commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #17.

The check. docs/hunt/verify-reuse.patch (against the pinned rustc), on under RUSTC_VERIFY_REUSE, checks what an incremental session reused:

  • reused metadata is encoded again and compared byte for byte;
  • at the end of the session, every green value of a query cached on disk is computed again and compared by stable hash, normalized Debug text and standalone cache encoding, plus which allocations values share;
  • a reused codegen unit is generated again and its unoptimized IR compared with the one kept when it was generated.

With each of the three earlier fixes reverted it reports that bug; with all three it is quiet apart from two benign patterns (docs/shadow-mode.md). rustc/fuzz.py and rustc/replay.py set it on every build.

Untracked reads. docs/hunt/report-untracked.patch, on under RUSTC_REPORT_UNTRACKED, reports every read of an [UNTRACKED] option, of source file contents or of the crate store's crate-wide state inside a task whose result may be reused, unless the task declared it (docs/untracked-reads.md). On one ordinary sink build it names finding 5's three options and finding 6, plus three more untracked options, folded into finding 5: -Zno-leak-check (an incremental rebuild accepts a program a clean build rejects), -C extra-filename (reused metadata keeps the old value, since 1.90) and -Zfuture-incompat-test.

New bugs, with reports, reproductions in docs/hunt/repro.sh and run-make tests that fail on the pinned compiler (no fixes: each fix is a maintainer's trade-off):

  • 6 reused object code keeps an edited file's old checksum in its debuginfo, and with -Zembed-source the old file; with optimizations the binary's ThinLTO symbol names differ from a clean build's. Since 1.44; Cranelift too.
  • 7 warnings from inline assembly, and optimization remarks, are not shown again when a rebuild reuses the codegen unit. Since at least 1.60.

Harness. fuzz.py --check (cargo check), --p5-builds (a second clean build tells nondeterminism from P6), replay.py --rustflags; runs under other flags, threads (with fixtures/sink-threads.patch working around #162202) and real crates as fixtures; an Ur query for finding 6's pattern.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh

@zmaril zmaril changed the title A patch that checks reuse inside rustc Check reuse inside rustc; findings 6 and 7 Oct 7, 2026
@zmaril zmaril changed the title Check reuse inside rustc; findings 6 and 7 Check reuse and report untracked reads inside rustc; findings 6 and 7 Oct 7, 2026
@zmaril
zmaril added this pull request to stack #19 October 7, 2026 20:17
zmaril and others added 25 commits October 7, 2026 16:17
…uild

docs/hunt/verify-reuse.patch: under RUSTC_VERIFY_REUSE, reused metadata is
encoded again and compared, and at the end of the session every green
cached query value is computed again and compared by stable hash, Debug
text and encoding, plus which allocations values share. With each of the
three fixes reverted it reports that bug; with all three it is quiet.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
… embedded source

Found by a short fuzz run at -Copt-level=2: binaries differed from clean
builds only in ThinLTO's .llvm.<hash> suffixes, because a reused codegen
unit's DIFile has the previous MD5 of the edited file. With -Zembed-source
the object embeds the previous file. Report drafted, reproduction added to
repro.sh. The fuzzer now names allocation-sharing findings by their queries.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
sourceContentRead flags reads of a source file's contents or hash. Over the
compiler it finds finding 6, the same reads in rustc_codegen_cranelift
(confirmed: with -Zembed-source its rebuilt object embeds the old file),
and the metadata site of finding 4.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
verify-reuse.patch now also keeps each generated codegen unit's
unoptimized IR and, when a later session reuses the unit, generates it
again and compares (srcloc cookies left out). It flags finding 6 under
-Zembed-source and is quiet on sink. Looking at its srcloc noise led to
finding 7: warnings LLVM reports for inline assembly are not shown again
when the unit is reused (1.60 through the nightly). Report, repro and a
run-make test that fails on the pinned compiler.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
…) from P6

The threads fixture also loses its async fns (rust-lang/rust#162202).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
docs/hunt/report-untracked.patch: under RUSTC_REPORT_UNTRACKED, a read of
an [UNTRACKED] option, of source file contents, or of the crate store's
crate-wide state inside a task whose result may be reused is reported,
unless the task declared it. On one sink build it names finding 5's three
options and finding 6, and two new ones: -Zno-leak-check (an incremental
rebuild accepts a program a clean build rejects) and -C extra-filename
(reused metadata keeps the old value, since 1.90). fuzz.py and replay.py
collect the lines in untracked.txt.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
… option

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
… crates

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
…erated

all recomputes values computed this session too: none of 575,658 in a
clean regex build differs, nor in the other crates or a threaded build.
eval_static_initializer is no longer recomputed (it can make a definition).
report-untracked.patch had been generated against the pinned commit and
so contained everything; it is now relative to the fixes and the check,
and the stack reproduces the compiler tree exactly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
… from text

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
…things

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
…allocation twice

Found by fuzzing with -Zmir-opt-level=4, named by the reuse check's sharing
report (now printing the allocation), reduced automatically to three lines.
On 1.60.0 through the nightly.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
…en-patches.sh

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
@zmaril
zmaril force-pushed the mirth/verify-reuse branch from 6d85c70 to cf7b264 Compare October 7, 2026 20:17
@zmaril
zmaril merged commit da368aa into main Oct 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant