Files
scriptc/tests/corpus/record-layout-views.ts
T
Malte UblandClaude Opus 5.5 6a30f02a69 Answer cross-layout record casts with views of the original record
A checked conversion of a capsule of record A into record type B, when A
has all of B's fields with the same types in any order, now answers a view:
a B object whose two trailing words hold A and A's offsets for B's fields.
Every field address of a B value tests the first word (recordViewFieldPtr,
the record clone and the JSON walker), so reads and writes through either
name reach the same storage. The view's record-source entry owns A's
capsule: boxing the view answers that capsule, so identity holds, B's
reflective surfaces and spreads see the whole object, and the entry dies
with the view, which releases A's capsule. The capsule finds its views
again through borrowed cast-list entries.

Only the target types of such conversions carry the words and the test.
They are planned from the IR before emission (record-views.ts): record
types a checked conversion can produce for which another record type in
the module has all their fields. Programs without checked conversions are
unchanged. This replaces the prefix pointer pass, whose narrower release
could not free the source's extra fields.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-27 06:35:26 -07:00

27 lines
1.0 KiB
TypeScript

// A native record converted from an untyped value into another record type
// that names some of its fields, in any order, is the same object: writes
// through either name show through the other, identity holds, and the
// untyped views, JSON and spreads of the narrower name see every field.
type Wide = { a: number; b: string; c: boolean; d: number[] };
type AC = { a: number; c: boolean };
type DB = { d: number[]; b: string };
const wide: Wide = { a: 1, b: "x", c: true, d: [1] };
const o: unknown = wide;
const v = o as AC;
v.c = false;
console.log((o as Wide).c, wide.c, o === v, (v as unknown) === o);
wide.a = 5;
console.log(v.a, JSON.stringify(v), Object.keys(v).join(","));
const w = o as DB;
w.d.push(2);
w.b = "y";
w.d = [7, 8];
console.log(wide.b, wide.d.length, JSON.stringify(o), w === (o as DB), v === (o as AC));
const v2 = { ...v };
console.log(JSON.stringify(v2));
function bump(x: AC): void { x.a += 1; }
bump(v);
console.log(wide.a, v.a);
const list: AC[] = [v, { a: 9, c: true }];
console.log(list.map((x) => x.a).join(","), JSON.stringify(list));