Conversation
bendlang#948) WORDS and the printed-kind table are indexed by a datatype's name, so a datatype named __proto__, constructor or toString read an inherited member instead of undefined: lay_of returned the prototype object and both emitters died in lay.ks.length, and the show descriptor held a function where a kind belongs. OPERATIONS and OPTIMIZED, the compiler's other user-indexed tables, already have null prototypes; these two now do too.
…ng#948) The type argument and the Array cell reach the same name-indexed tables and failed on their own (lay.ks.length, lay.ks.some). A constructor and a field named for a prototype member compile without the fix and are a control on its scope.
valueOf and hasOwnProperty inherit functions through the same lookup, so a table answering only the three reported names would still leave them broken. One nesting per name, over the layout and the printed kind.
VerificationAdversarial verification by a fresh run at head Environment. Every test on the branch, both arms
Transcripts: The hole: row B6 was closed by argument, and it was a real discriminatorThe body argued that Mutants — the load-bearing claim re-derived independently
Neither half alone passes — confirmed. Row B8 ( The control controls something
Rows converted from argument to measurement
The artefact, not the exit codePer the rule the hunt itself produced: each proto-named program was built alongside a twin with the prototype names mechanically renamed to ordinary ones, both lanes, names normalised back, files diffed. Byte-identical output was the bar, not a clean exit. C lane — upgraded from "entirely unexecuted" to "emission measured"
The compiled binary remains unmeasured; the body says so in Regression sweep and behaviour outside the stated bugEvery file in The diff was read for behaviour outside the stated bug: it is two Prior art re-run at this gate (16:55Z): issue bendlang#948 still OPEN, 0 comments, no labels, no linked PR. CI: Verdict: verified at Rules: run-the-artefact-the-fix-produces=covered(twin-artefact byte diff, .js and .c, both programs) | mutate-the-rejected-alternatives=covered(M1/M2/M3, each with named killers) | ledger-row-needs-its-fixture=covered(proto_name_value_of.bend for B6) | unreachable-row-same-bytes=covered(B7 and B17 measured unreachable at the parser, not argued) | control-returns-its-own-input=covered(proto_name_ctor_field is the only test M1 spares) | dispatch-arm-boundary-coverage=covered(JS lane executed end-to-end; C lane emission measured on all three arms, binary declared unmeasured) | prior-art-recheck-at-gate=covered(re-run 16:55Z, unchanged) | multi-assert-base-arm=unreachable(each test is one .bend file with one |
sprayberry-redline
left a comment
There was a problem hiding this comment.
Automated review from the Sprayberry Labs fleet code reviewer.
Reviewed by the GPT gating lane (gating review).
Verdict: ready for the operator; no blocking issues found.
I traced the base failure through bend2/comp.ts:985, where WORDS[t.k] ?? ... treats inherited Object.prototype members as valid layouts, and through the base printed-kind lookup at bend2/comp.ts:1304-1305. The changed lines correctly make both datatype-name-indexed tables null-prototype tables:
bend2/comp.ts:169-171:const WORDS: Record<string, Lay> = Object.setPrototypeOf(/{ U32: W32, F32: W32, Nat: W64 }, null);bend2/comp.ts:175-177:const SHOWN: Record<string, number> = Object.setPrototypeOf(/{ U32: 0, F32: 1, Nat: 2, Char: 3, String: 4, Array: 6 }, null);bend2/comp.ts:1313:const kind = SHOWN[adt.k] ?? 7;
This preserves owned keys, including the falsy valid SHOWN["U32"] === 0, while allowing unowned prototype-named datatypes to reach the existing fallbacks. The added compile fixtures cover the original inherited-key path, parameterized and Array-cell call paths, additional inherited names, and a constructor/field scope control. I independently read the base implementation and upstream issue bendlang#948, re-ran prior-art searches for the bug terms, checked the facts sheet, boundary ledger, policy quotes, labels, and commit messages. There are no reported fork CI checks; the PR body explicitly records the unavailable C binary and cluster-gate coverage.
What's good: the change follows the file's existing null-prototype-table idiom and fixes the downstream show_main table as well as the reported WORDS lookup, preventing a clean build from producing a broken emitted artifact.
Notes for the operator:
- Upstream description-format requirements, if any emerge at submission time, should be applied to the upstream PR body; the fork facts sheet already contains the relevant evidence.
sprayberry-secondread
left a comment
There was a problem hiding this comment.
Automated review from the Sprayberry Labs fleet code reviewer.
Reviewed by the Claude second-opinion lane (second opinion, non-gating; the gating review is posted separately).
The lookup repair is sound by inspection, but this candidate is not ready for submission: remove patch-history commentary from the fixtures, and note that upstream has now independently fixed this bug.
Finding 1 — medium: committed comments narrate the patch rather than the test contract
Exact changed locations:
tests/compile/proto_name_array_cell.bend:3-5:# by lay_el, which died in lay.ks.some rather than lay.ks.length. The/# array must reach the printed result: reading one element alone walks/# no layout and compiles on base.tests/compile/proto_name_ctor_field.bend:1-5:# (control) a CONSTRUCTOR and a FIELD named after an Object.prototype/# member compile on base too: only a DATATYPE's name indexes WORDS and/# the printed-kind table, and a constructor's own emitted key is already/# a computed property. This pins the fix's scope -- it must not need to/# change, and must not break, the constructor and field name paths.tests/compile/proto_name_datatype.bend:3-6:# inherited member for it. WORDS gave __proto__ the prototype object/# instead of undefined, so lay_of returned a non-Lay and both emitters/# died in lay.ks.length; the printed-kind table gave toString a/# function, which left the emitted show descriptor holding no cells.tests/compile/proto_name_type_param.bend:3:# so it broke where the flat case did (lay_of -> lay.ks.length).tests/compile/proto_name_value_of.bend:1-5:# the Object.prototype members the issue does not name reach the same...# them either. One nesting per name, so a table that answered only the/# three reported names would still die here.bend2/comp.ts:166-168,172-173:// A datatype's name indexes this table, so it has a null prototype:and// other: a datatype's name indexes it, so it is null-prototyped too.repeat and argue the immediately following implementation.
Submission failure scenario: the fixtures carry base-versus-patch narration and an argument for the fix's scope into the permanent suite, rather than simply documenting the language behavior each program exercises. Keep the A/B evidence in the PR description. This is a submission-hygiene finding, not a claim that the implementation fails at runtime.
Suggested fix:
Replace the fixture headers with short behavioral descriptions:
Array cells with prototype-member datatype names.
Prototype-member constructor and field names.
Nested datatypes named __proto__, constructor and toString.
A parameterized datatype named __proto__.
Nested datatypes named valueOf, hasOwnProperty and propertyIsEnumerable.
Drop the implementation-justification comments above WORDS.
Describe SHOWN only as the runtime's printed datatype kinds, if needed.
Keep historical failures and control classification in the PR evidence.
Upstream status and maintainer fit
My fresh searches for 948 and "null prototype" in upstream PRs returned no matches, but the module's commit history finds direct prior art: 9969b56d7490ffb18446475b0fea97ec23590677, “A wide record, a hidden cycle and a datatype named proto all compile.” It explicitly fixes bendlang#948 using a null-prototype WORDS and a list-based printer kind lookup. Current upstream source contains both repairs; #948 is closed. The fork body's “OPEN” status is stale. Do not submit this as an unfixed upstream bug; check whether any remaining regression coverage is useful separately. This status note is not counted as another code finding.
The module-level SHOWN table is a reasonable immutable lookup, not a per-book cache, and avoids allocating a literal for every node. The null-prototype idiom already appears in OPERATIONS/OPTIMIZED. Upstream has since chosen a different printer representation; that is concrete integration evidence, not a reason to call this representation incorrect.
I read the recent module history and merged outside PRs #855, #844, #861, and the file list for #958. bendlang#844 adds a 38-line compile fixture for a small layout repair; bendlang#855 adds separate fixtures for different compiler paths. Separate files for datatype, type-parameter, and Array-cell paths are therefore defensible, as are the short snake_case names and #| outputs used by neighboring fixtures. AGENTS.md specifies that format and leaves bend2/bend.ts human-written; this patch respects both. I found no basis in that guidance to demand a changelog, issue-first step, or squash. The declarative title fits recent compiler commit subjects. The five fixtures total 145 lines against an 11-line production addition; the path distinctions justify executable coverage, but not the lengthy explanatory headers flagged above.
Independently rebuilt boundaries and assertion read
The production diff adds no numeric bounds or loops. Its changed operations are the two table initializations and SHOWN[adt.k] ?? 7; WORDS consumers acquire new lookup semantics without textual changes.
| Operation / boundary input | Fixed behavior | Pin or reachability |
|---|---|---|
| WORDS owned names U32/F32/Nat | Same W32/W32/W64 objects | All new fixtures contain U32; existing f32_table_nan_bits covers F32. Nat remains an unchanged owned entry. |
| WORDS inherited names: proto, constructor, toString | Missing entry; existing fallback computes a Lay | proto_name_datatype; parameterized path in proto_name_type_param |
| WORDS valueOf/hasOwnProperty/propertyIsEnumerable | Same missing-entry fallback | proto_name_value_of |
| WORDS ordinary missing name | Normal layout computation | Box in proto_name_ctor_field |
| WORDS through Array element layout | Same repaired lookup via lay_el | proto_name_array_cell |
| SHOWN owned value zero (U32) | Preserves 0, not fallback 7 | U32 output fields in every fixture |
| SHOWN other owned values 1/2/3/4/6 | Preserves built-in kind | Array kind 6 in proto_name_array_cell; remaining entries unchanged, existing built-in coverage |
| SHOWN missing/inherited name yields undefined | Coalesces to kind 7 and emits constructor descriptors | Nested printed values in datatype/value_of/type_param/array_cell fixtures |
| Empty string, null/undefined name, empty collection | Not a source datatype identifier; null ADT is refused before SHOWN access | Guard at comp.ts:1310 and source identifier contract; no new source case |
| Negative, zero, limit, limit+1, maximum numeric key | No numeric index or limit introduced; name lookup, not array indexing | Numeric data does not become adt.k; no new numeric boundary |
| Constructor/field names rather than datatype names | Not keys of the changed tables | proto_name_ctor_field |
| JS versus C; interpreter | Shared layout/descriptor repair for emitters; interpreter unaffected | Fixtures run across lanes in gates/test.ts; local C binary evidence remains absent |
| Repeated books / module lifetime | SHOWN has only constant built-in entries, no per-book mutation | Static read of table and sole reader; no new stateful branch |
I read every new #| assertion: (T{C{P{35}}, 7}, 42), (W{9}, 9), ([E{4}], 7), (Q{H{V{20}}, 22}, 42), and (__proto__{5}, 5). The first four force the problematic datatype into the printed result, not merely into a computation that could disappear before descriptor construction. They distinguish the base compiler failure in both emitter paths by static trace. The constructor/field fixture is intentionally non-discriminating and protects a separate unchanged surface, not evidence that the datatype bug is fixed. Interpreter results are likewise controls, not regression proof for compilation.
What is good / limits
I can confirm the original bug from the removed base lines and their consumers: WORDS["__proto__"] returns Object.prototype rather than a Lay; repairing only that table still lets the old printer lookup return a function for toString, bypassing kind 7. Both fixes belong together. I found no new correctness defect in the executable change.
Reviewed the full diff, surrounding layout/printer code, test harness contract, neighboring tests, all three commit messages, and upstream evidence above. No test suite or local build was run in this review. gh pr checks reports no checks; that is absence, not passing CI. The disclosed lack of compiled C execution is appropriately explicit and should remain so. No em dash or other listed lexical tell was found in the title or commit messages; the committed-comment tells are enumerated above.
SECOND READ: NOT READY — committed comments narrate patch history and justify the fix instead of stating test behavior; upstream has also already repaired bendlang#948.
Dropped — fixed upstream before this branch existedClosing this candidate. The bug is real and the fix was correct, but The upstream fix
It touches
Issue #948 was closed as completed at 2026-09-21T17:55:14Z. Settled by execution, not by readingCut a worktree on ### proto_name_datatype @ /agent-workspace/oss/bend-wt-1790082804
[interp PASS]
[build rc=0]
[js rc=0]
[js PASS]
### proto_name_type_param @ ...
[interp PASS]
[build rc=0]
[js rc=0]
[js PASS]
### proto_name_array_cell @ ...
[interp PASS]
[build rc=0]
[js rc=0]
[js PASS]
### proto_name_value_of @ ...
[interp PASS]
[build rc=0]
[js rc=0]
[js PASS]
### proto_name_ctor_field @ ...
[interp PASS]
[build rc=0]
[js rc=0]
[js PASS]Five of five pass, zero failures. The four discriminators fail on our base Why the prior-art gate missed itThe hunt searched upstream PRs and issues by number and by term, and was clean. Upstream fixed this as a direct commit to the default branch — no PR to find — and the issue stayed open for a further 2h45m after the code landed, so it still read as huntable from outside. The verification's own findings stand on their merits (the The Second Read's other finding — fixture comments narrating patch history rather than test behaviour — is correct and is recorded in the rule book, but is moot here: nothing goes upstream. |
Summary
bend2/comp.tsindexes two tables by a datatype's name. Both were plain object literals, so a datatype named__proto__,constructor,toString,valueOforhasOwnPropertyread an inheritedObject.prototypemember instead ofundefined, and the??fallback never fired.lay_of(comp.ts:994) returned that inherited value as aLay; both emitters then died inlay.ks.length/lay.ks.some. The checker and the interpreter were unaffected — only-obuilds.WORDSalone (the one-line change the issue proposes) is not sufficient: the build then succeeds and the emitted JS crashes at run time, becauseshow_main(comp.ts:1313) has the identical pattern and hands a function to the printed-kind slot. Both sites are on one code path and are fixed together.Object.setPrototypeOf({...}, null), already used forOPERATIONS(:191) andOPTIMIZED(:349), the compiler's other user-indexed tables. +11/-3 inbend2/comp.ts, no new dependency, no behaviour change for any other name.tests/compile/: four discriminators covering the three distinct crash sites and the unreported prototype members, plus one declared control pinning the fix's scope.Upstream
bendlang/bend, default branchmain.e52cda47a58967aa65d1eb26efe8f42a0b0407df("Add coauthors to BendTT and BendRT papers").bend2/comp.ts—WORDS(:166base /:169head) andshow_main's printed-kind lookup (:1304base /:1313head, now the namedSHOWNtable).Bug
Trigger. Any Bend program declaring a datatype whose name is an inherited member of
Object.prototype—__proto__,constructor,toString,valueOf,hasOwnProperty,propertyIsEnumerable— and building it with-o(JS or C lane).Wrong outcome.
const WORDS: Record<string, Lay> = { U32: W32, F32: W32, Nat: W64 }is a plain object literal, soWORDS["__proto__"]evaluates toObject.prototypeandWORDS["toString"]to a function, neverundefined.lay_ofdoesWORDS[t.k] ?? memo(LAYS, ...): the coalesce is dead for these names, solay_ofreturns a non-Lay. The first consumer to read.kscrashes the compiler withTypeError: undefined is not an object (evaluating 'lay.ks.length'). The checker (--check-only) and the interpreter accept and run the same file correctly, so the failure is confined to the build lanes.A second, independent occurrence of the same defect sits on the same path:
show_mainbuilds the printed-value descriptor with{ U32: 0, F32: 1, Nat: 2, Char: 3, String: 4, Array: 6 }[adt.k] ?? 7. FortoStringthat yields a function and for__proto__an object, so the descriptor is emitted with a garbage cell kind. This is invisible untilWORDSis fixed, at which point the build succeeds and the program crashes at run time instead. In the C lane the same defect splices the function's source text into astatic const u32initialiser (measured, see Test evidence).Blast radius. Every user who names a datatype after a JS prototype member. Bend's surface language has no reserved-word list that excludes these names — the checker accepts them and the interpreter runs them, so the program is legal Bend and only the compiler disagrees. The failure is a raw host
TypeErrorwith no source location, not a Bend error page. It is not a 2.0.24 regression: the reporter confirms 2.0.23, andWORDShas carried a plain literal since the file's introduction.Repro
proto_type.bend(the reporter's, verbatim):On base (
bend2/comp.tsunchanged):The same
TypeErroron base forconstructor,toString,valueOfandhasOwnProperty; a datatype namedQbuilds and runs normally.Fix
Why this is the minimal correct change: a null-prototype table makes every lookup answer
undefinedfor a name the table does not own, which is exactly what the two??fallbacks already assume. It changes nothing for any other name — a datatype namedQorU32reads identically. The second table is lifted to a module-levelconstso it is allocated once and sits besideWORDS, the other datatype-name-indexed table, rather than being rebuilt per call.Alternatives rejected, each one built as a real mutant and killed by a named test (see Test evidence):
WORDSonly, as the issue proposes. Mutant M1 — build succeeds, emitted program crashesv.map is not a function. Killed byproto_name_datatype,proto_name_type_param,proto_name_array_cell,proto_name_value_of.show_main's table only. Mutant M2 — the originallay.ks.length/lay.ks.somebuild failure. Killed by the same four.||instead of??at the newSHOWNlookup. Mutant M3 —SHOWN["U32"]is0, a falsy valid kind, so||reclassifies it as kind 7. Killed by all five branch tests and by pre-existingfold_fuel_loop.bend/f32_table_nan_bits.bend.Object.hasOwn(WORDS, t.k) ? ... : ...at each site. Nine call sites readWORDS; guarding each is more code and each new site can forget. The prototype belongs to the table, not to its readers.Map. Correct, but it changes the type of aRecord<string, Lay>read in nine places and reads nothing like the file's two sibling tables.Test evidence
Five files, all in the existing
tests/compile/namespace, each in the repo's format (a.bendfile ending in the#|lines its run must print). Every row below was measured at headc5ce75cand on a base arm ate52cda4whosebend2/comp.tsis byte-identical to base (git diff --quiet e52cda4 -- bend2/comp.tsreturns clean).proto_name_datatype.bend__proto__,constructor,toString; the flatlay_ofpath and theshow_maindescriptorlay.ks.lengthproto_name_type_param.bend__proto__<A>; the name reaches the tables via the type argumentlay.ks.lengthproto_name_array_cell.bendArray<toString>; the cell layout vialay_el— a different crash sitelay.ks.someproto_name_value_of.bendvalueOf/hasOwnProperty/propertyIsEnumerable— the inherited members the issue does not name, one nesting per namelay.ks.lengthproto_name_ctor_field.bend(control)__proto__/toStringThe control is declared as such in its own header comment: only a datatype's name indexes these tables, and a constructor's emitted JS key is already a computed property. It passes on both arms by design and exists to pin the fix's scope — the fix must neither need nor break the constructor/field paths. It is not a green no-op: it is the only one of the five that mutants M1 (
v.map) does not kill, which is exactly the scope claim it makes.Fails-before (verbatim,
/agent-output/oss/bend/verify-base-arm.txt), base arm ate52cda4with the five test files applied andbend2/comp.tsuntouched:Passes-after (verbatim,
/agent-output/oss/bend/verify-head-arm.txt), at headc5ce75c— every test is interpreted, built, and its artefact run:Mutants — every rejected alternative is killed by a named test. Built as real mutations of
bend2/comp.tsin a scratch tree, each run against all five tests:WORDSnull-prototyped,show_mainleft alone — the exact one-line fix the issue proposesTypeError: v.map is not a function. (In 'v.map((x) => show_val(D, N, D[d + 1], x, 0))', 'v.map' is undefined). Killed by the four discriminators; control survivesshow_main's table null-prototyped,WORDSleft alonelay.ks.length(andlay.ks.somefor the Array test). Killed by the four discriminators; control survivesSHOWN[adt.k] ?? 7→ `So neither half of the fix alone passes, and the
??is load-bearing against its falsy-valid owned value.The emitted artefact is not merely non-crashing, it is byte-identical to a rename. For each proto-named program a twin was built with the prototype names mechanically renamed to ordinary ones (
__proto__→Aaa,toString→Ccc,valueOf→Vvv, …), both lanes emitted, the names normalised back, and the files diffed:C lane, emission measured.
clangis absent so nothing links, but-o out.cemits here. The same defect reaches the C lane and the fix repairs it:Neighbouring tests, regression check. Interpreted every file in
tests/compile/on both arms — 121 files, 111 pass / 10 differ at head and 111 pass / 10 differ at base, the same 10 files on both arms (array_oob_access,array_padding_slots,array_unboxed_default,axiom_runtime,ctor_tag_dispatch_000/001,erasure_dead_param,slab_drop_recycle,slab_lazy_alloc,slab_sparse_default). Those 10 are multi-line error-page tests carrying a trailingexit 1line that this line-wise comparator does not reconcile, not failures:axiom_runtimeandctor_tag_dispatch_000were spot-checked on both arms and want/got are identical apart from that line. The arms tie at 111 because the sweep interprets only, and interpretation is exactly the lane the bug spares — the build-lane discrimination is the per-test table above. Nothing in the existing suite changed behaviour.Formatter / linter / gate.
gates/repo.ts(the allow-list and ttok-cap gate) cannot run in this container: it shells out tottok, which is not installed, and dies withTypeError: null is not an object (evaluating 'got.stdout.toString')— identically on clean base, so it is the missing binary, not this change. Checked by hand instead: all five paths match the gate's own rule^tests/[a-z]+/([a-z0-9-]+/)?[a-z0-9_]+\.bend$(gates/repo.ts:72) and the largest new file is 914 bytes against a 16000-ttok cap. The repo ships no formatter, linter or type-check config of its own.Verification method
executed— in the task container:bun1.4.2 (installed vianpm install bun; the repo requires Bun, andmain.ts:671refuses to run under bare node), Linux x64. Every transcript above is copy-pasted from a real run; the arms are separate git worktrees, not an edit-and-revert. The per-file runner reproducesgates/test.ts's JS-lane probes by hand (check,interp, build, then run the artefact).This branch was adversarially re-verified by a second, independent run at head
c5ce75c: the boundary ledger below was rebuilt from the diff rather than from this body,proto_name_value_of.bendwas added to close row B6, mutant M3 was added to pin row B8, rows B7/B17 were converted from argument to measurement, and the C-lane and artefact-equivalence evidence above is that run's.What was NOT executed here, for the operator:
clangis absent, so-o <binary>never linked. The C source is emitted and inspected above on all three arms, which pins the defect and the fix in that lane; the compile-and-run step is unmeasured.gates/test.ts, which shards across a mini cluster and needsclang, Metal and the hub.gates/repo.ts, blocked on the missingttokbinary on base as well as head.Fork CI:
gh pr checks 1 --repo askalf/bendreports no checks at this sha. Actions were never enabled on the fork (it was created during the hunt run; operator card00MUBEJ5F8E56D6B1C313451BD). That is an absence of CI, not a failure — no job is red.Prior art
gh search prs --repo bendlang/bend "__proto__" --state openfix(js): keep foreign effects and scheduling helpers together— fixes bendlang#946, a different bug (the foreign-effect table injs_lib). Same class, different table and different issue; it touches neitherWORDSnorshow_main.gh search prs --repo bendlang/bend "prototype" --state open/closedOPERATIONS/OPTIMIZED, already null-prototyped), bendlang#811 (closed, Vulkan backend — unrelated)gh search prs --repo bendlang/bend "lay_of" --state open[]gh search prs --repo bendlang/bend "948 in:body" --state open/closedgh search prs --repo bendlang/bend "comp.ts" --state openWORDS/show_main/setPrototypeOf/ the inline kind literal — no hits on either tablegh pr list --repo bendlang/bend --state open --limit 20Initialize compiler caches before building printer layoutsis the nearest miss — it moves theshow_maincall aftercarb_bookfor a cache-ordering crash, confirmed to touch only the call sites. No conflict beyond a possible trivial context rebase.gh issue view 948Re-run at the verification gate (2026-09-21T16:55Z), after the hunt's own 15:42Z check: unchanged on every row above.
Policy
bendlang/bendships noCONTRIBUTING.md,.github/CONTRIBUTING.md,CLAUDE.md, PR template,CODE_OF_CONDUCT.md,AI_POLICY.md,.github/AI_POLICY.md,AI.mdorAGENT_POLICY.md— every one returns 404 from the contents API. There is no CLA and no DCO. The only governance file isAGENTS.md, which is silent on AI/LLM/agent contributions — no ban, no disclosure requirement, no mandated commit trailer.Binding lines from
AGENTS.md, quoted, and how this change complies:bend2/bend.tsis not touched. The diff isbend2/comp.ts(explicitly "the one compiler") plus five test files.All five tests are
.bendfiles ending in their#|expected output, placed in the existingtests/compile/namespace beside the other compiler tests (ctor_name_collision.bend,dollar_name_sanitize.bend).Checked by hand (see Test evidence); the gate itself cannot run here for a reason that reproduces on clean base.
WONTFIX.txt("Read this file before you open an issue") was read in full: this bug appears in none of its DESIGN, CAPACITY, OPEN, RUNTIME or SOON entries, so it is not a declined-by-design behaviour.Commit style follows the log: a declarative sentence naming the behaviour, with the issue number in parentheses.
Disclosure facts for the operator
Plain facts, for you to write your own disclosure:
bend-lang.com, whichAGENTS.mdplaces in the sibling repobendlang/bend-lang.com, and its body is a UX wishlist with no repro in this codebase. The agent re-scoped to issue A datatype named __proto__, constructor, or toString crashes both emitters through the inherited WORDS lookup bendlang/bend#948 within this repo.bend2/comp.tsand all five test files.tests/compile/sweep. No transcript here is reconstructed or paraphrased.show_main) by running the emitted program after fixing the first, not by reading — the issue reports only theWORDSsite.proto_name_value_of.bendplus the M3 mutant after finding two ledger rows that were argued rather than tested.clangin the container), the repo's cluster test runner, andgates/repo.ts(nottok).bendlang/bend.Boundaries
One row per predicate, comparison, lookup and fallback the diff adds or changes. Rebuilt from the diff at head
c5ce75c.WORDS["U32"]— an owned key, the primary hitW32, unchanged by the prototype changeproto_name_*test carriesU32fieldsWORDS["F32"],WORDS["Nat"]— the other owned keysW32/W64, unchangedf32_table_nan_bits.bendand the Nat tests), green on both armsWORDS["Q"]— an ordinary absent keyundefined,??fires, memoized layout computed — unchanged from baseproto_name_ctor_field.bendcontrol (datatypeBox); the twin-artefact diffs emit byte-identical JS and C for a renamed programWORDS["__proto__"]— the bug, absent but inherited (an object)undefined,??firesproto_name_datatype.bend(base:lay.ks.length)WORDS["constructor"],WORDS["toString"]— inherited, non-object valuesundefined,??firesproto_name_datatype.benddeclares all three typesWORDS["valueOf"],WORDS["hasOwnProperty"],WORDS["propertyIsEnumerable"]— inherited members the issue does not nameundefined,??firesproto_name_value_of.bend— base FAILSlay.ks.length, head PASSES, M1 fails at run time, M2/M3 fail at build. One nesting per name, so a table answering only the three reported names still dies hereWORDS[""]— the empty nameundefined,??fires""is not a producible datatype name; the parser requires an identifier, so no source reaches this key on either armSHOWN["U32"]→0, the falsy owned value0 ?? 7is0; a||here would silently reclassify everyU32as kind 7?? 7→|| 7): killed by all five branch tests and by pre-existingfold_fuel_loop.bend/f32_table_nan_bits.bend, withlay.arms[j]SHOWN["F32"]=1,Nat=2,Char=3,String=4,Array=6 — the other owned kindsproto_name_array_cell.benddrives theArraykind (6) at head5and7— values not in the table (Eqlis pushed as 5 directly; 7 is the??default)7is still the fallback for any unowned nameproto_name_datatype.bendandproto_name_value_of.bend(all six of their types take kind 7)SHOWN["__proto__"]— the second bug, returns an object on baseundefined,?? 7fires, descriptor gets kind 7v.map is not a function; C lane shows the raw defect asfunction toString() { [native code] }insidestatic const u32 SHOW_DESC[]SHOWN["toString"],SHOWN["valueOf"]— return a function on baseundefined,?? 7firesproto_name_datatype.bendandproto_name_value_of.bend__proto__<A>)lay_ofthroughty_adtexactly as the flat case; kind 7proto_name_type_param.bend(base:lay.ks.length)Array<toString>)lay_elreads the cell layout through the same table; a distinct crash siteproto_name_array_cell.bend(base:lay.ks.some)__proto__OPTIMIZED(already null-prototyped) and are emitted as computed keysproto_name_ctor_field.bend(control) — passes on base and head, and is the only test M1 does not killtoStringproto_name_ctor_field.bend(control)ArrayorIO/IO.OP— nameslay_ofspecial-cases before the memotype Array is Data:andtype IO is Data:are both refused by the parser on base and head —Error: expected a fresh name (duplicate declaration: Array). No source can occupy those keysWORDSread sites (:973,:1052,:1099,:1531,:2322,:2324,:2684,:2792,:3235), which compare=== undefined/=== W32rather than using??WORDS["__proto__"] === undefinedwasfalse, mis-classifying the type as a word type; at head it istrue. No site changes for an owned or ordinary nameproto_name_datatype.bendreachesty_clo/type_adts/emit_ctrthrough its nested record fields; the 121-file sweep pins the no-change-for-ordinary-names half; the twin diffs pin it byte-for-byte in both lanesSHOWNallocated once at module level instead of rebuilt per callconsts with no per-book stateSHOW_DESC; base emits no.cat all, M1 emits a function's source into au32array, head emits a well-formed descriptorclanghere) — stated in Verification methodSuggested upstream PR title
A datatype's name indexes a null-prototype table, not Object.prototype (bendlang#948)