ReviewOS

home-lang/home

Type checker: preserve guarded locals across bindings and callbacks

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

Bun parity exposed four related checker flow and scope defects in Zod 4.5.2:

  • an earlier local array could become unresolved when used as a later destructuring initializer during on-demand inference;
  • destructured for...of bindings were lost inside nested callbacks;
  • if (!value) value = ... joined the assignment with the unguarded incoming union, leaving undefined in the fallthrough type;
  • a stable typeof narrow in a conditional-expression branch was not retained by the callback created directly in that branch.

Implemented on main in 2e1a66e:

  • recover prior locals only inside destructuring declaration initializers, typing their initializer on demand without re-entering the full declaration;
  • resolve array/object loop bindings through the loop element type across callback boundaries;
  • seed conditional assignment joins with each branch's truthiness guard;
  • retain direct conditional-branch typeof narrows for unassigned captures, while rejecting mutable captures.

Validation:

  • TypeScript 6.0.2 oracle: zero diagnostics for the accepted cases and the expected TS2339 for a mutable capture;
  • focused checker regressions passed;
  • complete ReleaseFast checker suite: 4,393/4,393 passed;
  • full JSC-enabled ReleaseFast build: 50/50 steps succeeded;
  • pinned Zod 4.5.2 diagnostics: 21 -> 16, with five removals and zero additions.
8 days ago

Completed by 2e1a66e on main.

The checker now preserves prior locals in destructuring initializers, destructured loop bindings in callbacks, guarded initialization joins, and stable direct conditional-branch captures. TypeScript 6.0.2 oracle behavior matches, all 4,393 checker tests pass in ReleaseFast, the full JSC build passes 50/50 steps, and pinned Zod 4.5.2 falls from 21 to 16 diagnostics with no additions.

Sign in to comment on this issue.