You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
fix(pipeline): a bare Go reference can bind a struct Field — READS/WRITES/USAGE attach every local err to whichever Field is named err #1942
fix(pipeline): a bare Go reference can bind a struct Field — READS/WRITES/USAGE attach every local err to whichever Field is named err
Status: fix open — PR #1944 (cbm_go_suppress_bare_field_ref() at the same four resolver sites as #1937's guard; stacked on #1937 → #1940). Measured: USAGE onto Go fields 21308 → 0, WRITES 5191 → 0; the combined stack ends below main's totals (USAGE 29198 → 21035, WRITES 2681 → 774) while adding 4533 Field nodes. Found while field-validating #1940 — the third leg of its ordering constraint.
What happens
The READS/WRITES resolvers (pass_usages.c:resolve_rw_edges, pass_parallel.c:resolve_file_rw) and the USAGE registry fallback (resolve_usage_edges / resolve_file_usages) hand bare reference text to cbm_registry_resolve(). The registry contains Field nodes, so a dot-less local —
err:=doWork()
— resolves by simple name to anyField named err, project-wide.
In Go that binding is impossible by construction: a field is only reachable through a selector expression (x.f), and selector references resolve on the LSP path, never through this fallback. Unlike C#/Java/C++/Python, where a method body legitimately references its own members bare (_count++ — cp_reads_writes_cs_static_field pins that as required), so the veto must be Go-gated, not global.
21308 (top: a test struct's field T 3013, events 977, err 759, Path 242, config 221)
WRITES
5191
100% of Field-targeted USAGE edges carried dot-less reference text — no legitimate selector-shaped population is mixed in. (The 612/468 refs onto C/C++ fields surviving #1937 are the legitimate own-member-in-method shape plus C-side noise; untouched by this fix.) The remaining field-targeted class is 2466 CALLS — #1906/#1907's selector-guard territory.
Expected: no edge from Run into Tracker.err. Actual (with #1940 alone): WRITES Run → state.Tracker.err.
Detection recipe
SELECTe.type, count(*) FROM edges e
JOIN nodes t ONt.id=e.target_idWHEREt.label='Field'ANDt.file_pathLIKE'%.go'ANDe.typeIN ('READS','WRITES','USAGE')
GROUP BY1;
Any nonzero row is this bug.
Fix (as landed)
Pure predicate next to #1937's: drop the bind when the file is Go, the target label is Field, and the reference has no .. Wired at both sequential resolvers and both parallel twins; reproduce-first probes on both paths (RED on the #1940 stack), plus unit tests (selector-shaped refs may bind; non-Field targets and non-Go languages untouched).
Related: #1927 (same "nothing checks what a name can denote" class on CALLS), #1928/#1937, #1935/#1940; tracked in #1932.
The ordering was load-bearing rather than cosmetic: landing the ~4600 recovered Field nodes without the reference guard underneath would have minted roughly 5,700 WRITES and 22,000 USAGE name-collision edges onto fields named err, ctx and _.
The suppressor is cbm_go_suppress_bare_field_ref, and it is Go-gated — consistent with the standing decision that call-resolution suppressors stay per-language rather than trading recall globally. cp_reads_writes_cs_static_field pins the C# shape that must keep binding bare member references, and it is untouched.
Remaining in this family, deliberately not folded in: the 2466 field-targeted CALLS edges, which are #1906/#1907 selector-guard territory. #1932 tracks the family.
Activity
fix(pipeline): a bare Go reference never binds a struct Field
fix(pipeline): a bare Go reference never binds a struct Field
fix(pipeline): a bare Go reference never binds a struct Field
fix(pipeline): a bare Go reference never binds a struct Field
DeusData commentedon Aug 31, 2026
Fixed on
mainbycc00a0275efa37bbcf1a2f27da17b33f9b63add4, merged as20e86c02b168ed540aa608e222d8af21ed6db2b3(#1944).This completes the three-PR stack, landed in the order the issue's own measurement required:
fcd8bfc161de19bbFieldnodes existed for ~5055 declarations20e86c02FieldThe ordering was load-bearing rather than cosmetic: landing the ~4600 recovered
Fieldnodes without the reference guard underneath would have minted roughly 5,700WRITESand 22,000USAGEname-collision edges onto fields namederr,ctxand_.The suppressor is
cbm_go_suppress_bare_field_ref, and it is Go-gated — consistent with the standing decision that call-resolution suppressors stay per-language rather than trading recall globally.cp_reads_writes_cs_static_fieldpins the C# shape that must keep binding bare member references, and it is untouched.Remaining in this family, deliberately not folded in: the 2466 field-targeted
CALLSedges, which are #1906/#1907 selector-guard territory. #1932 tracks the family.fix(pipeline): key the Go Field guard on the recorded selector shape,…