Modules
A module is a namespace that groups related code together.
Think of modules as:
- folders for logic
- boundaries for visibility (
pubvs private) - a way to avoid name conflicts
Rust modules help you:
- organize large projects
- control what code is accessible from outside
- make APIs clean and safe
The mod Keyword – What It Does
The mod keyword tells Rust:
“There is a module with this name. Load it and make it part of the module tree.”
Example: mod math;
This means:
- A module named
mathexists - Rust should look for its contents in:
math.rs, ormath/mod.rs
Rust’s Module Tree (Mental Model)
Rust organizes code as a tree, starting from the crate root.
Crate Root
main.rs→ binary cratelib.rs→ library crate
Everything starts here.
Example module tree:
crate
├── main.rs
├── math
│ ├── add.rs
│ └── sub.rs
└── utils.rs
Inline Modules (Simple Example)
You can define modules inside a file.
Example: Inline module
mod greetings {
pub fn hello() {
println!("Hello, Rust!");
}
}
fn main() {
greetings::hello();
}
greetingsis a modulehello()is public- Access path:
greetings::hello()
Without pub, hello() would be private
Modules and Privacy Rules
Rust is private by default.
Rule summary
- Items inside a module are private unless marked
pub - Parent modules cannot access private items of child modules
- Child modules can access parent items
mod bank {
fn secret_code() {
println!("1234");
}
pub fn show_code() {
secret_code();
}
}
fn main() {
// bank::secret_code(); ❌ private
bank::show_code(); // ✅ public
}
File-Based Modules (Real-World Style)
Project structure
src/
├── main.rs
└── math.rs
main.rs
mod math;
fn main() {
println!("{}", math::add(2, 3));
}
math.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
mod math;tells Rust to loadmath.rsaddis public → accessible frommain
Nested Modules with Folders
When modules get big, we use directories.
src/
├── main.rs
└── math/
├── mod.rs
├── add.rs
└── subtract.rs
Note: In modern Rust, math.rs can replace math/mod.rs, but mod.rs is still common.
main.rs
mod math;
fn main() {
println!("{}", math::add::add(5, 2));
println!("{}", math::subtract::subtract(5, 2));
}
math/mod.rs
pub mod add;
pub mod subtract;
math/add.rs
pub fn add(a: i32, b: i32) -> i32 {
a + b
}
math/subtract.rs
pub fn subtract(a: i32, b: i32) -> i32 {
a - b
}
mathis a moduleaddandsubtractare submodules- Path:
math::add::addmath::subtract::subtract
use` Keyword – Cleaner Imports
Typing long paths gets annoying. Use use.
mod math;
use math::add::add;
use math::subtract::subtract;
fn main() {
println!("{}", add(10, 5));
println!("{}", subtract(10, 5));
}
This:
- brings functions into scope
- improves readability
pub mod vs mod
| Keyword | Meaning |
|---|---|
mod x; | module exists, private |
pub mod x; | module exists, public |
If a module isn’t public, its contents can’t be accessed outside.
crate, self, and super
These help with relative paths.
| Keyword | Meaning |
|---|---|
crate:: | from crate root |
self:: | current module |
super:: | parent module |
mod outer {
pub fn parent() {}
mod inner {
pub fn child() {
super::parent();
}
}
}
Library Project Structure Example
Structure
src/
├── lib.rs
├── auth/
│ ├── mod.rs
│ └── login.rs
└── utils.rs
lib.rs
pub mod auth;
pub mod utils;
auth/mod.rs
pub mod login;
auth/login.rs
pub fn login_user() {
println!("User logged in");
}
Usage (in another crate)
use mylib::auth::login::login_user;
Why Rust Modules Matter
- Modules help you:
- build clean APIs
- avoid accidental access
- scale projects safely
- keep code readable
Rust’s module system is strict by design, forcing you to think about architecture early.