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
cbm_go_suppress_bare_field_ref (merged in #1944, 20e86c02) drops a reference edge when the target label is Field, the file is Go, and strchr(ref_name, '.') == NULL. The dot test can never be false for Go, so the predicate is a blanket veto on Field-targeted references rather than the precise guard it documents.
Found during post-merge review of the #1937 → #1940 → #1944 stack.
Why the dot can never appear
Both call paths strip the receiver before the resolver ever sees the name.
READS/WRITES — resolve_lhs_write_name (internal/cbm/extract_semantic.c) documents its own contract:
// - field/member/selector access (`self.total = ...`, `obj.Field = ...` →
// write the trailing field name `total`/`Field`)
So t.err = x yields ref_name == "err", never "t.err".
USAGE — is_reference_node (internal/cbm/extract_usages.c) never treats selector_expression as a reference kind; the only occurrence of that node type in the file is a parent check. The reference is the inner field_identifier/identifier, whose own span is bare.
Consequences
The unit test pins a dead branch.ASSERT_FALSE(..., "t.err", "Field") asserts "selector-shaped refs may bind", but Go's extractor cannot produce that input. It is not a production guarantee.
The census that justified the change is a tautology. "100% of Field-targeted USAGE edges carried dot-less reference text, so there is no legitimate population mixed in" is guaranteed by the extractor, not measured from the data. It cannot distinguish noise from signal, which is the job the predicate was given.
Go Field nodes are reference-unreachable. The ~4588 Field nodes recovered by fix(extract): descend into Go struct field_declaration_list #1940 receive no USAGE/READS/WRITES edges at all, including genuine t.err = x writes and cfg.Timeout reads. Only CALLS can reach them.
Not a regression
main had zero Go Field nodes before #1940, so nothing that previously worked is lost. The accurate description of the merged stack is "adds ~4588 nodes that reference edges cannot reach", not "removes edges".
Cheap falsification
Index a Go repository on current main and count Field-targeted USAGE/READS/WRITES edges. The prediction is zero. A non-zero count disproves this issue.
The signal exists but is discarded
The distinction the predicate wants — field_identifier (the field half of a selector) versus identifier (a bare local) — is computed at extraction time and thrown away before the resolver runs. Threading it through would make the guard precise instead of total, and would let genuine x.f references bind while still refusing bare locals.
Suggested resolution
Either thread the field_identifier signal through to the resolver, or keep the blanket veto and make the docstring and unit test say so honestly — the current pair asserts precision the code does not have.
Summary
cbm_go_suppress_bare_field_ref(merged in #1944,20e86c02) drops a reference edge when the target label isField, the file is Go, andstrchr(ref_name, '.') == NULL. The dot test can never be false for Go, so the predicate is a blanket veto on Field-targeted references rather than the precise guard it documents.Found during post-merge review of the #1937 → #1940 → #1944 stack.
Why the dot can never appear
Both call paths strip the receiver before the resolver ever sees the name.
READS/WRITES —
resolve_lhs_write_name(internal/cbm/extract_semantic.c) documents its own contract:So
t.err = xyieldsref_name == "err", never"t.err".USAGE —
is_reference_node(internal/cbm/extract_usages.c) never treatsselector_expressionas a reference kind; the only occurrence of that node type in the file is a parent check. The reference is the innerfield_identifier/identifier, whose own span is bare.Consequences
ASSERT_FALSE(..., "t.err", "Field")asserts "selector-shaped refs may bind", but Go's extractor cannot produce that input. It is not a production guarantee.Fieldnodes are reference-unreachable. The ~4588Fieldnodes recovered by fix(extract): descend into Go struct field_declaration_list #1940 receive noUSAGE/READS/WRITESedges at all, including genuinet.err = xwrites andcfg.Timeoutreads. OnlyCALLScan reach them.Not a regression
mainhad zero GoFieldnodes before #1940, so nothing that previously worked is lost. The accurate description of the merged stack is "adds ~4588 nodes that reference edges cannot reach", not "removes edges".Cheap falsification
Index a Go repository on current
mainand countField-targetedUSAGE/READS/WRITESedges. The prediction is zero. A non-zero count disproves this issue.The signal exists but is discarded
The distinction the predicate wants —
field_identifier(the field half of a selector) versusidentifier(a bare local) — is computed at extraction time and thrown away before the resolver runs. Threading it through would make the guard precise instead of total, and would let genuinex.freferences bind while still refusing bare locals.Suggested resolution
Either thread the
field_identifiersignal through to the resolver, or keep the blanket veto and make the docstring and unit test say so honestly — the current pair asserts precision the code does not have.