Skip to content

Monomorphize generic overload calls and call generic methods through Pick views - #1511

Merged
ctate merged 2 commits into
opt/bc-sdk-typesfrom
opt/bc-pick-overloads
Oct 20, 2026
Merged

ctate merged 2 commits into
opt/bc-sdk-typesfrom
opt/bc-pick-overloads

Conversation

@cramforce

Copy link
Copy Markdown
Contributor

Stacked on #1466 (its Pick/Omit class views).

Calls that select an overload of a generic function or method

class Store {
  async load<T>(key: string, map: Mapper<T>): Promise<T>;
  async load(key: string): Promise<Reply>;
  async load<T>(key: string, map?: Mapper<T>): Promise<T | Reply> { /* ... */ }
}

Calls that resolved to an overload signature were refused ("calls selecting an overload signature of a generic method"). The implementation now monomorphizes under the bindings that the overload's resolved signature proves for the implementation's type parameters. This is the same structural unification every generic call uses, run against the overload. A type parameter the overload never mentions is unknown, the checker's answer for an uninferred parameter. The instance's parameters and result are the implementation's under those bindings, because the body was checked against them. The call's arguments and result coerce across, as a non-generic overload call already reconciles with its implementation. Parameters that the overload omits must be optional in the implementation; otherwise the refusal stays.

Generic methods through a Pick view

services.store.load(...), where store: Pick<Store, "load"> and load is generic or generically overloaded, compiled before but failed at run time ("reading 'load' on this native class through an untyped value"), because a generic method has no dispatchable method value. The call now extracts the Store instance from the view's live receiver and calls the method statically, as a Store-typed receiver does. A view holding a value of another class throws on the checked extraction.

Binding inference for T | Promise<T>

Callback slots shaped (r) => T | Promise<T> left T unbound, because the unifier skipped multi-part unions. Each declared part that names a generic target (Promise, an interface, an alias) now pairs with the one instantiated part of the same target, and a single remaining bare type parameter takes the single remaining part. Under an unknown binding, unknown | Promise<unknown> maps to the checked-dynamic value that the checker's own reduction gives.

Evidence

  • New corpus program 6495 generic-method-overloads.
  • overload-fences.ts now compiles completely and moves from the diagnostics fixtures to corpus 6496 overload-signatures.
  • Both match Node byte for byte in the plain and sanitized lanes. The 64 corpus programs whose names mention generic, overload or pick pass.
  • Zero-cost gate against Compile SDK-declared data types, any-valued members and Pick views of classes #1466 (f4a7c46): PASS. All 2504 programs are identical. Self-hosted compile time +0.70%. The bench timing interval came out inconclusive, but every program is byte-identical, so the difference is noise.
  • pnpm lint and pnpm format:check are clean. pnpm test:ts7 --baselines-only passes; the 6495 baseline is recorded and the moved fixture's baseline moves with it. diagnostics.test.ts: 199/199.
  • The self-hosted compiler's IR build reports no diagnostics.

Not included

Calling an optional function field after a truthiness check (p.cb ? p.cb(x) : d) inside such generic bodies needs #1413's narrowed-callback read.

🤖 Generated with Claude Code

…Pick views

- A call that resolves to an overload signature of a generic function or
  method with an implementation (`load<T>(k, map: Mapper<T>): Promise<T>;
  load(k): Promise<Reply>; load<T>(k, map?) {...}`) monomorphizes the
  implementation under the bindings the overload's resolved signature
  proves; a type parameter the overload never mentions is unknown, and
  parameters the overload omits must be optional in the implementation.
  It was refused.
- `view.m(...)` where `view` is a `Pick`/`Omit` view of a program class
  and `m` is a generic (or generically overloaded) method extracts the
  instance from the view's live receiver and calls the method statically,
  instead of a runtime refusal reading the method through the untyped
  view.
- Binding inference pairs the arms of `T | Promise<T>` with an
  instantiated `R | Promise<R>`, and `unknown | Promise<unknown>` maps to
  the checked-dynamic value the checker reduces it to.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
scriptc Ready Ready Preview, v0 Oct 20, 2026 5:26pm UTC

Comment thread packages/compiler/src/frontend/lowering/generic-functions.ts Outdated
Comment thread packages/compiler/src/frontend/lowering/generic-functions.ts
Comment thread packages/compiler/src/frontend/lowering/lower-calls.ts
@cramforce
cramforce requested a review from ctate October 20, 2026 12:09
@ctate
ctate merged commit 2fc57e8 into opt/bc-sdk-types Oct 20, 2026
63 of 65 checks passed
@ctate
ctate deleted the opt/bc-pick-overloads branch October 20, 2026 17:33

This branch was successfully deployed

1 active deployment
Preview — 19835975 Deployed Oct 20, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants