Mod declaration confusion

I moved a lib.rs to lib_static.rs and the [mod x;] declaration in it that worked fine now attracts an 'x not found' error.
but x.rs sits right there in the same directory so how can this possibly be wrong now?

The problem is not clear with the mod structure/layout before and after unknown.

It just reads to me that "I fiddled with some code and files, and it doesn't work any longer".

My guess from what you've said is that you had this:

src/
  lib.rs
  x.rs

Now, you have this:

src/
  main.rs -- or maybe a *new* lib.rs?
  lib_static.rs
  x.rs

If that is the case, then mod x; inside of lib_static.rs would indeed be invalid.

The best solution to this would be to read the documentation regarding modules in Rust, and how the files need to be structured. I'll try to summarise here:

main.rs and lib.rs, when they are the root module of a crate behave slightly differently to other modules. Their "search path" is the directory they are currently in.

When you have a submodule mod lib_static; inside of lib.rs, it will look for the file as either src/lib_static.rs or src/lib_static/mod.rs.

If you try to put a mod x; submodule in lib_static.rs, however, it will look for src/lib_static/x.rs or src/lib_static/x/mod.rs. Basically, once you're not talking about lib.rs or main.rs, submodules are expected to be in a subdirectory named after the module that contains them.

Or, in other words, you can't have an entire module tree in a flat directory. Well, you can, but you have to override paths for that to work, and you really shouldn't do it because it will just confuse everyone else looking at your code. :stuck_out_tongue:

The solution is to move x.rs to lib_static/x.rs.

3 Likes

I thought it more as avoiding superfluous detail.
it is the simplest possible arrangement:
src/lib.rs
src/x.rs
Cargo.toml

I renamed lib.rs to lib_static.rs with lib.rs macro filled
with the content of lib.rs plus extras.
so no change to lib_static.rs other than name for the following result:

error[E0583]: file not found for module `x`
  --> lib/src/lib_static.rs:16:1
   |
16 | pub mod x;
   = help: to create the module `app`, create file "lib/src/lib_static/x.rs" or "lib/src/lib_static/x/mod.rs"
   = note: if there is a `mod x` elsewhere in the crate already, import it with `use crate::...` instead

which suggests to me there is a difference in status of the main library crate file lib.rs versus supporting files.

Actually, this might make it clearer:

Back before, I think it was the 2018 edition of Rust, all modules which contained other modules were required to be laid out like this:

src/
  lib.rs
  lib_static/
    mod.rs
    x.rs

That is, if you had a "module-of-modules", it had to be in $name/mod.rs. In this context, lib.rs and main.rs are just special-cased versions of mod.rs: they are files that represent the root module of the crate, and that module's contents are in that directory.

From 2018 on, you were allowed to name these "module-of-modules" files as $name.rs in the directory of the parent module. However, their child modules still had to be in that subdirectory.

So, yes, lib.rs is special, but less special than you think. It's actually lib_static.rs which is more special, but in a non-obvious way.

(For context: I never liked this change, and felt it would make the module system harder to understand. :P)

Edit: the above ignores the existence of inline modules, because I can't be bothered to explain those as well right now.

3 Likes

Here's the relevant portion of the reference.

2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.