Skip to content

perf: extend the walker-rule prefilter to call expressions - #584

Merged
mattiamanzati merged 1 commit into
mainfrom
feat/call-signature-effect-prefilter
Aug 9, 2026
Merged

perf: extend the walker-rule prefilter to call expressions#584
mattiamanzati merged 1 commit into
mainfrom
feat/call-signature-effect-prefilter

Conversation

@mattiamanzati

Copy link
Copy Markdown
Contributor

What changed

Follow-up to #583. The reference-node prefilter left call expressions ungated — and calls were the largest remaining source of rule-phase GetTypeAtLocation cost, because querying a call's type re-runs expensive call-checking machinery.

  • NodeCouldBeStrictEffect now handles KindCallExpression via a new callCouldReturnStrictEffect: it consults the cached resolved signature and its cached return type (both computed during the main check phase, so the lookup is nearly free) and rules the call out when the declared return type conclusively cannot be a strict Effect, using the same conservative couldBeNamed walk as perf: prefilter walker-rule type queries by declared type #583. Both walker rules pick this up through their existing gates with no rule changes.
  • Resolved signatures are instantiated, so generic calls are handled precisely: generic("x") conclusively returns the literal "x" and is ruled out, while signature-less calls, any, Effect-containing unions, and optional chains (return type union-widened with undefined) all stay conservative.
  • promiseInEffectSuccess also stops computing GetTypeAtLocation for call nodes only to discard it — it goes straight to the resolved signature's return type, falling back to the location query only when no signature resolves.

Soundness

A call expression's type is its resolved signature's return type (promiseInEffectSuccess already relied on this equivalence), calls are not flow-narrowed references, and StrictEffectType requires the type's symbol to be named Effect. The gate answers a conclusive no only when the declared return type provably contains no possibly-Effect constituent; every shaky case falls through to the full query, and the whole path is panic-guarded like the rest of the predicate.

Verification

🤖 Generated with Claude Code

A call expression's type is its resolved signature's return type, and
both the signature and that return type are cached from the main check
phase. NodeCouldBeStrictEffect now consults them for KindCallExpression
nodes and rules the call out when the declared return type conclusively
cannot be a strict Effect, sparing the expensive re-check that
GetTypeAtLocation performs on calls. Resolved signatures are
instantiated, so generic calls whose instantiation is conclusively
non-Effect are ruled out precisely; signature-less calls, optional
chains and every inconclusive return type stay conservative.

promiseInEffectSuccess also stops computing GetTypeAtLocation for call
nodes only to discard it: it now goes straight to the resolved
signature's return type and falls back to the location query only when
no signature resolves.

Diagnostics are unchanged (verified byte-identical on a full Effect
monorepo build); wall time for that build drops a further ~4.6% on top
of the reference prefilter.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@mattiamanzati
mattiamanzati merged commit 8362acc into main Aug 9, 2026
6 checks passed
@mattiamanzati
mattiamanzati deleted the feat/call-signature-effect-prefilter branch August 9, 2026 18:39
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.

1 participant