Skip to content

Merge train: #9561 (forEach live-index squeeze defer) - #9563

Merged
proggeramlug merged 2 commits into
mainfrom
land-train79
Sep 2, 2026
Merged

Merge train: #9561 (forEach live-index squeeze defer)#9563
proggeramlug merged 2 commits into
mainfrom
land-train79

Conversation

@proggeramlug

Copy link
Copy Markdown
Contributor

Lands #9561 (a live-index map[i]/set[i] read inside an active forEach walk defers the squeeze instead of compacting under the walk counter — closes the hole #9513's review found) rebased onto main.

Validation: release build green; RUST_TEST_THREADS=1 perry-runtime 3021/0; new fixture and the #9513 multi-delete fixture both byte-identical to node; lint gates green.

Rebase-merge preserving authorship.

Ralph Küpper added 2 commits September 2, 2026 21:15
…tead of shifting the walk

#9504 made the array-like `map[i]` / `set[i]` read a live-index accessor: it
squeezes tombstones so raw index == live index and never hands out a hole.
`forEach` walks the raw entries with a counter that the delete-path squeeze
defers around (the walk registers itself) — but the accessor's squeeze had no
such guard. A callback that deleted already-visited entries and then read
`map[j]` compacted the buffer under the walk's counter, shifting the survivors
below it: with two earlier entries deleted, two later ones were never visited
(18 of 20, Map and Set).

While a walk is active the accessor now defers the squeeze exactly as the
delete path does and resolves the live index by stepping over the tombstones
(O(idx), on a path that is rare by construction); the outermost walk's
completion performs the deferred squeeze as before. Outside a walk the
accessor squeezes as #9504 specified, and #9504's
`a_tombstoned_collection_never_hands_a_hole_to_an_indexed_read` stays green.
The for…of fast path is unaffected: its cursor rebases through the compaction
log (#9513), so a squeeze under it was already exact.

Found by the automated review on #9513, reproduced on merged main.

Tests: `a_live_index_read_inside_foreach_defers_the_squeeze_and_skips_nothing`
for Map and Set (every entry visited once; live values read mid-walk; layout
left alone during the walk, squeezed on completion; the accessor still
squeezes outside a walk) and `test_gap_foreach_live_index_read_no_skip.ts`
(single and nested walks), node-differential. perry-runtime 3018 passed /
0 failed (release, single-threaded); #9504's and #9513's fixtures still match
node; cargo fmt --all --check clean; no clippy warning in the touched files.
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