Version
0.10.8 (also reproduces on 0.9.0)
Platform
macOS (arm64), Darwin 25.6.0
Summary
On Rust, a method call whose receiver is a std type loses the receiver at extraction and exact-matches a same-named project method, fabricating a CALLS edge. PathBuf::join, Option::from, Vec::len etc. are attributed to project symbols that the calling file never mentions.
This is the Rust instance of the class already filed for Go (#1906, #1909, #1927) and cross-language (#1572). I did not find a Rust-specific issue open for it — #1694 (cfg-duplicated names) is closed and a different mechanism.
Minimal reproduction
Cargo.toml + a single src/lib.rs:
use std::path::{Path, PathBuf};
/// A project method named `join`. Only `real_caller` below calls it.
pub struct EvidenceTier(pub u8);
impl EvidenceTier {
pub fn join(&self, other: &EvidenceTier) -> EvidenceTier {
EvidenceTier(self.0.max(other.0))
}
}
/// The ONLY legitimate caller of EvidenceTier::join.
pub fn real_caller() -> EvidenceTier {
EvidenceTier(1).join(&EvidenceTier(2))
}
/// Calls std PathBuf::join. Must NOT produce an edge to EvidenceTier::join.
pub fn stdlib_receiver(root: &Path) -> PathBuf {
root.join("subdir")
}
/// Call-expression receiver. Must NOT produce an edge to EvidenceTier::join.
pub fn call_expr_receiver(root: &Path) -> PathBuf {
root.to_path_buf().join("nested")
}
codebase-memory-mcp cli index_repository --repo_path <repro>
codebase-memory-mcp cli query_graph --project <p> \
--query "MATCH (a)-[:CALLS]->(b) RETURN a.name AS caller, b.name AS callee, b.qualified_name AS callee_qn"
Actual
join EvidenceTier ...src.lib.EvidenceTier
real_caller join ...src.lib.EvidenceTier.join <- correct
real_caller EvidenceTier ...src.lib.EvidenceTier
stdlib_receiver join ...src.lib.EvidenceTier.join <- FABRICATED
call_expr_receiver join ...src.lib.EvidenceTier.join <- FABRICATED
Expected
EvidenceTier::join has exactly one caller (real_caller). stdlib_receiver and call_expr_receiver call std::path::Path::join / PathBuf::join, which is not a project symbol and should produce no CALLS edge to a project node.
Scale on a real repo
A 376k-line Rust workspace (860 .rs files, indexed as 53,989 nodes):
|
0.9.0 |
0.10.8 |
total CALLS edges |
26,635 |
34,746 |
| edges targeting stdlib-shaped names1 |
5,728 (21.5%) |
13,065 (37.6%) |
1 target name in new, len, join, iter, from, get, contains, push, take, ok, all, min, max, clone, into, next, insert, unwrap, to_string, … (70 names). Not every one of these is fabricated — some project methods legitimately carry those names — but spot-checks came back 100% fabricated:
scripts/reasoning-helper/src/path_safety.rs::accepts_child_path → EvidenceAxisTier::join.
Real code is root.join("3.8.0"). grep -c EvidenceAxisTier in that file = 0.
plugins/grok-bench-v2/src/checkpoint.rs::absolutize → EvidenceAxisTier::join.
Real code is fn absolutize(root: &Path, path: PathBuf) { root.join(path) }. Same file, EvidenceAxisTier count = 0.
Impact beyond the edges
get_architecture hotspots are ranked by this fabricated fan-in, so the "most important functions" list is wrong, not just noisy — on the repo above the top entries were join(426), matches(343), iter(257), len(234), i.e. std methods. That matches what #1572 reports for Louvain clusters.
Because the answer is confident, well-formed, and wrong, an agent that trusts trace_path for "who calls X" has no signal that it should fall back to grep. Suggestion: when the receiver type cannot be resolved, emit no edge (or a distinctly-typed low-confidence edge that trace_path filters by default) rather than name-matching into the project namespace — and exclude unresolved-receiver edges from hotspot/cluster ranking.
Version
0.10.8 (also reproduces on 0.9.0)
Platform
macOS (arm64), Darwin 25.6.0
Summary
On Rust, a method call whose receiver is a std type loses the receiver at extraction and exact-matches a same-named project method, fabricating a
CALLSedge.PathBuf::join,Option::from,Vec::lenetc. are attributed to project symbols that the calling file never mentions.This is the Rust instance of the class already filed for Go (#1906, #1909, #1927) and cross-language (#1572). I did not find a Rust-specific issue open for it — #1694 (cfg-duplicated names) is closed and a different mechanism.
Minimal reproduction
Cargo.toml+ a singlesrc/lib.rs:Actual
Expected
EvidenceTier::joinhas exactly one caller (real_caller).stdlib_receiverandcall_expr_receivercallstd::path::Path::join/PathBuf::join, which is not a project symbol and should produce noCALLSedge to a project node.Scale on a real repo
A 376k-line Rust workspace (860
.rsfiles, indexed as 53,989 nodes):CALLSedges1 target
nameinnew, len, join, iter, from, get, contains, push, take, ok, all, min, max, clone, into, next, insert, unwrap, to_string, …(70 names). Not every one of these is fabricated — some project methods legitimately carry those names — but spot-checks came back 100% fabricated:scripts/reasoning-helper/src/path_safety.rs::accepts_child_path→EvidenceAxisTier::join.Real code is
root.join("3.8.0").grep -c EvidenceAxisTierin that file = 0.plugins/grok-bench-v2/src/checkpoint.rs::absolutize→EvidenceAxisTier::join.Real code is
fn absolutize(root: &Path, path: PathBuf) { root.join(path) }. Same file,EvidenceAxisTiercount = 0.Impact beyond the edges
get_architecturehotspots are ranked by this fabricated fan-in, so the "most important functions" list is wrong, not just noisy — on the repo above the top entries werejoin(426),matches(343),iter(257),len(234), i.e. std methods. That matches what #1572 reports for Louvain clusters.Because the answer is confident, well-formed, and wrong, an agent that trusts
trace_pathfor "who calls X" has no signal that it should fall back to grep. Suggestion: when the receiver type cannot be resolved, emit no edge (or a distinctly-typed low-confidence edge thattrace_pathfilters by default) rather than name-matching into the project namespace — and exclude unresolved-receiver edges from hotspot/cluster ranking.