Rust Modules
Every example so far has lived in one main.rs file. That’s fine for small programs, but real projects split code into logical pieces. Rust’s tool for that is the module system — mod, pub, and use.
Defining a module
Section titled “Defining a module”A module is a named block that groups related code together:
mod math { pub fn add(a: i32, b: i32) -> i32 { a + b }}
fn main() { let sum = math::add(2, 3); println!("{sum}");}Output:
5Two things to notice: the function is called with math::add(...), using the module name as a path. And it’s marked pub — without that, it wouldn’t be reachable from outside the module.
Everything is private by default
Section titled “Everything is private by default”This is worth calling out because it surprises people: unlike most things in Rust, module contents are private by default. If you remove pub from the example above, it won’t compile:
mod math { fn add(a: i32, b: i32) -> i32 { // no `pub` a + b }}
fn main() { let sum = math::add(2, 3); // ❌ error: function `add` is private println!("{sum}");}You have to explicitly mark anything you want callers outside the module to use with pub. This is intentional — it lets a module hide its internal helper functions and only expose the parts meant to be a public API.
Nested modules
Section titled “Nested modules”Modules can contain other modules, which is how larger projects build up a tree-like structure:
mod shapes { pub mod circle { pub fn area(radius: f64) -> f64 { 3.14159 * radius * radius } }}
fn main() { let area = shapes::circle::area(2.0); println!("{area}");}use — shortening long paths
Section titled “use — shortening long paths”Writing shapes::circle::area(...) every time gets tedious. use brings a path into scope so you can refer to it directly:
mod shapes { pub mod circle { pub fn area(radius: f64) -> f64 { 3.14159 * radius * radius } }}
use shapes::circle;
fn main() { let area = circle::area(2.0); // shorter than shapes::circle::area println!("{area}");}You’ve actually already used use — it’s the same keyword from the HashMap page (use std::collections::HashMap;).
Splitting modules across files
Section titled “Splitting modules across files”The examples above put everything in one file, which the Rust Playground requires. In a real project on your own machine, each module usually gets its own file. If you had a project with a math module, it would typically look like this:
src/├── main.rs└── math.rsmod math; // tells Rust: look for this module's code in math.rs
fn main() { let sum = math::add(2, 3); println!("{sum}");}pub fn add(a: i32, b: i32) -> i32 { a + b}mod math; (with a semicolon, no body) tells Rust to load the module’s contents from math.rs in the same directory. This is the pattern you’ll use as soon as a project grows beyond a single file.
mod name { ... }groups related code into a named module.- Everything inside a module is private by default — add
pubto expose it outside the module. usebrings a path into scope so you don’t have to write it out in full every time.- In a multi-file project,
mod name;(no body) loads that module’s code from a matching file.