Extract Rust trait methods - #3383
Conversation
A trait's declaration_list was never walked, so a method it declared had no node at all unless some impl in the same file happened to define a same-named method, in which case that impl's node stood in for it, anchored at the impl's line rather than the declaration's. A trait with no implementor anywhere in the corpus contributed zero method nodes. Two shapes were involved. A default-bodied method (function_item, the same node type an impl method already uses) now walks through the same member handling impl_item already had, via parent_impl_nid=item_nid. A signature-only method (function_signature_item, the grammar's node type for a bodyless fn foo(&self);) had no extraction path at all, so this adds a dedicated branch mirroring function_item's node/edge/parameter and return type handling minus the body it never has. Fixes Graphify-Labs#3366.
|
@safishamsi opened this against #3366 (Rust trait method declarations produced no nodes at all, 77 percent missing across the reporter's real repos). Verified against their exact repro including the no-impl-anywhere case, plus found sample.rs already exercises the signature-only shape and added coverage there. Happy to address any feedback. |
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Extracts trait method declarations in Rust, which the extractor previously skipped entirely: extract_rust now walks a trait's declaration_list, emitting a node and method edge for both bodyless function_signature_items (fn foo(&self);) and default-bodied function_items, anchored at the declaration's own line rather than at some coincidentally-matching impl. This means traits with no implementor anywhere in the corpus, and signature-only methods that had no extraction path at all, now get their methods surfaced. Adds tests covering the signature-only, no-implementor, and default-bodied cases.
No blocking issues surfaced. 2 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 144 functions depend on the 144 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract_rust()— 19 callers, 6 callees - new:
walk()— 1 callers, 8 callees
Verification — 144 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 144 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify extract\_rust.
The verifier did not have enough to check extract\_rust, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set
· 2 more finding(s) on lines outside this diff (see the check run).
What
trait_item's branch minted the trait's own node and walkedtrait_boundsfor supertraits, but never walked the trait'sdeclaration_list, so a method it declared had no node at all unless some impl in the same file happened to define a same-named method, anchored at the impl's line rather than the declaration's.Two shapes needed separate handling:
function_item, the same node type an impl method already uses, so it now routes through that existing branch viawalk(member, parent_impl_nid=item_nid), mirroring whatimpl_itemalready does for its own methods.fn foo(&self);) is afunction_signature_item, a node type that had no handling anywhere in the file at all (confirmed viagrep -rn "function_signature_item"returning nothing). Added a dedicated branch mirroringfunction_item's node/edge/parameter/return-type handling, minus the body it never has.Verified against the reporter's exact repro
And the no-impl-anywhere case (
Lonelytrait, nothing implements it in the corpus): bothonly_signature()andwith_default()now get nodes; previously zero.sample.rs already had this exact shape (
Processor.run/Logger.log, both signature-only, one with an impl in-file and one without), so added coverage there plus a dedicated fixture for the default-bodied case sample.rs doesn't otherwise exercise.Fixes #3366.