Summary
A mechanical probe over the kubernetes CALLS census shows 415 same_module edges lost under receiver-qualified method QNs (#1913) with one thing in common: the target definition lives in a _test.go file while the call site does not. This is an independent defect class — it is not the cross-package collision and not the alias or shadowing shapes — and nothing else tracks it.
What the rows look like
Before: a non-test file calls x.Method(); resolve_same_module hashes the flat pkg.Method and hits — but the sole Method in the package is defined on a test-only type in pkg/foo_test.go. Confidence 0.9, cand=1. That edge was already wrong in the old graph (production code cannot call into a _test.go symbol), it just looked right.
After: the QN is pkg.TestType.Method, the flat hash misses, and the edge disappears. So the "loss" is mostly a loss of wrong edges — but the census cannot tell without reading each one, and there is no rule that makes the graph refuse the binding on principle.
Proposed handling
Go's build model is explicit: symbols declared in _test.go are visible only to the package's test binary. A per-language rule "a call from a non-_test.go file never resolves to a definition in a _test.go file of the same package" is sound by construction, is a pure predicate (file paths on both ends), and fits the existing per-language suppressor pattern (cbm_go_suppress_weak_method_match, cbm_tsjs_suppress_weak_method_match, wired at both pass_calls.c and pass_parallel.c). The 415 rows are the regression fixture set; a handful should be hand-verified first to confirm no legitimate row is among them.
Summary
A mechanical probe over the kubernetes CALLS census shows 415
same_moduleedges lost under receiver-qualified method QNs (#1913) with one thing in common: the target definition lives in a_test.gofile while the call site does not. This is an independent defect class — it is not the cross-package collision and not the alias or shadowing shapes — and nothing else tracks it.What the rows look like
Before: a non-test file calls
x.Method();resolve_same_modulehashes the flatpkg.Methodand hits — but the soleMethodin the package is defined on a test-only type inpkg/foo_test.go. Confidence 0.9,cand=1. That edge was already wrong in the old graph (production code cannot call into a_test.gosymbol), it just looked right.After: the QN is
pkg.TestType.Method, the flat hash misses, and the edge disappears. So the "loss" is mostly a loss of wrong edges — but the census cannot tell without reading each one, and there is no rule that makes the graph refuse the binding on principle.Proposed handling
Go's build model is explicit: symbols declared in
_test.goare visible only to the package's test binary. A per-language rule "a call from a non-_test.gofile never resolves to a definition in a_test.gofile of the same package" is sound by construction, is a pure predicate (file paths on both ends), and fits the existing per-language suppressor pattern (cbm_go_suppress_weak_method_match,cbm_tsjs_suppress_weak_method_match, wired at bothpass_calls.candpass_parallel.c). The 415 rows are the regression fixture set; a handful should be hand-verified first to confirm no legitimate row is among them.