Files
scriptc/tests/corpus/2026-width-spread.ts
Chris Tate 273ceac4a7 Optimize same-shape record spreads (#168)
* Optimize same-shape record spreads

- Lower TypeScript record updates through reusable clone helpers
- Outline large record clones in C and LLVM to reduce generated code
- Add ownership, IR, integer-proof, and differential coverage

* Fix cast record spread clone fallback
2026-08-17 23:37:15 -05:00

41 lines
1.6 KiB
TypeScript

// Width subtyping in SPREAD clothing: `{ ...wider }` building a narrower
// literal drops the extra fields and lifts the rest per field — the same
// copy-reshape rule as slot flows (SEMANTICS.md 36; Node's object would
// keep the extra keys, so reads-after-narrow only).
type A = { a: string; b: string };
const extra1 = { a: "a", b: "b", extra: "extra" };
const a1: A = { ...extra1 };
console.log(a1.a, a1.b);
// A spread field lifting into a union-typed target slot.
type B = { x: number | undefined; y: string };
const src = { x: 3, y: "s" };
const b1: B = { ...src };
const bx = b1.x;
if (bx !== undefined) console.log(bx, b1.y);
// A spread field whose own record narrows (nested width inside spread).
type C = { inner: { keep: string } };
const wide = { inner: { keep: "k", drop: 1 }, junk: true };
const c1: C = { ...wide };
console.log(c1.inner.keep);
// Later explicit properties still override the spread (last-write-wins).
const a2: A = { ...extra1, b: "override" };
console.log(a2.a, a2.b);
// A shape-changing static cast is erased in IR. The same-shape clone
// optimization must inspect that lowered value and decline to this width
// copy instead of cloning it as the asserted narrower shape.
const a3: A = { ...(extra1 as A), b: "cast override" };
console.log(a3.a, a3.b);
// The optional-source merge idiom keeps its present-test semantics next
// to the new lifts.
type Opts = { mode?: string };
const defaults = { mode: "default" };
function build(overrides: Opts | undefined): { mode: string } {
return { ...defaults, ...overrides };
}
console.log(build({ mode: "set" }).mode, build(undefined).mode, build({}).mode);