perf: prefilter walker-rule type queries by declared type - #583
Merged
Conversation
The effectInFailure and promiseInEffectSuccess rules walk every node of a file and query its flow type via GetTypeAtLocation just to test whether it is a strict Effect type. Flow narrowing can only refine a reference's declared type, so a declared type that conclusively contains no possibly-Effect constituent can never produce a strict-Effect flow type. The new TypeParser.NodeCouldBeStrictEffect predicate exploits this: for identifier and property-access nodes it inspects the referenced symbol's declared type and lets the rules skip the expensive flow-analysis query on a conclusive negative. It stays conservative (any/unknown, instantiables, symbol-less types, deep unions and every other node kind fall through to the full query), and the underlying walk is generalized over a type-name set so future prefilters for other wrapper types can reuse it. Diagnostics are unchanged (verified byte-identical on a full Effect monorepo build); wall time for that build drops ~10%. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
effectInFailureandpromiseInEffectSuccesswalk every node of a source file and callGetTypeAtLocation— a flow-analysis query, the most expensive part of Effect rule execution — just to test whether the node's type is a strict Effect. This PR adds a declared-type prefilter that skips that query for reference nodes which conclusively cannot be an Effect:TypeParser.NodeCouldBeStrictEffect(node)ininternal/typeparser/could_be_strict_effect.go: for identifiers and property accesses it resolves the referenced symbol (via the already-cachedReferenceSymbolAtNode) and inspects its declared type with a conservative walk.falseis returned only on a conclusive negative: primitives/never, plain object types whose symbol has a different name, and unions of those.GetTypeAtLocationcall. Skipped nodes can never match, so the rules'shouldSkip/matchedbookkeeping is unaffected; call expressions are never gated.couldBeNamed), so prefilters for other wrapper types (Stream, Layer, …) are one-line wrappers if ever needed.Why it is sound
StrictEffectTypeonly matches types whose symbol is namedEffect. Flow analysis can only refine a reference's declared type — select union constituents, narrowany/unknown, or intersect it (and intersections are synthetic, with noEffectsymbol). So a declared type conclusively containing no possibly-Effect constituent can never produce a strict-Effect flow type. Every case where this argument gets shaky stays conservative and falls through to the full query:any/unknown, type parameters/conditionals/indexed accesses, symbol-less types (including theobjectkeyword and evolving types), unions nested beyond depth 4, unresolvable symbols, and all other node kinds.Example
Verification
tsc -b --diagnosticsbuild of the Effect monorepo.any/unknown, type parameters,objectkeyword, Effect-containing unions), call expressions never gated, and nil safety.pnpm lint,pnpm check, and the fullpnpm testsuite pass.🤖 Generated with Claude Code