Repository navigation
A read-only walk borrows its list when a word shares a slot with a box (#1805) - #1806
Merged
Merged
Conversation
bendlang#1805) A word that is not a box holds no reference. val_arms now collects an arm's borrow label for a slot only where that arm boxes it, and val_own looks a label up only for a box word. Before, a Bool sharing a slot with a String made the slot's labels disagree, and a word read through a box slot (that Bool, or a List<&2, U32>'s head, which the generic Con lays out as a box) owned its root at an owned position. family_arg_hot, family_field_hot and drop_spine shared a value through such a reader. Each now shares it through an owning give, so its C keeps and seals as on main.
val_box handed a non-box word back under its own name, so a List<&2, U32> head put back into a list ([h]) found the label node_fields gave the generic Con head, and the box built from it owned the walk's list. The word now gets a fresh name when it carries a label. lens in brw_mixed_word_slot witnesses it; drop_spine's header is rewrapped. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Lorenzobattistela
approved these changes
Oct 21, 2026
This was referenced Oct 23, 2026
Merged
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.
Fixes #1805.
What changes
A word that is not a box holds no reference, so the borrow analysis now ignores it in the two places the issue names:
val_armsmerges an unboxed match's arms into one set of out slots, and each slot collects one borrow label per arm. An arm now adds a label only where that arm has a box in the slot. Before,Flag'sBooladded""next toHit'shits~0, the labels disagreed, andhits~0became owned.val_ownlooks a word's label up only when the word's kind isbox. With the first change alone, the merged slot keepsHit's label, soFlag'sBool, read back out of that slot, carries it. Passing thatBoolto a call (onsin the new test) made its root owned again.The
val_ownchange also covers a case beyond the issue.lay_nodelays out a generic constructor once, soCon's head is a box field, andnode_fieldslabels it. AList<&2, U32>then reads that head as aU32that still carries the label. So a walk that kept its head across its own call (h + sum(tail)) took its list.The comment above
val_newnow says a non-box word neither roots nor owns.comp.tsgoes from 65,807 to 65,872 ttok (cap 66,000).What it reaches
I built every runnable test, bench and demo to C and JS with main's compiler and with this one:
term_keeps that shared the value go away too, and so do therfc_seals of the types that sharing heated.demos/pure_par_sort:Tree(d)keepsNats inSigma's generic fields.tests/check/data_table_inferred: thesumabove, somain.outno longer keepsxs.tests/run/family_arg_hot,tests/run/family_field_hotandtests/rfc/drop_spine: see below.demos/pure_par_sorton an M3 Max (medians of 7 interleaved runs after a warm-up; both printsorted):-falign-functions=64-falign-functions=64Three tests needed an owner
family_arg_hot,family_field_hotanddrop_spineeach need a value to be shared, so that its type is hot. Each got that sharing from a reader that owned its argument only because of a stray label. With this PR those readers borrow and nothing is shared: each test's C has noterm_keepand norfc_seal. The tests still pass, but they no longer test what they were written for. To show this, I removed each test's guard from scratch copies of both compilers:givefacts_hotwalks a stuck family's argumentsfamily_arg_hot(want 29)emit_ctrheats a hot build's fields (#853)family_field_hot(want 5)Each test now passes the shared value through
give, an identity def that owns what it returns:family_arg_hot:heatisfirst(give(c)) + first(c).family_field_hot:total(s, build(give(s))).drop_spine: the matcher is renamedhead, andfirst(xs)ishead(give(xs)), so each sum owns its copy as before.Each test's C now has main's keeps, seals, takes and
CID_T. I found no removed guard thatdrop_spinecatches: zeroingCID_T's drop column (#1438) passes on main too, with and withoutBEND_POISON. Its header says it shares one copy, and withgiveit does again. Each header gets a line naming its owner.Tests
tests/reg/brw_mixed_word_slot.bendis a borrow witness with three readers: the issue'shits;ons, which passes theBoolto a call; andsumover aList<&2, U32>.mainreads both lists after them. On main all three take; with this PR all three peek. Neither change alone makesonspeek.I ran the gate locally on four shards:
PASS: 1692 / 1694. The two failures,gfx_clicksandgfx_window, expect "no display", and they fail on main here too because this Mac has a desktop session. Repo gate:PASS: 54 / 54.tscreports the same 11 errors as on main.