0

I was trying to create two modules with the same name for different crates, and was surprised that when declaring the second module, it was pointing to the code of the first. Does this mean that module definitions are coupled to the file hierarchy in addition to their place of declaration inside crates?

/src/bin/main_one.rs // contains declaration `mod foo;`
/src/bin/main_two.rs // contains declaration `mod foo;`

/src/bin/foo.rs // Thre can only ever be one foo.rs here

Would the only solution here be to have differently named modules?

src/bin/foo-for-one.rs // module used by one.rs
src/bin/foo-for-two.rs // module used by two.rs

If the same code is reached via its location in the filesystem, what's the point of the mod keyword? Is it for module privacy only?

aryzing
  • 4,982
  • 7
  • 39
  • 42
  • "[I] was surprised that when declaring the second module, it was pointing to the code of the first" – what behavior were you expecting? – Elias Holzmann May 12 '23 at 15:25
  • _/src/bin/foo.rs // Thre can only ever be one foo.rs here_ yes ? If you want an isolation then you need to add another namespace for them, like `src/bin/one/foo.rs` , `src/bin/two/foo.rs` – Ömer Erden May 12 '23 at 15:26
  • @ÖmerErden It should work. – Chayim Friedman May 12 '23 at 15:32
  • 1
    *"Does this mean that module definitions are coupled to the file hierarchy in addition to their place of declaration inside crates?"* - Yes, that is true. Rust does not search through the filesystem on its own, you need to tell it to look for a `mod`. Once you do, it resolves the content of the `mod` by looking for the respective file in the filesystem. – Finomnis May 12 '23 at 15:35
  • 1
    *"Would the only solution here be to have differently named modules?"* - I'd say no. If your bins are so different that they want to use an identically named module with different content, I'd say those two bins shouldn't be in the same package. Create a second package or nested packages, whatever suits your usecase more. – Finomnis May 12 '23 at 15:45
  • I think I don't understand your question. – Chayim Friedman May 12 '23 at 15:50

2 Answers2

6

I'd just use the recommended layout for binaries with multiple files:

src/
└── bin/
    ├── main-one/
    │   ├── main.rs
    │   └── foo.rs
    └── main-two/
        ├── main.rs
        └── foo.rs

where main-one/main.rs has the contents of the previous main-one.rs and analog for main-two.
With foo.rs directly in src/bin you'd have to stop that from being detected as binary anyways, and this way the name conflict goes away automatically.

cafce25
  • 15,907
  • 4
  • 25
  • 31
1

Well, there are 2 options:

  1. Place modules foo inside files main_one.rs and main_two.rs:
// main_one.rs

mod foo {
  // code
}

// main_two.rs

mod foo {
   // code
}
  1. Use #[path = "..."] attribute on mod declaration. E.g. with files foo-for-one.rs and foo-for-two.rs:
// main_one.rs

#[path = "foo-for-one.rs"]
mod foo;

// main_two.rs
#[path = "foo-for-two.rs"]
mod foo;

mod keyword is used either to declare inner module inside of file (like in p. 1) or to add file module to crate (like mod my_mod_name;). In second case, if you don't write this mod declaration, it wouldn't be added to your crate. It is often used for conditional compilation:

// Enable some more features if user requested it.
#[cfg(feature = "my_extra")]
mod my_extra_features;

// Choose different code for different OSes.
#[cfg_attr(windows, path = "windows_impl.rs")]
#[cfg_attr(unix, path = "unix_impl.rs")
mod os;