Skip to content

cfg-gated twin functions collapse into one node; get_code_snippet returns the inactive branch's body #495

Open

Description

@metalmon

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

Activity

  1. added
    bugSomething isn't working
    parsing/qualityGraph extraction bugs, false positives, missing edges
    on Jun 18, 2026
  2. DeusData commented on Jun 18, 2026

    @DeusData
    Owner

    Excellent report, thank you @metalmon 🙌 And thanks for cleanly distinguishing it from #405, #478, and #438. You're right that this is a node extraction and snippet fidelity defect, fixable in the C pipeline independent of call graph accuracy.

    The worst part is exactly what you flagged: get_code_snippet silently returning the inactive cfg(not(...)) fallback as if it were the implementation. Our direction is to keep both definitions as distinct nodes keyed by their cfg predicate (which also fixes the complexity and metrics misattribution you noted), possibly with an interim marker noting that a symbol has multiple cfg gated definitions. Common pattern, so worth doing right. Thanks again!

  3. DeusData commented on Jun 28, 2026

    @DeusData
    Owner

    This issue now has a first-class, durable reproduction in the cumulative bug-reproduction suite landing in #667 — a test that pins the exact failing behaviour, so it's tracked and guarded against silent regression. Where #667 also lands the root-cause fix, that's called out in the PR; otherwise the reproduction makes the eventual fix straightforward and verifiable.

    The reproduction goes live once #667 merges. (Posted from the release branch's QA pass.)

  4. added
    priority/normalStandard review queue; useful PR with ordinary maintainer urgency.
    on Jun 30, 2026
  5. added this to the 0.9.1-rc milestone on Jul 8, 2026
  6. added
    priority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.
    and removed
    priority/normalStandard review queue; useful PR with ordinary maintainer urgency.
    on Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edgespriority/highNeeds near-term maintainer attention; high-impact bug, regression, safety issue, or release blocker.

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions