Bug Description
When two items share a qualified name and are distinguished only by #[cfg(...)] attributes (the common Rust #[cfg(feature = "x")] / #[cfg(not(feature = "x"))] pair), the indexer stores a single graph node. get_code_snippet then returns the body of one arbitrary branch — in practice the inactive/fallback one — silently hiding the real implementation. An agent asking "what does f do?" gets a misleading answer (e.g. "it's a no-op returning None") when the feature-enabled build has a full implementation.
Steps to Reproduce
Index any Rust crate containing a cfg-gated twin, e.g.:
#[cfg(feature = "rag-pdf")]
fn try_extract_pdf_text(bytes: &[u8]) -> Option<String> {
if bytes.len() < 5 || &bytes[..5] != b"%PDF-" { return None; }
/* real extraction */
}
#[cfg(not(feature = "rag-pdf"))]
fn try_extract_pdf_text(_bytes: &[u8]) -> Option<String> { None }
query_graph: MATCH (n) WHERE n.name = 'try_extract_pdf_text'
RETURN n.qualified_name, n.start_line, n.end_line, n.signature
Observed
total: 1 — only one node exists for the two definitions.
- It is the
#[cfg(not(...))] stub: start_line 385, end_line 387, signature (_bytes: &[u8]).
get_code_snippet returns fn try_extract_pdf_text(_bytes: &[u8]) -> Option<String> { None } — the real #[cfg(feature = "rag-pdf")] impl (lines 372–383) is absent from the graph entirely.
Expected
Either (a) keep both definitions as distinct nodes tagged by their cfg predicate, or (b) at minimum surface that the symbol has multiple cfg-gated definitions so get_code_snippet can't silently return a non-representative branch. Returning the inactive fallback as if it were the implementation is the worst outcome.
Impact
get_code_snippet — a core tool — can return source that is misleading or the opposite of the real behavior.
- Complexity/metrics (
complexity, cognitive, bt) are computed from whichever branch wins, so they misrepresent the active build.
- Common in real Rust:
#[cfg(feature)], #[cfg(test)], #[cfg(unix)]/#[cfg(windows)] twins.
Relation to existing issues
Distinct from #405 (which targets call-edge resolution via the rust-analyzer integration) — this is a node-extraction / snippet-fidelity defect that's independent of call-graph accuracy and fixable in the existing C pipeline. Not #478 (cross-package bare-name collision) nor #438 (edge→Module attribution).
Environment
- codebase-memory-mcp
v0.8.1
- Project: Rust workspace (~786 Rust files), Windows 11
- Repro symbol:
crates/zeroclaw-runtime/src/tools/file_read.rs
Bug Description
When two items share a qualified name and are distinguished only by
#[cfg(...)]attributes (the common Rust#[cfg(feature = "x")]/#[cfg(not(feature = "x"))]pair), the indexer stores a single graph node.get_code_snippetthen returns the body of one arbitrary branch — in practice the inactive/fallback one — silently hiding the real implementation. An agent asking "what doesfdo?" gets a misleading answer (e.g. "it's a no-op returningNone") when the feature-enabled build has a full implementation.Steps to Reproduce
Index any Rust crate containing a cfg-gated twin, e.g.:
Observed
total: 1— only one node exists for the two definitions.#[cfg(not(...))]stub:start_line 385,end_line 387,signature (_bytes: &[u8]).get_code_snippetreturnsfn try_extract_pdf_text(_bytes: &[u8]) -> Option<String> { None }— the real#[cfg(feature = "rag-pdf")]impl (lines 372–383) is absent from the graph entirely.Expected
Either (a) keep both definitions as distinct nodes tagged by their
cfgpredicate, or (b) at minimum surface that the symbol has multiple cfg-gated definitions soget_code_snippetcan't silently return a non-representative branch. Returning the inactive fallback as if it were the implementation is the worst outcome.Impact
get_code_snippet— a core tool — can return source that is misleading or the opposite of the real behavior.complexity,cognitive,bt) are computed from whichever branch wins, so they misrepresent the active build.#[cfg(feature)],#[cfg(test)],#[cfg(unix)]/#[cfg(windows)]twins.Relation to existing issues
Distinct from #405 (which targets call-edge resolution via the rust-analyzer integration) — this is a node-extraction / snippet-fidelity defect that's independent of call-graph accuracy and fixable in the existing C pipeline. Not #478 (cross-package bare-name collision) nor #438 (edge→Module attribution).
Environment
v0.8.1crates/zeroclaw-runtime/src/tools/file_read.rs