Merge two modules into one

Hello,
I am trying to merge 2 modules to get the same namespace:

  • mod1.rs
pub mod mod0 {
    pub mod sub_mod1 {
        pub struct S1;
    }
}
  • mod2.rs
pub mod mod0 {
    pub mod sub_mod2 {
        pub struct S2;
    }
}
  • main.rs
mod mod1;
mod mod2;
pub use mod1::*;
pub use mod2::*;

fn main() {
mod0::sub_mod1::S1 //ok
mod0::sub_mod2::S2 // not merged
}

I don't want to create a folder or merge the files.
Is it possible ?

Thank you in advance for your help.

mod1::mod0 and mod2::mod0 are separate, distinct modules. Neither of the lines in fn main should work as mod0 is an ambiguous name due to being (glob) imported twice.

There's no automatic way to automatically combine separate modules based on globbed names or the like. You could do it "manually", e.g. for the specific example:

-pub use mod1::*;
-pub use mod2::*;
+// A third distinct `mod0` module
+pub mod mod0 {
+    // That imports everything from the other two
+    pub use super::mod1::mod0::*;
+    pub use super::mod2::mod0::*;
+    // (Still a possibility of ambiguity due to overlapping names though)
+}

You perhaps already know this and don't care, but just in case: this all seems very unidiomatic and you should thus probably find another, more standard way to accomplish your goals.

5 Likes

Yes, I don't undersand why the following code is not accepted in the same file:

pub mod mod0 {
    pub mod sub_mod1 {
        pub struct S1;
    }
}
pub mod mod0 {
    pub mod sub_mod2 {
        pub struct S2;
    }
}

It seems easy for rust-analyzer to merge and check if there are duplicate.
It is probably a design choice, but maybe there is a PR for such a feature.

In some other languages (e.g. C++ and Java), there is some syntax which says “this code should be placed in this namespace”. That is not how Rust’s mod works. mod is defining an item — a named compile-time entity, just like a struct or fn — and the contents of the {} or file give the contents of that module. Modules have several properties besides their contents, such as their visibility and their documentation.

If modules were to be mergeable, there would have to be decisions about how those properties were merged. Also, there would be “action at a distance” due to items in one module-piece being visible in the other; this could even accidentally change the meaning of code (when use ...::* is involved) — unless there was a special rule that they are not visible.

Keeping a module defined in one place also helps with readability; once you find where a module is defined, you know that it isn't also defined in part elsewhere. (Though, this is equally an argument against impl blocks.)

4 Likes

Ok
Thank you for your help.