Skip to content

Look for new bugs with a wider fixture - #13

Merged
zmaril merged 2 commits into
mirth/regressionsfrom
mirth/hunt
Oct 7, 2026
Merged

zmaril merged 2 commits into
mirth/regressionsfrom
mirth/hunt

Conversation

@zmaril

@zmaril zmaril commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Stacked on #12.

I ran mirth against the unmodified pinned compiler with a wider fixture, to see whether it finds bugs nobody planted. It found two single-threaded incremental bugs that look new, and rediscovered one known parallel-front-end bug. All three reproduce on the official nightly-2026-10-06 without mirth: run docs/hunt/repro.sh. The write-up is docs/hunt.md; draft upstream reports are docs/hunt/issue-*.md.

finding root cause fix
1 incremental rebuild ≠ clean build: Generics::param_def_id_to_index encoded in a different order HashMap encodes in iteration order and decodes by inserting in that order. With colliding keys, every round trip through the incremental cache rotates the map. make it an FxIndexMap
2 incremental rebuild ≠ clean build: a string literal encoded twice literals are deduplicated when created (allocate_bytes_dedup), but decoding from the cache always makes a fresh AllocId. Regression from rust-lang/rust#116707 (1.90). deduplicate immutable memory on decode
3 two RPITIT traits not reproducible under -Zthreads=8 known: rust-lang/rust#162202 —

Finding 1:

  • Reduced case:
    pub struct Grid<A, B, C>(A, B, C);
    impl<A, B, C> Grid<A, B, C> { pub const AREA: usize = 1; }
  • Real crates: either, smallvec, memchr and arrayvec all show it after a one-line comment edit. The fix makes all four identical.
  • Proof of the mechanism: a standalone HashMap + rustc-hash program reproduces rustc's exact sequence. It's a 3-cycle across incremental sessions.

Finding 2:

  • Reduced case:
    #[inline] pub fn a() -> &'static str { "literal" }
    #[inline] pub fn b() -> &'static str { "literal" }   // edit b's body
  • Bisection: nightly-2025-07-24 is fine and nightly-2025-07-26 is affected; #116707 is between them.
  • Runtime effect: none found. Pointer equality is unchanged and codegen merges identical constants anyway.
  • Correction: my first write-up blamed hygiene data. That was a side effect of decoding cached MIR, and docs/hunt.md is now corrected.

Verification:

  • Regression tests: each fix has a test in rustc's tests/run-make style (docs/hunt/tests/). Each one fails on the pinned compiler, still fails with only the other fix, and passes with its own fix.
  • With both fixes: P6 holds for all ten single-threaded edits. These rustc tests still pass: tests/incremental (180), the metadata UI (532) and run-make (46) tests, tests/ui/{consts,statics,const-generics} (1844) and tests/codegen-llvm (1122). The full test suite was not run.

Not filed upstream. That's your call. Fix 2 dedups more than strictly needed, and its semantics should be checked by someone who knows the const-eval memory model. The report says so.

🤖 Generated with Claude Code

https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh

zmaril and others added 2 commits October 7, 2026 16:17
fixtures/wide adds a proc-macro crate, a build script, derives, const
generics, a GAT, impl Trait and async fn in traits and an exported macro,
with ten edits. rustc/hunt.sh builds a fixture repeatedly with -Zthreads=8
and checks P6 after each edit, with -Zincremental-verify-ich, single-threaded
and threaded.

docs/hunt.md has what it found in the unmodified compiler, each reduced and
reproducible with the official nightly by docs/hunt/repro.sh: incremental
rebuilds encode Generics::param_def_id_to_index in a different order from
clean builds (docs/hunt/generics-index-map.patch fixes it); incremental
rebuilds of a crate using a proc-macro derive encode hygiene data clean
builds do not (not root-caused); and two RPITIT traits are not
reproducible under -Zthreads (known, #162202).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
Finding 1: HashMap's Encodable writes iteration order and Decodable collects
in that order, so Generics::param_def_id_to_index rotates every time
generics_of goes through the incremental cache when its keys collide. A
standalone program with std HashMap and rustc-hash reproduces rustc's
sequence exactly. Four real crates show it; FxIndexMap fixes all four.

Finding 2 was not hygiene data. String literals share an AllocId through
allocate_bytes_dedup, but decoding a memory allocation from the cache
always reserves a fresh one, so a rebuild encodes the literal twice.
Reduced to two lines; regression from #116707, bisected between
nightly-2025-07-24 and nightly-2025-07-26.

docs/hunt/issue-*.md are draft reports. Each fix has a run-make style test
that fails before it and passes after, and with both fixes P6 holds for all
ten single-threaded edits while rustc's incremental, metadata UI and
run-make, consts/statics/const-generics UI and codegen-llvm tests pass.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Mnrg9JXj9X1ht6Qkz2ybh
@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