Rust Chapter7 Modules - HTML
Rust Chapter7 Modules - HTML
FOUNDATIONS
Using
Modules to
01 The Big Picture
02 mod keyword
03
04
Modules to Files
Submodule Rule
Reuse
VISIBILITY
and Organize
Code
05 pub keyword
06 Privacy Rules
07 Privacy Examples Learn how Rust's module system lets you split code into namespaced units,
PATHS & SCOPE control what's public or private, and bring names into scope cleanly. Three
08 use keyword keywords rule them all.
11 Full Walkthrough
12 Practice Problems
01 — BIG PICTURE
13 Cheatsheet
Why Do We Need Modules?
As programs grow, putting everything in [Link] becomes unmanageable. You need a way to group
related code, hide implementation details, and expose a clean API. That's exactly what modules do.
📦 REAL-WORLD ANALOGY
Think of a large company. You don't expose every internal process to every employee — HR
handles hiring, Engineering handles code, Finance handles money. Each department has a
public interface (what they'll do for you) and private internals (how they do it). Modules work
the same way in Rust.
Namespacing — two modules can each have a function named connect() without conflict
Privacy — hide implementation details; only expose what users need
Organization — split code across files as the project scales
02 — MOD KEYWORD
To call connect from outside the network module, you use :: path syntax:
08 use keyword
10 super keyword
network::connect(); // must use full path from outside the module
MASTERY
11 Full Walkthrough
13 Cheatsheet You can have as many sibling modules as you need. They each form their own namespace so function
names don't clash:
mod network {
fn connect() {} // ← network::connect()
}
mod client {
fn connect() {} // ← client::connect() — totally different!
}
✅ KEY POINT
The same function name in different modules causes zero conflict. Each module is its own
namespace. This is exactly why namespacing matters.
Nested Modules
You can put modules inside modules. The path just gets longer:
mod network {
fn connect() {} // path: network::connect()
mod server {
fn connect() {} // path: network::server::connect()
}
mod client {
fn connect() {} // path: network::client::connect()
CHAPTER 7 }
Modules & Code }
Organization
07 Privacy Examples
PATHS & SCOPE
12 Practice Problems
🧠 THE KEY MENTAL MODEL
mod client;(with semicolon) means: "There IS a module named client, but its contents are in
13 Cheatsheet
another file — go find src/[Link] ."
mod client { ... } (with body) means: "Here is the module, right here, inline."
// src/[Link] // src/[Link]
mod client { mod client; // ← semicolon! body in [Link]
fn connect() {} mod network; // ← semicolon! body in [Link]
fn disconnect() {}
// 500 more lines...
}
mod network {
// 800 more lines...
}
SRC/[Link]
CHAPTER 7 // DO NOT write "mod client" here!
FOUNDATIONS
3 Run cargo build — it should compile
01 The Big Picture Rust automatically finds src/[Link] when it sees mod client; in src/[Link] .
02 mod keyword
Modules to Files
03
🚨 THE #1 MISTAKE — DON'T DO THIS
04 Submodule Rule
SRC/[Link] — WRONG!
VISIBILITY
10 super keyword
MASTERY
04 — THE SUBMODULE DIRECTORY RULE
11 Full Walkthrough
When a Module Has Submodules: Use a
12 Practice Problems
Directory
13 Cheatsheet
Here's where most beginners get confused. When you want to split a module that itself has child
modules, you can't just use a .rs file — you need a directory with a [Link] inside it.
⚠️ THE PROBLEM
If network is in src/[Link] and you write mod server; inside it, Rust will error: "cannot
declare a new module at this location." Rust can't tell that src/[Link] belongs to network
— it looks like a top-level module!
TERMINAL
mkdir src/network
04 Submodule Rule
VISIBILITY
4 In src/network/[Link] — declare the submodule
05 pub keyword
SRC/NETWORK/[Link]
06 Privacy Rules
10 super keyword
The Complete File Layout
MASTERY
11 Full Walkthrough
FILE TREE ↔ MODULE TREE
12 Practice Problems
13 Cheatsheet
📁 FILE TREE 🌳 MODULE TREE
src/ communicator
├── [Link] ├── client
├── [Link] └── network
└── network/ └── server
├── [Link]
└── [Link]
The module hierarchy stays IDENTICAL. Only the file layout changes.
Rust needs to know which module is the parent of a file. When [Link] is inside the
network/ directory, Rust knows it belongs to network . If it were at src/[Link] , Rust would
think it's a sibling of network , not a child. The directory structure encodes the parent-child
relationship.
05 — PUB KEYWORD
🔒 PRIVACY ANALOGY
Imagine a house. The front door (public API) is accessible to guests. The bedrooms and
CHAPTER 7 basement (private internals) are not. You explicitly choose what's guest-accessible. Rust does
Modules & Code the same — everything starts locked; you unlock only what you need.
Organization
FOUNDATIONS
The Cascading pub Problem
01 The Big Picture
This is the most common mistake: you make a function pub but forget to make its parent module pub .
02 mod keyword
Both must be public for outside code to reach the function.
03 Modules to Files
VISIBILITY
SRC/[Link]
05 pub keyword
SRC/[Link]
11 Full Walkthrough
SRC/[Link]
↓
STEP 3 — BOTH MODULE AND FUNCTION ARE PUBLIC ✅
SRC/[Link]
SRC/[Link]
FOUNDATIONS
06 — PRIVACY RULES
05 pub keyword
Rule 1 — Public item:
06 Privacy Rules
Can be accessed through any of its parent modules.
07 Privacy Examples
Rule 2 — Private item:
PATHS & SCOPE
Can ONLY be accessed by its own module and any of that module's child modules.
08 use keyword
Parents can see public children. Parents CANNOT see private children's internals.
09 Glob & Multi-use Children can always see their parents.
10 super keyword
MASTERY
13 Cheatsheet
Same module ✅ YES ✅ YES
Child module (nested inside) ✅ YES ✅ YES
Parent module ❌ NO ✅ YES
Sibling module ❌ NO ✅ YES (via parent)
External crate ❌ NO ✅ YES (via pub chain)
07 — PRIVACY IN PRACTICE
mod outermost {
pub fn middle_function() {} // pub
fn middle_secret_function() {} // private
fn try_me() {
outermost::middle_function(); // ?
outermost::middle_secret_function(); // ?
outermost::inside::inner_function(); // ?
outermost::inside::secret_function(); // ?
CHAPTER 7 }
Modules & Code
Organization
Before reading the answers — which lines compile? Think through each one using the two rules.
FOUNDATIONS
Line-by-Line Analysis
01 The Big Picture
02 mod keyword
05 pub keyword
Why? try_me is in the root module. outermost is private, but Rule 2 says: a private item can
06 Privacy Rules be accessed by its parent module. The root module IS the parent of outermost . And
07 Privacy Examples
middle_function is pub . Both checks pass. ✅
PATHS & SCOPE
08 use keyword
11 Full Walkthrough
Practice Problems Why? middle_secret_function is private. The root module is not its own module, nor a child of
❌
12
❌ ERROR
outermost::inside::inner_function();
Why? Even though inner_function is pub , the inside module itself is private. You can't
reach through a private module to get to a public item inside it. The inside module is only
accessible by outermost and outermost 's children — not by the root. ❌
❌ ERROR
outermost::inside::secret_function();
To make outermost::inside::inner_function() work from the root, you'd need to make both
outermost and inside public: pub mod outermost { pub mod inside { pub fn
inner_function() {} } } . Every link in the chain must be public.
CHAPTER 7
02 mod keyword
03 Modules to Files
❌ Without use — verbose ✅ With use — clean
04 Submodule Rule
fn main() { use a::series::of;
VISIBILITY
a::series::of::nested_modules();
05 pub keyword a::series::of::nested_modules(); fn main() {
a::series::of::nested_modules(); of::nested_modules();
06 Privacy Rules } of::nested_modules();
07 Privacy Examples of::nested_modules();
}
PATHS & SCOPE
08 use keyword
For functions, the convention is to use the parent module, not the function itself. This makes it
clear the function isn't local: you write module::function() . For types (structs, enums), it's
idiomatic to bring them in directly: use std::collections::HashMap then use HashMap bare.
use only applies to the scope it's in. If you write use at the top level of a file, it's available throughout
that file. If you write it inside a function, it's only available in that function.
fn foo() {
of::nested_modules(); // ✅ works
}
fn bar() {
of::nested_modules(); // ✅ also works
CHAPTER 7 }
Modules & Code
Organization
02 mod keyword
Bringing Multiple Items from One Namespace
03 Modules to Files
Use curly braces to import multiple items from the same path in one use statement:
04 Submodule Rule
VISIBILITY RUST — MULTIPLE USE
05 pub keyword
enum TrafficLight { Red, Yellow, Green }
06 Privacy Rules
// Import two variants explicitly
07 Privacy Examples
use TrafficLight::{Red, Yellow};
PATHS & SCOPE
11 Full Walkthrough
13 Cheatsheet The glob operator imports everything visible from a namespace at once:
RUST — GLOB
fn main() {
let r = Red; // ✅
let y = Yellow; // ✅
let g = Green; // ✅ all imported
}
Glob imports are convenient but dangerous. They can pull in names you didn't expect, causing
naming conflicts that are hard to debug. You also lose visibility into where a name came from.
Use explicit imports in production code. Globs are acceptable in tests and preludes.
In real Rust code, you'll use use constantly for standard library types:
use std::collections::HashMap;
use std::collections::HashSet;
use std::collections::{HashMap, HashSet}; // both at once
use std::io::Result;
use std::fmt;
CHAPTER 7
02 mod keyword
PATH NAVIGATION
03 Modules to Files
08 use keyword
10 super keyword
THIS FAILS — PATHS ARE RELATIVE TO CURRENT MODULE
MASTERY
::client::connect(); super::client::connect();
// Start from crate root, go down // Go up one level, then navigate
The idiomatic pattern is to combine super with use so you don't have to write super:: in front of
every single call:
#[cfg(test)]
mod tests {
use super::client; // bring client into scope once
#[test]
fn test_connect() {
client::connect(); // ✅ clean, no super:: every time
}
#[test]
CHAPTER 7 fn test_disconnect() {
Modules & Code client::disconnect(); // ✅ same import works for all tests
Organization }
}
FOUNDATIONS
02 mod keyword
If you use absolute paths like ::client::connect() everywhere and then refactor your module
tree — moving modules around — you'd need to update every absolute path. With super:: , as
03 Modules to Files long as the relative relationship stays the same, paths continue to work. Less brittle.
04 Submodule Rule
VISIBILITY
05 pub keyword
11 — COMPLETE WALKTHROUGH
06 Privacy Rules
Building the Communicator Library End-to-End
07 Privacy Examples
PATHS & SCOPE Let's put every concept together and build the complete communicator library from the book, step by
08 use keyword step, with every file shown.
11 Full Walkthrough
communicator
12 Practice Problems
├── client (public)
13 Cheatsheet └── network (public)
└── server (public)
File Layout
src/
├── [Link] ← crate root, declares modules
├── [Link] ← client module body
├── [Link] ← binary crate (uses the library)
└── network/
├── [Link] ← network module body, declares server submodule
└── [Link] ← network::server module body
#[cfg(test)]
mod tests {
use super::client;
#[test]
fn it_works() {
client::connect();
}
}
SRC/[Link] — CLIENT MODULE
CHAPTER 7
FOUNDATIONS
02 mod keyword
pub fn connect() {
03 Modules to Files println!("network connected");
}
04 Submodule Rule
VISIBILITY pub mod server; // body in src/network/[Link]
05 pub keyword
07 Privacy Examples
pub fn connect() {
PATHS & SCOPE println!("server connected");
}
08 use keyword
Running It
TERMINAL
In Rust 2015 (this book's edition), you need extern crate mylib; in [Link] to use an external
crate. In Rust 2018+ (what you'll likely use), this line is no longer needed — Cargo handles it
automatically. Everything else in this chapter applies to both editions.
02 mod keyword
PROBLEM 02 — pub & Privacy
03 Modules to Files
Controlling What's Visible
04 Submodule Rule
Create a module bank with a private function validate_pin(pin: u32) -> bool and a
VISIBILITY
public function withdraw(amount: f64, pin: u32) -> Result<f64, &'static str> . The
05 pub keyword public function calls the private one. In main() , call bank::withdraw(100.0, 1234) .
06 Privacy Rules Then try to call bank::validate_pin(1234) and observe the compile error.
07 Privacy Examples 💡 Hint: Private functions are accessible within the same module. Return Ok(amount) if pin is
PATHS & SCOPE
valid, Err("wrong pin") otherwise.
08 use keyword 🏆 Bonus: Make the module's public API only include withdraw and deposit . All validation logic stays
private.
09 Glob & Multi-use
10 super keyword
MASTERY PROBLEM 03 — Nested Modules
12 Practice Problems Define a module with two submodules: two_d and three_d . In two_d , add
shapes
pub fn circle_area(r: f64) -> f64 . In three_d , add pub fn sphere_volume(r: f64)
13 Cheatsheet
-> f64 . Make both submodules public. Call both functions from main() using full
paths: shapes::two_d::circle_area(3.0) and shapes::three_d::sphere_volume(3.0) .
💡 Hint: Circle area = π × r². Sphere volume = (4/3) × π × r³. Use std::f64::consts::PI.
Cleaning Up Paths
Take the code from Problem 03. Add use shapes::two_d and use shapes::three_d at
the top of main() . Rewrite the calls to use the shortened paths. Then add a third
function call using use shapes::two_d::circle_area so you can call it bare:
circle_area(5.0) .
💡 Hint: use only brings exactly what you specify into scope. Children of the module are not
automatically included.
Create a library project with cargo new mylib --lib . Split it into two files:
src/[Link] and src/[Link] . In [Link] , add pub fn hello(name: &str) ->
String . In [Link] , add pub fn goodbye(name: &str) -> String . In src/[Link] ,
declare both modules with mod greet; and mod farewell; and make them public.
Write a test in [Link] that calls both functions using use super::greet and use
super::farewell .
💡 Hint: Tests live in a mod tests block inside [Link]. Use use super::greet; to bring the
module into test scope. Run with cargo test.
CHAPTER 7 PROBLEM 06 — File Modules (With Submodules)
FOUNDATIONS src/greet/[Link] with a pub fn formal_hello(name: &str) -> String that returns
"Good day, [name], I presume?" In src/greet/[Link] , declare pub mod formal; . In
01 The Big Picture
your test, call greet::formal::formal_hello("Alice") .
mod keyword
💡 Hint: When greet gets a submodule, src/[Link]
02
→ src/greet/[Link]. The mkdir command:
03 Modules to Files mkdir src/greet && mv src/[Link] src/greet/[Link].
04 Submodule Rule 🏆 Bonus: Add another submodule greet::casual with a different style of greeting. The directory should
VISIBILITY have three files: [Link], [Link], [Link].
05 pub keyword
06 Privacy Rules
PROBLEM 07 — Privacy Deep Dive
07 Privacy Examples
Reason About Visibility
PATHS & SCOPE
Without running it, predict which lines compile in this code. Then run it and check your
08 use keyword answers:
09 Glob & Multi-use
12 Practice Problems
mod deep {
13 Cheatsheet pub fn deep_visible() {}
}
}
fn secret() {}
}
fn main() {
outer::inner::visible(); // Line A
outer::inner::hidden(); // Line B
outer::secret(); // Line C
outer::inner::deep::deep_visible(); // Line D
}
💡 Which lines compile? Apply the two rules: public items are accessible from any parent.
Private items are only accessible from the same module and its children. Note that deep is a
private module.
🏆 Bonus: Make all lines compile by adding/removing the minimum number of pub keywords.
Build a small "todo" library with this structure: src/[Link] (declares modules),
src/todo/[Link] (the Todo struct and add/complete functions), src/todo/[Link]
(a pub fn print_all function). Create src/[Link] that imports the library, adds
three todos, completes one, and prints them all. The Todo struct should have a title:
String and done: bool field, both public.
CHAPTER 7
💡 Hint: Start with cargo new todos (binary). The library is src/[Link]. [Link] uses use
todos::todo::Todo (or however you name your crate). Run with cargo run.
Modules & Code
Organization
FOUNDATIONS
02
03
mod keyword
Modules to Files
📋 Chapter 7 Complete Cheatsheet
04 Submodule Rule
DECLARE MODULE (INLINE) DECLARE MODULE (FILE)
VISIBILITY
08 use keyword
MAKE THINGS PUBLIC CALL WITH FULL PATH
09 Glob & Multi-use
12 Practice Problems }
13 Cheatsheet
FOUNDATIONS
pub fn bar() {} // ✅ function is public
// Only then can outsiders call foo::bar()
01 The Big Picture
02 mod keyword
03 Modules to Files
04 Submodule Rule ✅ You've mastered Chapter 7. The module system is the foundation for all larger Rust projects.
VISIBILITY Next: Chapter 8 — Common Collections (Vec, String, HashMap) — data structures that grow at
runtime.
05 pub keyword
06 Privacy Rules
07 Privacy Examples
PATHS & SCOPE
08 use keyword
10 super keyword
MASTERY
11 Full Walkthrough
12 Practice Problems
13 Cheatsheet