Skip to main content

Modules

A module is a namespace that groups related code together.

Think of modules as:

  • folders for logic
  • boundaries for visibility (pub vs 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 math exists
  • Rust should look for its contents in:
    • math.rs, or
    • math/mod.rs

Rust’s Module Tree (Mental Model)

Rust organizes code as a tree, starting from the crate root.

Crate Root

  • main.rs → binary crate
  • lib.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();
}
  • greetings is a module
  • hello() 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 load math.rs
  • add is public → accessible from main

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
}
  • math is a module
  • add and subtract are submodules
  • Path:
    • math::add::add
    • math::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

KeywordMeaning
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.

KeywordMeaning
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.