Skip to content

Call resolver: several block-scoped definitions of one name in a file (const Node = … per test) all resolve to one of them, not the enclosing scope's #3759

Closed

Description

@squid-protocol

What

packages/zod/src/v4/classic/tests/cyclic-data.test.ts (colinhacks/zod@2bf7b0630d53) declares const Node = (): any => … separately inside several test(...) callbacks (lines 726, 758, 798, 910). Each one recursively calls its own Node() from a getter:

test("parses a factory-built recursive schema", () => {
  const Node = (): any =>
    z.object({
      id: z.number(),
      get kids() { return z.array(Node()); },   // -> Node@726
    });

The engine links every one of those calls (file step) to Node at line 798. The kids getter at 729 → Node@726, self at 760 → Node@758, and kids at 912 → Node@910 are all wrong. The TypeScript checker flags them as wrong in the new Level 2 TypeScript check (tests/tools/call_graph_resolution.py typescript, branch claude/optimistic-heisenberg-bta91d).

Likely direction

Python already solved this shape for nested definitions (#3712: "a function's own nested wrapper, not the file's first"). The same rule applies here: among same-file candidates, prefer the one whose scope encloses the call. Short of real scopes, a good proxy is the nearest preceding definition whose span contains the call site, or else the nearest preceding one. When line-based evidence can't separate the candidates, the pair should become tie rather than a confident file link.

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