Use declaration differences between main.rs and other files

I just discovered that, while in main.rs I can do:

use mylibs::math;

...when mylibs is the name of a module directory. But, from every other file in my project, including another file right next to it in the same directory, say notmain.rs, I must do:

use crate::mylibs::math;

This seems like an odd exception. I read through the docs, and the changes from Rust 2015 to 2018, which seems to confirm what I'm thinking.

I've never seen this explicitly said, though: main.rs (and maybe lib.rs) act differently from all other files in a package / crate. Is this correct? (If this is the case, I may just forgo the mylibs "namespacing" because crate:: communicates the same concept: that this is local code. At least, it does this in non-main.rs files. (!?)

It seems that, except for in main.rs, these paths are interpreted as relative. (?)

EDIT: Another exception I think I found:

  • A mod declaration is required in main.rs but not in other files.

It is because the lib.rs and main.rs files are roots of the library and binary crate in your project respectively, and the binary crate depends on the library crate.

You only use crate:: when something is in your own crate. This means that if main.rs has no mod statements, then it's the only file in the binary crate, and as such the only file that needs mylibs:: instead of crate::.

If you do have mod statements in main, then those files would also need mylibs:: instead of crate:: to access the library crate.

Note that if you have a tests/ or examples/ directory next to the src/ directory, those only depend on the library crate, and can't access things in the binary crate. They would also use mylibs:: to acces the library crate.

3 Likes

Focussing just on main.rs, I find it weird how the rules are different for it. I just found a second one:

  • A mod declaration is required in main.rs but not in other files.

The module tree is explicitly specified by mod statements, starting at the root source code file for the crate (lib.rs/main.rs by default). If there isn’t a code block on the module declaration, rustc looks for a correspondingly-named source code file to use as the module body. A mod declaration inside one of these modules declares a submodule.

The crate:: prefix isn’t required inside main.rs because the modules are locally declared: when you’re at the root of the tree, there’s no difference between relative and absolute paths. Submodules can similarly be used from the source code files that declare them without any prefixes.

It's more accurately viewed through the lens of Rust Editions, the latest being 2018. Before 2018, modules were messier to use, and the 2018 edition straightened that out a bit. This is a result of that progress being made.

1 Like

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.