Skip to content

Call resolver: an untyped receiver's built-in method call (str.trim(), map.get()) links confidently to a same-named repo method via file/import #3756

Description

@squid-protocol

What

In TypeScript, a method call on a receiver the engine has no type for (x.m()) resolves through the file or import step to any repo function named m, whether that's a class method, an object-literal property, or an imported module's member. This happens even when the call is a built-in: String.prototype.trim, Map.prototype.get, Set.prototype.has/add. These links are confident, so they feed function PageRank and fan-in, and cross-file ones become fcall edges in the file graph (#3333).

Evidence

This comes from the new TypeScript Level 2 check (tests/tools/call_graph_resolution.py typescript, branch claude/optimistic-heisenberg-bta91d). The TypeScript compiler's type checker resolves 52 of the engine's confident links on zod (colinhacks/zod@2bf7b0630d53) to declarations that exist only outside the repo, in lib.d.ts. On that check this takes confident precision from 99.6% to a strict 96.3%.

step callee name count
import get 17
import has 16
import add 9
file includes, startsWith, endsWith, isFinite, parse, get 8

Examples:

  • packages/zod/src/v3/types.ts:903: input.data = input.data.trim();. The value is a string, but the engine links it to ZodString.trim() at types.ts:1231 (step file).
  • packages/zod/src/v3/types.ts _parse: ctx.addIssue(...) is linked (file) to the addIssue: arrow inside a checkCtx object literal at types.ts:4328. The checker resolves it to ZodError.addIssue (ZodError.ts:298).
  • packages/zod/src/v4/classic/from-json-schema.ts convertBaseSchema: seen.has(...) on a Set is linked (import) to $ZodRegistry.has at v4/core/registries.ts:74, because the file imports registries.ts.

Likely direction

For an untyped, non-this receiver, a name that is only a method (a class member or object-literal property) in the candidate file is weak evidence. It probably belongs in receiver, which is ambiguous and so never an edge, rather than file/import. That matters most for names that shadow built-in methods of String/Array/Map/Set/Promise. The Python side already solved the same shape with calls_out_qualifiers (d.get() on a dict). The TypeScript check's confident_external count is the metric to move to 0. confident_strict_precision_pct is baselined but not gated yet.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugUnintended behavior or logic failure in the enginecore-engineModifications to the central physics and parsing engine

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions