Skip to content

rust: unit structs (struct Unit;) are not indexed, taking their impl Trait for edges with them #1513

Description

@ctype-lab

codegraph extracts no symbol at all for a Rust unit struct (struct Unit;),
so the type is absent from the graph — and so is everything attached to it. The
most visible loss is impl SomeTrait for Unit: the edge never forms, because its
source endpoint does not exist.

Brace structs (struct S { .. }) and tuple structs (struct S(u32);) are
extracted normally. Only the unit form is affected.

The grammar parses the file correctly, so this is in the symbol-extraction layer,
not the grammar.

Environment

  • codegraph: 1.5.0 (npm), reproduced again on main @ d6d1728
  • Backend: node:sqlite (WAL)
  • Platform: Linux x64
  • Both extraction paths affected: the native kernel and the wasm/TS walker
    (CODEGRAPH_KERNEL=0)

Repro

src/lib.rs:

pub struct UnitStruct;
pub struct TupleStruct(pub u32);
pub struct BraceStruct { pub x: u32 }

pub trait Greet { fn hi(&self) -> String; }

impl Greet for UnitStruct  { fn hi(&self) -> String { "unit".into()  } }
impl Greet for TupleStruct { fn hi(&self) -> String { "tuple".into() } }
impl Greet for BraceStruct { fn hi(&self) -> String { "brace".into() } }
codegraph init .
sqlite3 .codegraph/codegraph.db \
  "SELECT kind, name FROM nodes WHERE kind IN ('struct','trait') ORDER BY name;"

Expected

Three struct nodes and three implements edges.

Actual

Two of each — UnitStruct is missing, and with it the Greet <- UnitStruct
realization.

struct  BraceStruct
struct  TupleStruct
trait   Greet
Greet <|.. TupleStruct
Greet <|.. BraceStruct

Impact

Unit structs are the idiom for zero-sized markers, test doubles and stub
implementations, so the loss concentrates in test and adapter layers rather than
being spread evenly.

On a 2,669-node Rust/TypeScript repository, re-indexing after a local fix
recovered 13 structs and 9 implements edges — every one of them a unit
struct such as SystemClock, StubTransport, MockEncoder, StubSettings.
Asking for implementors of a trait, or the impact radius of one, silently omitted
these.

Cause

extractStruct treats a missing body field as a forward declaration and returns
before minting the node. That is correct for C/C++ (struct Foo; really is a
forward declaration) but Rust has no forward declarations — a bodiless struct
is always a complete definition.

This looks like the same case two earlier patches already recognised:

Struct kept the unconditional skip, so Rust was never covered.

The kernel's Rust walker mirrors the behavior deliberately — it is listed in
rustlang.rs's bug-for-bug quirk header and in the R7b port checklist — so both
walkers need the same change to stay at parity.

I have a fix ready and will open a PR referencing this issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions