Content-address span anchors so definitions that merely move stay green - #97
Draft
xmakro wants to merge 4 commits into
Draft
Content-address span anchors so definitions that merely move stay green#97xmakro wants to merge 4 commits into
xmakro wants to merge 4 commits into
Conversation
xmakro
force-pushed
the
perf/anchor-respan
branch
from
August 6, 2026 06:02
d645986 to
00c78e7
Compare
xmakro
force-pushed
the
perf/offset-span-hashing
branch
2 times, most recently
from
August 6, 2026 08:01
d00cac2 to
d9c211d
Compare
xmakro
force-pushed
the
perf/anchor-respan
branch
2 times, most recently
from
August 6, 2026 11:58
372c8ba to
be63e55
Compare
xmakro
force-pushed
the
perf/offset-span-hashing
branch
from
August 6, 2026 11:58
d9c211d to
deca580
Compare
xmakro
force-pushed
the
perf/anchor-respan
branch
from
August 7, 2026 12:39
be63e55 to
2190174
Compare
xmakro
force-pushed
the
perf/anchor-respan
branch
3 times, most recently
from
August 7, 2026 21:13
96ce91c to
4b14f71
Compare
xmakro
force-pushed
the
perf/anchor-respan
branch
from
August 8, 2026 00:43
4b14f71 to
4a62588
Compare
xmakro
force-pushed
the
perf/anchor-respan
branch
from
August 8, 2026 10:59
4a62588 to
b59ed1e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stacked on #99 (the fused
def_anchordesign), which this depends on. Reworked from the earlier revision of this PR that sat on #91's bucketed channel; thedef_positionquery that revision added is gone, subsumed bydef_anchor.source_span(def)is the anchor every consumer of a definition's relative spans depends on: theSPAN_TRACKcallback records a read of it whenever a parented span is resolved inside a tracked task. Its result fingerprint was the absolute span, so an edit that merely shifted a definition down its file re-fingerprinted the anchor and re-executed every span-carrying consumer below the edit. Early cutoff stopped the cascade before codegen (relative-span fingerprints are position-independent), but the whole front end below the edit still re-ran.This PR content-addresses the anchor.
source_spannow returnsAnchorSpan, a wrapper whose stable hash covers (file, length) and deliberately excludes the offset, so a definition that merely moves keeps a green anchor and its consumers are never re-executed at all. That is sound because every remaining observer of a definition's absolute position is tracked explicitly:source_spanvalue, so decode fidelity never depended on the fingerprint.#[track_caller], debuginfo line tables, coverage, pretty-printed paths in cached diagnostics) depend ondef_anchor(Definition-anchored line-table dependencies for offset-based span hashing #99), which hashes the rendered line index and column of the definition's start along with its extent's line structure. Those are exactly the values a renderer derives from the definition's position, so a move that changes any rendered value goes red through the one anchor node, and a move that changes no rendered value (byte shifts within unchanged line structure) stays green end to end. This is where the fusion pays: the previous revision needed a second per-definition query (def_position) next to the line-table dependency, recorded at every rendering site; here the singledef_anchoredge that Definition-anchored line-table dependencies for offset-based span hashing #99 already records is sufficient, and Definition-anchored line-table dependencies for offset-based span hashing #99's automatic line-observation tracking guarantees that a rendering which somehow escapes the anchor turns its task unconditionally red rather than stale.A load-bearing upstream invariant deserves stating explicitly, because the soundness argument leans on it: under incremental compilation,
rustc_expandparents every macro invocation span to its enclosing definition beforeExpnDatacaptures it ascall_site(collect_invocationsinrustc_expand/src/expand.rs). Body-level macro call sites are therefore parented spans: they hash relative to their enclosing definition, and when a line-rendering consumer reaches one (for examplespan_as_caller_locationwalking toexpansion_cause), the tracked lookup recordsdef_anchorof that enclosing definition. This is what keeps#[track_caller]lines and collapsed debuginfo correct when a function containing a macro invocation moves. The remaining position-bearing residue isExpnData's genuinely parentless spans: macro definition sites, item-level invocation call sites, and the call sites of compiler desugarings. Those keep offset-based fingerprints in this PR (a shifted macro definition still re-fingerprints its uses); content-addressing them is the follow-up in the next PR of the stack.Coverage keeps its single instance anchor. The invariant that makes one anchor per function sufficient (every parented mapping span shares the instance's typeck root) is enforced at runtime by #99's fallback: a mapping span outside the anchored extent costs that codegen task's reuse instead of emitting stale coordinates.
tests/run-make/incr-anchor-movepins the correctness edge: it swaps two byte-identical-length functions, so the line table, both functions' contents, and their relative spans are all unchanged and only their positions swap. Nothing about them re-fingerprints; thedef_anchordependency, through the anchor line index it hashes, is the only thing that refreshes their#[track_caller]lines andDW_AT_decl_lines. The #99 tests and the full incremental suite stay green.Performance
Same-day A/B on the same setup as #99 (instructions:u, jemalloc, 81 cells). Marginal effect of this commit against #99's head:
No cell regresses by 0.25% or more. The win concentrates where the design predicts, in front-end-heavy rebuilds: serde incr-patched improves -1.61% to -1.98% across profiles, with hyper, regex-automata and cargo check incr-patched at -0.33% to -0.70%. The suite's println patches understate the effect because early cutoff already protected codegen; the saving is the below-the-edit front-end re-execution, which grows with crate size and how high in the file the edit lands.
Cumulative for the full reworked stack (#99 + #97 + #98) against the merge-base (fresh base run), 81 cells: full -0.15%, incr-full +0.07%, incr-unchanged -0.47%, incr-patched -4.03%, all cells -1.48%, with 47 cells improved by at least 0.25% and 8 regressed; every check-profile cell improves (serde incr-patched -19.0% to -20.7%). The largest residual is cargo debug incr-unchanged +9.4%, with the rest at or below +1%. See #99 for the trust-tiered anchor design and the staleness bugs the fail-red rework surfaced.