Skip to content

fix(go): don't emit embeds for interface type-set constraints#1818

Open
Synvoya wants to merge 1 commit into
Graphify-Labs:v8from
Synvoya:fix/go-interface-type-union-not-embeds
Open

fix(go): don't emit embeds for interface type-set constraints#1818
Synvoya wants to merge 1 commit into
Graphify-Labs:v8from
Synvoya:fix/go-interface-type-union-not-embeds

Conversation

@Synvoya

@Synvoya Synvoya commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Problem

The Go extractor treats every interface type_elem as an embedded interface.
But a Go type-set constraint (generics) is not embedding — a union
A | B or an approximation ~T is a set of type terms, and Go only ever
embeds a lone interface type. Because the branch walked union terms the same
way it walks an embedded interface, each non-predeclared term produced a
spurious embeds heritage edge.

Reproduction on v8 HEAD

package p
type MyInt int
type MyFloat float64
type Number interface {
    MyInt | MyFloat
}

extract_go emits:

Number --embeds--> MyInt
Number --embeds--> MyFloat

embeds is a heritage relation (grouped with inherits / implements /
mixes_in in extract.py), so this asserts a composition/method-promotion
relationship that does not exist — Number cannot embed the concrete types
MyInt/MyFloat; they are constraint terms. This pollutes heritage queries
over the graph with false edges.

Fix

Detect a type-set type_elem (it has a | or a negated_type child — both
tokens appear only in constraint position, never in embedding) and reclassify
its terms as references (context="type_constraint") instead of embeds.
This keeps the type link but drops the false heritage claim. The edge count is
unchanged; only the relation/context is corrected.

Genuine interface embedding is untouched — a lone interface term
(Reader, io.Reader, Sortable[int]) has no |/~, so it still emits
embeds.

Tests

Added to tests/test_languages.py:

  • test_go_interface_type_union_is_not_embeddingnegative control:
    union terms must not be embeds, and are present as
    references/type_constraint. Fails on HEAD (asserts the spurious
    Number->MyInt embed away), passes with the fix.
  • test_go_interface_embedding_emits_embeds /
    test_go_struct_embedding_emits_embeds — positive guards that genuine
    embedding on the existing sample.go fixture (ReaderLogger embeds
    Logger/Reader; DataProcessor embeds BaseProcessor) still works.

python3 -m pytest tests/test_languages.py -q317 passed, 13 skipped
(the 13 skips are the optional tree-sitter-dm grammar). No behavior change
outside Go interface type-set constraints.

An interface type_elem that is a generics type-set constraint - a union
(`A | B`) or an approximation (`~T`) - was walked like an embedded
interface, so each non-predeclared term produced an `embeds` heritage
edge (e.g. `type Number interface { MyInt | MyFloat }` emitted
Number->MyInt and Number->MyFloat embeds).

Go only embeds a lone interface type, and each embed is its own element;
union/approximation terms are a constraint type set that can never be
embedded, so those edges assert composition that does not exist. Detect
type-set elems (a `|` or `negated_type` child) and reclassify their
terms as `references` (context=type_constraint), preserving the type
link without the false heritage edge. Genuine interface embedding
(single/qualified/generic interface terms) is unchanged.

Adds regression coverage: positive guards for struct and interface
embedding, plus a negative control asserting union terms are not embeds.
@Synvoya
Synvoya force-pushed the fix/go-interface-type-union-not-embeds branch from bc877de to 72ddb3a Compare July 22, 2026 11:19
@Synvoya

Synvoya commented Jul 22, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto current v8 and revalidated this fix. The focused Go regression tests pass locally, the full local Python 3.12 suite passes (3552 passed, 3 skipped), and the fresh GitHub CI matrix is green on Python 3.10 and 3.12.

This is the strongest, most self-contained fix in my open extractor batch, so I’d appreciate prioritizing this one. I’ll hold off on additional Graphify PRs while the existing batch is reviewed, and I’m happy to adjust or close lower-priority items if you prefer a narrower queue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant