ReviewOS

home-lang/home

fix(ts): instantiate dependent generic defaults in declaration order

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

Parent

  • #548
  • Correctness tracker: #416
  • Symbolic indexed-access defaults: #634
  • Recursive fixed-point follow-up: #639

Problem

When a generic type reference omits a later type argument whose default depends on an earlier parameter, Home records the raw default instead of substituting the earlier effective argument first. For example, Family<T = unknown, U = Box<T>> leaves T free inside U when referenced as Family or partially as Family<number>.

This produces invalid assignability failures on the pinned Zod 4.5.2 graph. The frozen post-#627 baseline contains 710 diagnostics across the unchanged 106-file production graph.

Acceptance criteria

  • Add reduced conformance regressions for bare and partially supplied generic references with dependent trailing defaults.
  • Match current TypeScript on valid defaulted references and invalid unrelated controls.
  • Apply earlier effective arguments to each later already-symbolic default in declaration order at every default-fill site.
  • Preserve generic identity, recursion safeguards, missing-required-argument diagnostics, and invalid constraint controls.
  • Keep symbolic indexed-access preservation in #634 rather than re-lowering arbitrary declaration HIR during use-site substitution.
  • Keep recursive fixed-point closure in #639 rather than globally weakening free-parameter deferral.
  • Re-run the unchanged pinned 106-file Zod 4.5.2 graph and report exact normalized diagnostic removals and additions.
  • Add only fair benchmark/correctness evidence, document the results in docs/docs/TS_PERFORMANCE.md, and update the linked README table.
  • Keep #548 and #416 updated; link this issue from each commit.
8 days ago

Implementation discovery: declaration-order substitution and symbolic indexed-access-default retention are separate mechanisms. #633 remains scoped to defaults whose lowered TypeId preserves earlier parameters (for example U = Box<T>). A default such as D = T["state"]["definition"] is currently reduced to unknown while its declaration is recorded; attempting to recover it by re-entering HIR changed seven unrelated Zod diagnostic locations. That approach was rejected. I am opening a dedicated follow-up for preserving that symbolic default at declaration time.

The accepted #633 candidate must still have zero added Zod diagnostic locations/identities versus the frozen 710-diagnostic post-#627 baseline.

8 days ago

Shipped to main in 4446c586458b884f797cc467f141fad32d0be5ef (checker and regressions) and c5c3fd009e2909f40838a6b4b25a1244953b76cf (benchmark docs and README).

Final evidence:

  • Focused TypeScript 6.0.3 / native TypeScript 7.0.2 oracle: bare and partial dependent defaults plus the valid declaration-backed object-union constraint are accepted; all three invalid controls are rejected.
  • Pinned Zod 4.5.2 graph: 710 → 604 diagnostics, 106 removed (14.9%), 0 added. Removals are 67× TS2430, 21× TS2345, and 18× TS7006.
  • Both candidate runs produced the same complete sorted diagnostic-key SHA-256: b1507875d4327b4df2dce0fed41123d3d409d8f85aca7b05fcaf6d3777c29210.
  • Rebased final tree passed the focused regression, the complete 4,346-test checker suite in Debug / ReleaseSafe / ReleaseFast, the Program suite, zig fmt, scoped pickier, and git diff --check.
  • Full record: https://github.com/home-lang/home/blob/main/docs/docs/TS_PERFORMANCE.md#dependent-generic-defaults
  • README summary: https://github.com/home-lang/home#typescript-frontend-benchmark-snapshot

The result uses declaration-order substitution and declaration-backed structural proofs only; there are no Zod symbol/member special cases. Symbolic indexed-access defaults remain tracked by #634. The recursive constraint fixed-point limitation discovered by the negative controls remains tracked by #639.

Sign in to comment on this issue.