ReviewOS

home-lang/home

fix(ts): preserve map entry tuples through array callbacks

#660
Closed chris opened this 8 days ago ·
8 days ago

Problem

Home loses tuple element positions when a Map<K, V> is spread into an array and consumed by chained filter / map callbacks with destructured parameters. For [string, Flags], both callback bindings become string | Flags; TypeScript preserves the tuple and infers the final key array as string[].

This accounts for the three remaining TS2345 diagnostics at src/v4/core/schemas.ts:2827:100, :2830:52, and :2830:89 in the pinned Zod 4.5.2 graph.

Fair oracle

Strict same-file reduction in /tmp/home-ts-map-callback-tuples:

type Flags = { l?: true; r?: true };
const entries = new Map<string, Flags>();
const bothKeys = [...entries]
  .filter(([, flags]) => flags.l && flags.r)
  .map(([key]) => key);
const valid: string[] = bothKeys;
  • TypeScript 6.0.3: clean.
  • Native TypeScript 7.0.2: clean.
  • Current Home ReleaseFast: two false TS2339 diagnostics on flags.l / flags.r, then TS2322 because bothKeys is (string | Flags)[].

The appended negative changes only the final annotation to number[]:

  • TS 6 and TS 7: exactly one TS2322, string[] not assignable to number[].
  • Home must retain exactly that negative after the fix.

Acceptance

  • Preserve positional [K, V] tuple information through Map iteration, array spread, contextual callback destructuring, and chained array methods.
  • No special cases for Zod, bothKeys, property names, or source locations.
  • Add a permanent positive/negative checker regression.
  • Run focused and full checker suites plus Program.
  • Compare the complete pinned Zod diagnostic-key set against post-#659 main; expected target is removal of the three identified TS2345 keys with zero additions, but the exact measured delta decides admission.
  • Keep Zod untimed until its diagnostic gate reaches zero; document accepted results in the README and TS_PERFORMANCE.md under #416.
8 days ago

Implementation and validation evidence

Root cause

  • The builtin Map<k, v> surface synthesized iterator entries as a generic array-like object whose numeric index was K | V instead of retaining the semantic [K, V] tuple identity.
  • The parser also discarded array-binding elisions, so [, value] reached the checker as a one-slot pattern and value was projected from tuple index 0.

General fix

  • Build Map iterator entries through the existing fixed tuple constructor as mutable [K, V].
  • Preserve array-pattern elisions as empty HIR parameter slots, which the binder and emitter already handle.
  • Teach pattern binding projection to recognize checker-created tuple origins, not only pool-native tuple flags.
  • No Zod symbols, source paths, method chains, or diagnostic locations are special-cased.

Fair standalone oracle: /tmp/home-ts-map-callback-tuples

  • Valid filter/map pipeline: Home ReleaseFast 0 diagnostics; TypeScript 6.0.3 0; TypeScript 7.0.2 0.
  • Negative number[] assignment: all three retain exactly one TS2322 and identify the inferred source as string[].

Pinned Zod 4.5.2 audit

  • Parent #659: 446 diagnostics / 441 unique file:line:column:code keys.
  • Candidate: 440 diagnostics / 435 unique keys.
  • Delta: 6 unique removals, 0 additions.
  • Removed: schemas.ts lines 2827/2830, three TS2345; schemas.ts line 2825, two TS2339; compile.ts line 262, one TS2322.
  • Immutable #548 baseline: 602 diagnostics / 597 unique keys. Candidate is 162 unique removals with 0 additions.
  • Candidate distribution: TS2345 203, TS7006 100, TS2339 59, TS1361 16, TS2304 16, TS2322 12, all remaining codes below five each.

Regression and validation

  • Permanent positive/negative checker regression covers Map spread -> filter destructuring with an elision -> map destructuring -> string[] plus a retained number[] TS2322.
  • Focused regression: pass.
  • Full ts_checker suite: pass (4356/4356).
  • Full ts_parser suite: pass.
  • ts_program suite: pass (189/189).
  • ReleaseFast build: pass; wall time excluded because the shared machine was contended.
  • zig fmt --check, git diff --check, and scoped Pickier: pass.

Evidence files

  • /tmp/home-zod-660-candidate.stderr
  • /tmp/home-zod-660-candidate-keys.sorted
  • /tmp/home-zod-659-candidate-keys.sorted
  • /tmp/home-zod-548-current.stderr
8 days ago

Completed on main.

Acceptance is met: the fair TS6/TS7/Home positive and negative controls agree exactly; the permanent regression and broad suites pass; pinned Zod improves by six unique identities with zero additions; results and exclusions are documented. Closing this scoped issue while #548 and #416 continue.

Sign in to comment on this issue.