mod Declaration
mod Declaration
Level 7 — Modules, Visibility & Project Structure Declares a submodule; the compiler looks for
mod_name.rsormod_name/mod.rs.
1. Prerequisites
- fn — The blocks of code you are trying to organize.
- Struct — The data structures you want to separate into different files.
2. Term Category
Rust-specific (the project tree builder): In languages like Node.js or Python, the file system is the module system. If you create a file named math.js, the program automatically knows it exists. Rust does NOT work this way!
In Rust, the compiler only looks at your "root" file (main.rs or lib.rs). If you create a new file called math.rs in your folder, the compiler will completely ignore it. The mod keyword is how you explicitly tell the compiler: "Hey, there is another file over there, please include it in the project."
3. Explanation
(1) Design Motivation — "Why did we design this?"
The Rust designers wanted explicit control over the project structure. They didn't want the compiler magically scanning your hard drive and randomly including files just because they happen to be in the folder.
By requiring the mod keyword, you build an explicit "tree" of modules starting from the root. This guarantees that every single file in your compiled binary was explicitly asked for. It also prevents the chaos of having to write confusing relative path imports (like ../../utils.rs) all over your codebase.
(2) Reality Metaphor
Imagine main.rs is the CEO of a company.
You (the developer) hire a new employee and stick them in an office down the hall (you create the file math.rs). The CEO has absolutely no idea the employee exists! If the CEO tries to ask the employee to do work, the CEO will fail.
Writing the mod math; declaration is you walking into the CEO's office and handing them the employee's ID badge. You are explicitly wiring the new file into the company's official organizational chart.
(3) Rust Code Examples
Short Snippet (The basic file link)
This is exactly how you link a separate file into your Rust project.
File: math.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
File: main.rs
// 1. We DECLARE the module. This tells the compiler to look for `math.rs`
mod math;
fn main() {
// 2. Now we can use the code inside that module!
let result = math::add(5, 10);
println!("Result: {}", result);
}
Fuller Example (Inline vs Filesystem)
Modules don't have to be separate files. You can define them inline! But when you do map them to the file system, Rust looks for two specific file paths.
// 1. INLINE MODULE: We define the module right here in the same file.
mod inline_math {
pub fn multiply(a: i32, b: i32) -> i32 {
a * b
}
}
// 2. FILESYSTEM MODULE: We just write `mod name;` without the curly braces.
mod external_math;
// When the compiler sees `mod external_math;`, it looks for exactly two files:
// Option A: `external_math.rs` (in the same directory)
// Option B: `external_math/mod.rs` (if you want a folder for submodules)
fn main() {
println!("{}", inline_math::multiply(5, 5));
}
4. Common Mistakes & Pitfalls
Mistake 1: Confusing mod Declarations with use Import Statements
The mistake: Writing mod foo; everywhere you want to call items inside foo.rs.
Why it is wrong: mod foo; registers a new module file into your crate tree once. It must be declared only once in the parent file. Accessing items from other files should be done with use foo::item;. Declaring mod foo; multiple times causes compiler errors (error: duplicate definition of module 'foo').
Incorrect:
// In file_a.rs:
mod foo; // ❌ Duplicate module declaration!
Fix:
// Declare `mod foo;` once in lib.rs or main.rs, then write `use crate::foo;` in other files!
Mistake 2: Assuming Creating a .rs File Automatically Registers it in Compilation
The mistake: Creating src/network.rs and expecting cargo build to compile it without adding mod network; to src/main.rs.
Why it is wrong: Rust only compiles files attached to the crate root tree. src/network.rs is ignored until declared via mod network;.
Mistake 3: Mixing Legacy mod.rs Directories with Modern Edition Module File Naming
The mistake: Creating both src/foo.rs and src/foo/mod.rs in the same project directory.
Why it is wrong: In 2018+ editions, src/foo.rs acts as the module file for submodules located inside src/foo/. Coexisting src/foo.rs and src/foo/mod.rs causes ambiguous module resolution compiler errors.
5. Practice Exercises
Exercise 1: The Invisible File
Scenario: You are building a game. You have a main.rs and you just created a player.rs file in the same folder. However, when you write player::jump(); in your main.rs, the compiler says use of undeclared crate or module 'player'. How do you fix it?
Answer
Exercise 2: Inline vs File Module Declarations
Scenario: Declare an inline module mod utils { pub fn ping() {} } and call utils::ping().
Expected output:
Answer
Exercise 3: Nested Submodule Hierarchy Declarations
Scenario: Access net::http::client::connect() through nested module paths.
Expected output:
Answer
6. Related Terms
useStatement — The keyword you use to actually import things from the modules you declare withmod.pubVisibility — How you make the functions inside your modules visible to the rest of the project.pub(crate)/pub(super)— Related concept:pub(crate)/pub(super).- Module — Related concept: Module.
7. Key Takeaways
- Rust does not automatically read files just because they are in your folder!
mod name;explicitly tells the compiler to look for a file namedname.rsorname/mod.rsand physically include it in the compiled project.- You only declare a module with
modexactly once in your whole project (where it belongs in the tree). - Do not confuse
mod(which builds the tree) withuse(which creates a shortcut to an item already in the tree).