Skip to content

fix(rust): wrap modules in mod name { ... } instead of inlining (#1)#3

Merged
iray-tno merged 1 commit into
mainfrom
feature/1_wrap_modules_to_avoid_name_collisions
Jun 3, 2026
Merged

fix(rust): wrap modules in mod name { ... } instead of inlining (#1)#3
iray-tno merged 1 commit into
mainfrom
feature/1_wrap_modules_to_avoid_name_collisions

Conversation

@iray-tno
Copy link
Copy Markdown
Owner

@iray-tno iray-tno commented Jun 3, 2026

Closes #1.

Problem

prepkit rust preprocess flattened modules by inlining each module's body into a single shared namespace and then stripping mod:: qualifiers with a regex. Any project where two modules defined an item with the same name collided once inlined:

// geometry.rs and search.rs each define `pub fn helper`
pub fn helper() -> i32 { 1 }
pub fn helper() -> i32 { 2 }   // error[E0428]: the name `helper` is defined multiple times

Fix

Flatten by wrapping instead: every mod name; declaration is recursively expanded into an inline mod name { <body> } block. Each module keeps its own namespace, so:

This mirrors cargo-equip's approach and lets prepkit handle library-style multi-module projects, not just flat single-namespace ones.

The old module-discovery + dependency-graph + topological-sort machinery is dropped: Rust resolves items crate-wide regardless of declaration order, so wrapped modules need no reordering.

Example

Input main.rs + utils.rs

mod utils {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
}

fn main() {
    let result = utils::add(5, 3);
    println!("Result: {}", result);
}

Tests

  • New name_collisions fixture (the exact reproduction from the issue) + regression test, including an rustc compile check.
  • Updated test_glob_imports / test_inline_modules_preserved to assert the new (correct) qualifier-preserving behavior.
  • Regenerated 4 snapshots to reflect wrapped output.
  • Full suite: all green; every fixture output compiles under rustc (edition 2021).

🤖 Generated with Claude Code

Module flattening previously inlined each module's body into a single
shared namespace and then stripped module qualifiers with a regex. Any
project where two modules defined an item with the same name (e.g.
`helper`) failed to compile with E0428 once the bodies collided.

Flatten by wrapping instead: every `mod name;` declaration is expanded
recursively into an inline `mod name { <body> }` block. Each module keeps
its own namespace, so:

- same-named items across modules no longer collide;
- qualified paths (`crate::a::b`, `mod::fn()`) keep resolving, so the
  separate qualifier-stripping step is gone;
- `use` statements (including globs) are preserved rather than removed;
- `//!` module docs stay valid as the first item inside the block.

This mirrors cargo-equip's approach and lets prepkit handle library-style
multi-module projects, not just flat single-namespace ones. The dependency
graph / topological sort is dropped: Rust resolves items crate-wide
regardless of order, so wrapped modules need no reordering.

Adds the name-collision reproduction as a fixture + regression test
(incl. an rustc compile check) and updates snapshots and the README.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@iray-tno iray-tno merged commit 84feaf9 into main Jun 3, 2026
2 checks passed
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 preprocess: flatten by wrapping modules in mod name { ... } to avoid name collisions

1 participant