fix(query): avoid cyclic package docs deadlock - #2681
Draft
Myriad-Dreamin wants to merge 26 commits into
Draft
Conversation
Myriad-Dreamin
force-pushed
the
fix-package-docs-type-check-deadlock
branch
3 times, most recently
from
July 31, 2026 13:38
47351fd to
b4fa737
Compare
Myriad-Dreamin
force-pushed
the
fix-package-docs-type-check-deadlock
branch
from
July 31, 2026 14:19
b4fa737 to
bd047c0
Compare
Myriad-Dreamin
marked this pull request as draft
August 3, 2026 09:42
Dynamic SCC maintenance and atomic batch publication are unchanged; only the staleness mechanism is simplified: - A merge now eagerly relabels member files to a fresh group id and removes the merged groups, so a stored group id is always live and no find/path-compression layer is needed. - Sealed constituents are retracted with an atomic tombstone flag in the same critical section that relabels their members, replacing the root-canonicity check; `is_current` becomes a lock-free flag read. - The cycle region for a closing edge is computed with per-candidate forward searches instead of building a reverse edge index. - The pdg tests move to pdg_tests.rs unchanged in coverage. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Cyclic coordination remains covered by the package docs tests. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- Drop the eager component_vars pre-population; the lazy path in component_var creates the identical shared variable on first reference, and the env outlives all members of the batch. - Extract the repeated missing-member panic into component_member. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The check-then-publish sequence let a concurrent late-edge merge land between the ownership check, the dependency-identity reads, and the history publication. A retracted owner could publish an obsolete batch (computed with no-wait fallbacks), and the dependency read on a merged group answered None, panicking expr_history_key. The window predates the tombstone refactor: the union-find version also took separate lock acquisitions for each step. - Add ComponentCoordinator::commit_current: verifies ownership by pointer identity against the live group and runs the publication in the same critical section as the reads, so no merge can interleave. Expression and type batches both publish through it. - Add member_dependencies for one consistent snapshot on the reuse path; a retracted owner yields None (cache miss + retry) instead of a panic. expr_history_key becomes a pure function of the snapshot. - Restore the reverse-index backward search in add_edge; the per-candidate forward searches degraded to O(N^2) when a long chain closed a cycle. - Cover the retract/commit linearization with a coordinator test. Nesting the cache locks under the coordinator mutex is one-directional: no path holds an IncrCacheMap lock while acquiring the coordinator. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Package-scan reruns produced different inferred types for identical input. Two ordering substrates leaked scheduling into results: - Interned hashes by pointer address, so the HashTrieSet bound sets in DynTypeBounds iterated in allocation order; checker invocation order over receiver bounds then depended on thread interleaving. The bound sets become RedBlackTreeSetSync, iterating in content order. - The default Decl ordering compared raw file-id and span identities, which are assigned in interning order. Every sort built on it (iter_union, freeze, transform_let) was schedule-dependent; the codebase already carried the content-stable strict_cmp marked 'free from the concurrency issue' and a 'todo: buggy' on TypeVar::cmp. Decl and TypeVar now order by strict_cmp, with an equal-id fast path so same-file comparisons stay cheap. - Interned<InsTy> ordering compared only values; an ordered set would merge instances that pointer equality keeps apart. Ties now break on syntax-source content (not spans, whose identities are unstable). Known remaining suspect, deliberately deferred: BuiltinTy derives Ord through typst's Element/Type; if those compare by static address, they vary per process (ASLR) and will show up as residual scan diffs. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
SyntaxNode::into_text does not exist in this typst fork; the memoized name accessor covers leaf and inner nodes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The package-scan rerun at cb2d611 cut the nondeterministic type diffs from 193 to 175 rows but confirmed remaining flips, and pinned them on cmp_value: functions and args compared raw span identities, modules compared raw file ids, and color/content/symbol/styles/dyn fell back to address comparison. All of these depend on interning or allocation order, so sorts recursing through Interned<InsTy> stayed schedule-dependent even after the container and Decl fixes. - Functions order by name, then content-stable span (file path plus in-file span), then element name or display representation. - Args and modules use the content-stable span/file-id comparisons. - Types order by long name instead of typst's Ord. - Every pointer fallback becomes a display-representation comparison; distinct values with an identical representation now compare equal, which an ordered set may collapse — acceptable, as they also render identically wherever a type is shown. StrictCmp is promoted to pub(crate) for reuse; ptr_cmp is gone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Uh oh!
There was an error while loading. Please reload this page.