Skip to content

fix(rust): expand grouped use imports - #2932

Merged
DeusData merged 3 commits into
DeusData:mainfrom
kasheeesh08:fix/rust-grouped-imports-2922
Nov 10, 2026
Merged

DeusData merged 3 commits into
DeusData:mainfrom
kasheeesh08:fix/rust-grouped-imports-2922

Conversation

@kasheeesh08

Copy link
Copy Markdown
Contributor

Fixes #2922

Summary

Fixes Rust grouped use import extraction so grouped imports are expanded into individual import paths.

The extractor now handles nested grouped imports, aliases, self, and wildcard imports recursively.

Changes

  • Added a recursive tree-sitter use-tree walker.
  • Expanded grouped Rust imports into individual CBMImport records.
  • Preserved support for simple imports.
  • Added regression coverage for grouped, nested, aliased, self, and wildcard imports.
  • Added an end-to-end pipeline regression for the grouped-import resolution failure.

Testing

Local test execution was blocked by Windows sandbox environment restrictions. No local test results are claimed.

GitHub Actions CI is expected to provide authoritative test and lint verification.

@kasheeesh08
kasheeesh08 requested a review from DeusData as a code owner November 7, 2026 17:50
@github-actions

github-actions Bot commented Nov 7, 2026

Copy link
Copy Markdown

Thanks for opening this — it has been seen, and it is queued.

This note is automated, but it is not a brush-off: it exists so you know where your PR stands instead of having to guess from silence.

Current review status: working through a backlog. 0.9.1-rc.1 is out, so the release freeze that held reviews is over — but it left a large queue of open pull requests behind it, and we are reading through them oldest-first. The background is in discussion #1144.

What that means for this PR, concretely:

  • It will not be closed for inactivity. No stale bot touches pull requests here.
  • It may still sit a while before a human reads it. That is on us, not on you.
  • Older PRs are read first, so a recent one is not being skipped — it is behind a queue.

Things that will genuinely speed it up whenever review does happen:

  • Keep it rebased on main — the tree is moving quickly right now, and a conflicting branch cannot be reviewed as the diff you intended.
  • Get CI green, or say which failures you believe are pre-existing.
  • Keep the change to one claim. Bundled features and refactors get split before they get merged, which costs you a round trip.
  • Every commit needs a sign-off (git commit -s) — CI enforces DCO.

If this fixes a bug, a reproduction we can run is worth more than a description of the symptom.

Thanks for contributing, and sorry in advance for the wait.

@DeusData

DeusData commented Nov 9, 2026

Copy link
Copy Markdown
Owner

Thank you so much, @kasheeesh08, and welcome! We reviewed this carefully and it is ready to merge: walking the use tree through the grammar's own fields handles every form we tried (nested groups, self inside a group, renames, globs inside a group, pub use, trailing commas and comments inside the braces), and both of your tests fail on the old extractor and pass with your change. On jdx/mise, the project from #2922, every grouped import now binds its own name.

Another change that just merged also edits tests/test_pipeline.c (different tests, no conflict), so we merged current main into your branch - a plain signed-off merge commit, your change is untouched - to get a fresh CI run on the exact tree that will merge. Nothing is needed from you: it merges as soon as that run is green. If you push again, please pull first so the merge commit is kept.

@DeusData
DeusData merged commit d40ebf6 into DeusData:main Nov 10, 2026
26 checks passed
@DeusData

Copy link
Copy Markdown
Owner

Thank you so much, @kasheeesh08, for this fix, and welcome to the project! Walking the use tree through the grammar's own fields (argument, path, list, alias) instead of slicing the declaration text is exactly the right approach, and it handles every form we tried: nested groups, self inside a group, as renames, globs inside a group, a group with no prefix, pub use, trailing commas and comments inside the braces. Your tests are spot on too: both fail on the old extractor and pass with your change, and the pipeline test reproduces the exact case from #2922, where more than 256 new candidates leave only the import map to bind the call.

We also measured the change on two real Rust workspaces, jdx/mise (the project from the issue) and meilisearch. Every grouped import now binds its own name: on mise the 1,912 import edges whose local name started with { are gone and Rust import edges go from 5,172 to 8,964, calls resolved through the import map go from 927 to 2,303 (791 to 2,427 on meilisearch), OutputHandler::new in mise's src/cli/run.rs now links to its definition, and repeated runs produce identical graphs. As a bonus, pub use re-exports and plain use a::b as c; imports now get the right path and name as well.

Merged in d40ebf6. Thanks again for the careful work!

taggedzi pushed a commit to taggedzi/codebase-memory-mcp that referenced this pull request Nov 10, 2026
In a Cargo workspace a relative `use` bound a sibling crate's item. The
import resolver has no Rust branch, so `crate::util::helper` fell through
to the project-wide symbol-name fallback (Strategy 3), which matches the
last path segment, then every enclosing segment, against every same-named
definition in the project and keeps the lexicographically smallest QN:
whichever crate sorts first. The same fallback bound imports of external
crates to project symbols by name (`use serde_json::json` -> the project's
own `json` function, and every `json!` call through import_map) and let a
module segment bind a function (`crate::util::Gone` -> fn `util`), while
Strategy 4 resolved `crate::`, `self::` and `super::` from the repository
root instead of the crate's module root.

A Rust import of a file under a Cargo.toml is now classified by its first
path segment and resolved inside exactly one crate:
- `crate::` is the importing crate's module root: the nearest Cargo.toml's
  src/ (or tests/, benches/, examples/; a build script is its own root);
- `self::` / `super::` are relative to the importing file's module path;
- a child module of the importing module is that module (2018 paths);
- a workspace member's crate name (a package `foo-bar` is `foo_bar`) is
  that member;
- anything else (std, core, a dependency) binds no project symbol.
Inside the crate the item at the module the path names wins, else the
module the full path names, else a same-named item in a submodule of that
module (a re-export from below), else the type an associated item or enum
variant belongs to. Nothing else is guessed, ties break on module-path fit
then QN, and files with no Cargo.toml above them keep the generic
strategies. The CALLS import map is built from these IMPORTS edges in both
drivers, so import_map CALLS follow.

On jdx/mise this removes all 720 relative IMPORTS that crossed into
another workspace crate, all 1,123 IMPORTS bound through an external-crate
path and all 259 import_map CALLS that followed them; IMPORTS and
import_map CALLS into a crate the caller does not depend on drop from
920 and 12 to 0. Wall time and index worker peak RSS are unchanged; a
non-Rust control graph is byte-identical.

Strategy 4's module-prefix loop moves into resolve_module_prefixes so the
crate tree can reuse its lookup (plus the mod.rs form); Strategy 4's own
behaviour is unchanged.

Refs DeusData#2922, DeusData#2932

Signed-off-by: Martin Vogel <[email protected]>
@DeusData DeusData mentioned this pull request Nov 10, 2026
4 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rust: a grouped use a::{B, C} becomes one import with local name {B, C}, so calls through it never use the import map

2 participants