fix(rust): index unit structs — bodiless is a definition, not a forward decl (#1800)
Land upstream PR #1514 for issue #1513 by cherry-picking
ctype_lab's a94c9dc94eee348bf63c7e2dd567c0b43577678a.
Keep allowBodilessStruct as a Rust-only opt-in, with matching behavior in
the wasm/TypeScript walker and native kernel. Create the node before
checking for a body and walk members only when present. Resolve against
main's shared struct/union walker while retaining its stack guard, kinds,
fields, and existing impl-receiver fixes.
Verified FAIL to PASS on Linux x64 with Node 22.19.0 after rebuilding via
tsc, copy-assets, and build:kernel. The identical fixture on main 7b339373
had two structs and two implements edges; fresh wasm (CODEGRAPH_KERNEL=0)
and native indexes now have three of each. UnitStruct and its Greet
implements edge are recovered; tuple and brace structs remain intact.
The native run loaded the rebuilt kernel and completed without fallback.
Focused extraction.test.ts and kernel-rustlang-parity.test.ts runs:
645 tests passed with the kernel disabled, and 645 with it enabled;
all three parity tests ran in each configuration, with no skips.
(cherry picked from commit a94c9dc94eee348bf63c7e2dd567c0b43577678a)
Co-authored-by: ctype_lab <cksgud1226@gmail.com>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
ctype_lab
Claude Opus 5
parent
7b339373b4
commit
71d049cd28
@@ -1252,6 +1252,35 @@ pub struct User {
|
||||
expect(structNode?.name).toBe('User');
|
||||
});
|
||||
|
||||
it('should extract unit and tuple structs, not just brace structs', () => {
|
||||
// A unit struct has no body field, but it IS a complete definition —
|
||||
// Rust has no forward declarations. Skipping it dropped the type and
|
||||
// every `impl Trait for UnitStruct` edge with it.
|
||||
const code = `
|
||||
pub struct Unit;
|
||||
pub struct Tuple(pub u32);
|
||||
pub struct Brace { pub x: u32 }
|
||||
`;
|
||||
const result = extractFromSource('shapes.rs', code);
|
||||
|
||||
const structs = result.nodes.filter((n) => n.kind === 'struct').map((n) => n.name).sort();
|
||||
expect(structs).toEqual(['Brace', 'Tuple', 'Unit']);
|
||||
});
|
||||
|
||||
it('should link impl Trait for a unit struct', () => {
|
||||
const code = `
|
||||
pub struct Unit;
|
||||
pub trait Greet { fn hi(&self) -> String; }
|
||||
impl Greet for Unit { fn hi(&self) -> String { "unit".into() } }
|
||||
`;
|
||||
const result = extractFromSource('greet.rs', code);
|
||||
|
||||
const unit = result.nodes.find((n) => n.kind === 'struct' && n.name === 'Unit');
|
||||
expect(unit).toBeDefined();
|
||||
const trait = result.nodes.find((n) => n.kind === 'trait' && n.name === 'Greet');
|
||||
expect(trait).toBeDefined();
|
||||
});
|
||||
|
||||
it('should extract trait declarations', () => {
|
||||
const code = `
|
||||
pub trait Repository {
|
||||
|
||||
@@ -5,7 +5,8 @@
|
||||
* SAME ExtractionResult as the wasm TreeSitterExtractor — nodes, edges, and
|
||||
* unresolved refs compared as canonicalized multisets — over the checked-in
|
||||
* torture fixture (torture.rs: impl/trait quirks incl. generic / lifetime /
|
||||
* reference / scoped / generic-trait impl receivers (#1588), unit-struct skip, phantom
|
||||
* reference / scoped / generic-trait impl receivers (#1588), unit structs
|
||||
* (a bodiless struct IS a definition — both walkers mint a node), phantom
|
||||
* const identifiers, use-binding refs incl. nested groups + wildcard-emits-
|
||||
* nothing, chained-call re-encode, turbofish, Rocket route macros body-only,
|
||||
* fn-ref shapes, value-ref shadowing, attribute-broken docstrings, dead-code
|
||||
|
||||
Reference in New Issue
Block a user