Skip to content

fix(go): resolve calls through typed function and method parameters - #808

Open
kunalgoesbyken wants to merge 1 commit into
trailhq:mainfrom
kunalgoesbyken:fix/go-parameter-typed-receivers
Open

kunalgoesbyken wants to merge 1 commit into
trailhq:mainfrom
kunalgoesbyken:fix/go-parameter-typed-receivers

Conversation

@kunalgoesbyken

Copy link
Copy Markdown
Contributor

Summary

In Go a parameter is the usual way a function gets hold of another type, but func handle(s *Server) { s.Start() } produced no call edge: handleGo never bound parameters, so resolveRecvType returned nothing and the member call was dropped. callers Server.Start missed every caller that is handed the server instead of building it.

Changes

  • bindings.ts: in handleGo, bind each parameter_declaration of a function_declaration or method_declaration to its type. Grouped names (a, b *T) and named results are included. Qualified (http.Request), slice, map and variadic types bind nothing.
  • A name declared again with a type we cannot read now hides the outer binding instead of inheriting it: a func literal parameter, a := from an untyped call, a var x = f(), a range variable, a receive or type-switch variable. Without this, s := other(); s.Start() inside func f(s *Server) resolved to Server.Start. FileBindings.shadow stores a blank type, lookup stops at it and set never overwrites it. Only the Go handler writes it.
$ graft callers Server.Start      # before
Start · method · server.go:L5-L5
  no indexed callers

$ graft callers Server.Start      # after
Start · method · server.go:L5-L5
  calls ← handle (handler.go:L3-L5)
      4: s.Start()

Testing

On Windows 11 with Node 26:

  • test/graph-go-params.test.ts (new). The first test covers pointer, value, grouped and named-result parameters, a method's own parameter, and a slice parameter that must not bind. The second covers a func literal parameter, an untyped :=, a range variable and a multi-value := hiding the typed parameter, with an unshadowed call still resolving. Both fail on main.
  • test/graph*, blast*, ask*, generic*, depth*, resolve* and covers* suites: 674 tests, 1 fail. The one failure is discoverWorkspaceChildren follows a symlinked child repo, a symlink permission error on Windows that fails the same way on main.
  • tsc --noEmit passes.

On seedfall (84 Go files plus examples), calls edges go from 3318 to 3408: 92 added, 2 removed. Added edges are calls on parameters, such as engine/build.go#Build -> engine/config.go#Config.specs. The two removed are real calls (memFS.OpenFile -> memFile.Truncate and mainPackages -> mainPackage.matches). Bindings are one map per function, so a name that is also declared untyped, or as a func literal parameter, elsewhere in the same function is left unresolved instead of guessed.

Fixes #807

A Go function gets its collaborators as parameters, but only `:=`, `var`
and struct fields were bound to a type. `func handle(s *Server) { s.Start() }`
had no receiver type, so the call was dropped and `callers Server.Start`
missed every caller that is handed the server instead of building it.

Bind each parameter of a declared function or method (grouped names and
named results included) to its type.

A name declared again with a type we cannot read (a func literal
parameter, a `:=` from an untyped call, a range or type-switch variable)
now hides the outer binding instead of inheriting it, so `s.Start()` under
`s := other()` no longer resolves to the parameter's type.
@trailhq-graft

trailhq-graft Bot commented Nov 10, 2026 •

Copy link
Copy Markdown

🌱 graft blast radius

Nothing outside this diff depends on it. 1 area changed; no indexed dependents at depth 2.
Tests: no test reaches Graph Bindings.
Tag: @shhdwi — Graph Bindings

Who knows this code — 1 person across 1 area
Area Who knows it
Graph Bindings · changed @shhdwi — 4 commits, last 13d ago

Ownership is git history over each area's own files, weighted towards recent work (120-day half-life). Merge commits and bots are dropped, and you are dropped from your own PR. A name with no @ has no GitHub handle in its commit email — tag them by hand, or add a .mailmap entry. A suggestion from history, not a CODEOWNERS rule.

Test signal per changed area — 1 ✗

Reached = a node under a test path has a resolved edge into the changed symbol. It undercounts anything called indirectly — through a CLI, a spawned process or a dynamic import — so read a low ratio as “look here”, never as a coverage gate.

  • ✗ Graph Bindings — 0 of 4 reached · no test file reaches it
    • not reached: set, shadow, lookup, handleGo

graft blast · origin/main...HEAD · depth 2 · 2 changed files

Open the interactive graph → — click an area to see its dependent symbols at file:line.

github-actions Bot added a commit that referenced this pull request Nov 10, 2026

This branch has not been deployed

No deployments
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.

Go: calls through a typed function parameter (s.Start() in func handle(s *Server)) produce no call edge

1 participant