Repository navigation
Description
Version: codebase-memory-mcp v0.12.1 (pkg/go/v0.12.1, a7158ac). main at 612eee2 has the
same parser (internal/cbm/extract_imports.c:1900, identical body) and the same lookup
(src/pipeline/registry.c:1859, called at :2321).
What I did
I indexed jdx/mise v2026.11.2 and compared its CALLS edges with a rust-analyzer SCIP index of
the same checkout. src/cli/run.rs:27 imports the handler in a group:
use crate::task::task_output_handler::{OutputHandler, SummaryOutcome};and src/cli/run.rs:1808 calls OutputHandler::new(output_config). SCIP links the call to the
one OutputHandler.new in the project; cbm has no edge. Of mise's 5,172 Rust IMPORTS edges,
1,912 have a local_name that starts with {.
To isolate it I wrote a probe crate (mode full, cbm 0.12.1):
// src/h.rs
pub struct Handler { pub n: u32 }
impl Handler { pub fn new() -> Self { Handler { n: 1 } } }
pub struct Other;
// src/a.rs
use crate::h::{Handler, Other};
pub fn grouped() -> u32 { let _o = Other; Handler::new().n }
// src/b.rs
use crate::h::Handler;
pub fn single() -> u32 { Handler::new().n }I indexed it twice: with src/many.rs empty, and with many.rs holding 300
pub struct S{i}; impl S{i} { pub fn new() -> Self { S{i} } }. The second run pushes the bare
name new past the registry's 256-candidate cap, so the name lookup can't cover for the import map.
What happened
| file | IMPORTS local_name |
Handler::new(), many.rs empty |
with 300 more news |
|---|---|---|---|
src/b.rs |
Handler |
edge, import_map |
edge, import_map |
src/a.rs |
{Handler, Other} |
edge, unique_name |
no edge |
a.rs also gets only one IMPORTS edge, to Handler. The import of Other is lost.
Why
parse_rust_imports (internal/cbm/extract_imports.c:1099-1127) makes one CBMImport per
top-level use_declaration. module_path is the whole text after use , and
local_name = path_last(full). path_last (:99-113) cuts after the last /, ., : or \,
so for crate::h::{Handler, Other} the local name is {Handler, Other}.
The IMPORTS edge stores that local name (src/pipeline/pass_parallel.c:1862-1866). The call-time
import map is built from those edges (src/pipeline/pass_lsp_cross.c:1007, read at :1054-1066).
resolve_import_map (src/pipeline/registry.c:1350) looks the callee's first segment up by exact
key (:1360-1368). Handler never equals {Handler, Other}, so the lookup is empty (:1370-1371)
and resolution falls through to the name lookup.
Proposal
- Walk the
use_listandscoped_use_listchildren and push one import per member:- each with its own local name: the member's last segment, or its alias for
as; - each with its full path, the group's prefix joined to the member;
selfin a group (use a::b::{self, C}) bindsb.
- each with its own local name: the member's last segment, or its alias for
- Do the same for nested groups (
use a::{b::{C, D}, E}). - Add an extractor test:
use crate::h::{Handler, Other as O};gives two imports,Handler→
crate::h::HandlerandO→crate::h::Other.
Activity
DeusData commentedon Nov 10, 2026
Fixed by #2932, merged in d40ebf6. Grouped
usedeclarations are now expanded into one import per member (nested groups,self, renames and globs included), so a call likeHandler::new()behinduse crate::h::{Handler, Other};resolves through the import map. Thank you, @sortakool, for the precise report and the minimal reproduction: the 300-newprobe went straight into the regression test, and your mise numbers (5,172 imports, 1,912 with a{local name) matched our measurement exactly. And thank you, @kasheeesh08, for the fix!fix(rust): resolve use paths inside the importing crate