Skip to content

Code Analysis Go Interface Methods

Tu Shaokun edited this page Nov 8, 2026 · 4 revisions

Go interface method declaration anchors

Validated in Draft, not Labs: #1284, head 59f1a80058c5e5fd8859be960b436a05a799d8e7, starts from candidate #1283 at 0c81af0ea and targets the #1283 source branch, not labs/code-analysis. No approval, formal merge, release or installation. The six-language improvements and Labs remain unchanged.

The next source step

Before, an Echo call such as c.RealIP() through the echo.Context interface stopped at go-method-dispatch even though Context.RealIP is declared at context.go:46:2. After, the call targets that interface method declaration. gopls definition reports the same declaration. The implementation *context.RealIP remains at context.go:298; the runtime implementation is not asserted.

The same change binds nine prometheus.Gatherer.Gather call sites to prometheus/registry.go:173. *Registry.Gather remains at registry.go:455, and other Gatherer implementations are not chosen. This is declaration evidence, not dynamic dispatch resolution.

Fixed samples and results

Neither repository participated in the prior Go method work (Cobra, Chi, gRPC). Source-first expectations were recorded before measurement.

  • Echo fa780cd → ebbb855 (origin/v4): changed concrete *context.RealIP; the Context interface declaration already existed.
  • prometheus/client_golang 7c438e9 → 8f7c887: changed (*Registry).Gather; Gatherer.Gather already existed.

Build scope: root module only, Darwin/arm64, cgo disabled, no custom tags, tests included. Go 1.27.2; gopls v0.24.0 built with the same toolchain. Archify uses incomplete source typing; gopls loads the module graph independently. Position pinning: context.go:46:2 and prometheus/registry.go:455:20.

Question gopls references Before correct / wrong / missed / unknown After correct / wrong / missed / unknown
Echo Context.RealIP 9 3 / 0 / 6 / 0 9 / 0 / 0 / 0
client_golang Gatherer.Gather 56 47 / 0 / 9 / 0 56 / 0 / 0 / 0

Six and nine new correct call-site targets appeared. The 3 and 47 direct targets already resolved to the concrete methods and did not gain extra evidence. No target moved to a different declaration, so the wrong count stays zero. Remaining reasonable unknowns are runtime implementations and calls through uncaptured interfaces.

Repo-wide effect from the same captures:

Project Calls go-interface-method calls Captured InterfaceMethod records Declarations reached Unresolved before → after
Echo head 11,019 734 98 68 7,685 → 6,951
client_golang head 9,435 501 70 46 6,883 → 6,382

Every new target matched a captured InterfaceMethod record. go-direct-function and go-direct-method results are unchanged.

Interface and runtime scope

  • Echo: gopls finds *context.RealIP as an implementation; Archify reaches the same interface declaration for six interface-typed calls and keeps the three direct calls on the concrete method.
  • client_golang: gopls references on Gatherer.Gather return 61 positions across implementations, while references on Registry.Gather return 56. Archify binds the nine interface-mediated sites and the 47 direct sites separately, and does not select among other implementations. TransactionalGatherer.Gather is a separate captured declaration.
  • Calls through uncaptured external interfaces, type-parameter receivers and function variables remain unknown by design.

Remaining miss

A paired change question for a changed concrete implementation still reports only direct callers: Echo *context.RealIP reports 3 instead of 9, and client_golang *Registry.Gather reports 47 instead of 56. The interface callers are visible from the interface declaration but are not attached to the implementation. Closing that gap needs captured interface-to-implementation edges or gopls method-set references; name matching alone would pick the wrong implementation when several exist.

Follow-up: #1285 closes this gap with captured method-set edges and separate interface candidates. See Go interface candidates.

Model and delivery

Adapter revision 4, go-source-direct-v3, adds InterfaceMethod records and the go-interface-method resolution. Schema and semantics require the new resolution to match a captured InterfaceMethod definition start. Change questions include InterfaceMethod in Go definition pairing.

Reproduction: fixed inputs, per-reference tables and gopls commands. run.py takes both CLI entrypoints, both preserved heads and gopls explicitly, matches the innermost containing call range, and writes per-repository JSON plus summary.json. The checked-in summary replaces local paths with commit labels.

gopls trial

Used only as a comparison oracle, not added as a product dependency.

  • Cold first reference load on client_golang: 8.08s; warm runs 0.3–0.5s.
  • Extra dependency: a 41 MiB gopls binary plus a Go toolchain and a resolvable module graph.
  • Broken workspace probe: gopls prints gopls: <file>:<line>:<col>: can't find non-Go definition of Broken and exits 0 with no result. A failed load can look like "no definition" unless stderr is checked.

Validation states

  • Local: npm test --prefix archify/modules/code-analysis passed 417/417 with zero skips at the Draft head; gofmt clean.
  • Package: canonical archify.zip rebuilt with Node 22.23.3; website distribution tests passed 59 with one skip.
  • ZIP: unpacked archives of ebbb855 and 8f7c887 produce identical call totals and resolution counts, including 734 and 501 interface bindings.
  • Remote: final-head CI 42453029671 completed success at 59f1a8005; website and zip-freshness both passed.
  • Integration: Draft only; no merge, approval, release, installation or Labs update.

Decision input: keep improving the built-in parser. The next step is implementation edges for changed concrete methods, not adopting gopls. No PR merge and no labs/code-analysis update in this round.

Clone this wiki locally