Skip to content

fix(extract): Go struct fields are never extracted — 0 Field nodes for ~5000 field declarations (structs miss one level of descent) #1935

Description

@ilyabrykau-orca

fix(extract): Go struct fields are never extracted — find_class_body stops one level above field_declaration_list

Status: fix open — PR #1940 (descend struct_typefield_declaration_list before extract_class_fields() iterates + skip blank-identifier _ padding; stacked on #1937). Measured: 0 → 4533 Go Field nodes, each with its declared type in return_type. Ordering: must land with #1937 (cross-language refs) and #1944 (bare-ref-vs-Field, found while validating this) under it — see below.

What happens

go_field_types[] = {"field_declaration"} is registered in lang_specs.c; the extractor just never reaches those nodes. find_class_body() returns type_spec's type child:

  • interface: interface_type holds its method specs directly → always worked;
  • struct: struct_type's only named child is a field_declaration_list, one level above the field_declarations the member loop matches → every field silently skipped. parse_partial flags nothing (the file parses clean).

Damage measured (~1150-file Go repo)

source graph
Go struct field declarations ~5055 (4846 named, 208 embedded) 0
Field nodes in the whole graph 850, all C/C++
Go interface method declarations 342 present

No Config.Timeout, no Event.PID; trace_path data-flow stops at the struct; nothing exists for a declared-type resolver (#1927's guard rationale) to consult; func-typed-field call dispatch has no node to reach — probed with type Router struct{ fn func(int) error }: r.fn(4) binds Router.fn once fields exist, and without them the call is dropped or free to be hijacked by an unrelated same-named symbol.

Minimal reproduction

package fxf

type Config struct {
	Name    string
	Timeout int
	Nested  *Config
}

type Reader interface {
	Read(p []byte) (int, error)
	Close() error
}

Actual: Struct Config, Interface Reader, both interface Methods — no node for Name/Timeout/Nested. After the fix: three Field nodes with return_type string/int/*Config; interface members unchanged.

Detection recipe

SELECT CASE WHEN file_path LIKE '%.go' THEN 'go' ELSE 'other' END, count(*)
FROM nodes WHERE label='Field' GROUP BY 1;

Zero go rows on a struct-bearing Go repo is this bug.

Why this must not land alone (measured, twice)

Recovering ~4.5k nodes named err/ctx/path/_ exposes the reference resolvers:

  1. Cross-language slicefix(pipeline): USAGE and WRITES edges have no cross-language guard — 31% of WRITES on a Go+C repo cross the Go/C boundary #1928/fix(pipeline): guard USAGE/WRITES/READS against cross-language binds #1937: without the guard, ~5.7k WRITES / ~22k USAGE minted, many across the Go↔C boundary.
  2. Same-language slicefix(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 never binds a struct Field #1944 (found field-validating this stack): even with fix(pipeline): guard USAGE/WRITES/READS against cross-language binds #1937, bare Go locals bound the new fields project-wide — USAGE onto Go fields 21308, WRITES 5191, top target a test struct's field T with 3013 edges. A bare identifier can never denote a Go field (selector-only access), so fix(pipeline): a bare Go reference never binds a struct Field #1944 vetoes those binds.

With both guards under it the full stack ends below main's reference totals (USAGE 29198 → 21035, WRITES 2681 → 774) while adding the nodes. Embedded fields (~208) stay unrepresented by construction (no name child) — separate follow-up; lsp_embed_dispatch unaffected. Blank _ padding fields are skipped (55 nodes, 241 collision edges otherwise).

Related: #451 (same feature, Python), #1939 (field-chain dispatch, consumes these nodes); tracked in #1932.

Metadata

Metadata

Assignees

No one assigned

    Labels

    parsing/qualityGraph extraction bugs, false positives, missing edgesstability/performanceServer crashes, OOM, hangs, high CPU/memory

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions