Rust Modules: Your Code's File System
Think of Rust modules as a file system for your code, grouping logic and hiding details. You declare them with `mod`, and Rust finds the code in corresponding files. The footgun: items are private by default, so you must use `pub` to expose them.
WHY IT EXISTS: Modules exist to manage complexity in growing codebases. Without them, all your code would live in a single, flat namespace. This would lead to name collisions, poor readability, and no way to enforce boundaries between different parts of your application's logic.
THE MENTAL MODEL: Think of Rust's module system as a file system for your code, with the crate root being the top-level directory. A module is a folder that groups related items like functions, structs, and even other modules (sub-folders). Paths, like crate::garden::vegetables::Asparagus, are the file paths you use to navigate this structure and access items within it.
HOW IT WORKS: The compiler starts at your crate root (src/main.rs for a binary or src/lib.rs for a library). When it encounters a module declaration like mod garden;, it looks for the module's code in one of two places: the file src/garden.rs or the file src/garden/mod.rs. This file-based mapping is the core convention. Submodules follow the same pattern within their parent's directory. For example, mod vegetables; inside src/garden.rs points to src/garden/vegetables.rs. By default, everything inside a module is private and only accessible within that module and its children. To make an item visible outside, you must mark it with the pub keyword. To bring an item into the current scope for easier use, you can use the use keyword, which creates a shortcut to its full path.
WHEN TO USE IT: You use modules in every Rust project that grows beyond a single file. They are the fundamental tool for separating concerns. For instance, a web service might have modules for database, api_handlers, and authentication. This organization makes the code easier to navigate, test, and maintain by keeping related logic together and separate from unrelated logic.
WHEN NOT TO USE IT: The question is not if you should use modules, but how to use them effectively. A common anti-pattern is making everything public with pub, which defeats the purpose of encapsulation. Privacy is a feature, not a hindrance; use it to hide internal implementation details. This prevents other parts of your code from depending on things that might change, creating a more robust and maintainable system. Avoid creating overly deep module hierarchies for simple projects.
ONE CANONICAL EXAMPLE: Imagine a src/main.rs file with the line pub mod garden;. This tells the compiler to include and make public the module defined in src/garden.rs. Inside src/garden.rs, you have pub mod vegetables;, which points to src/garden/vegetables.rs. Finally, src/garden/vegetables.rs contains pub struct Asparagus {}. To use this struct in main.rs, you would write use crate::garden::vegetables::Asparagus;. Every pub keyword here is essential; without them, the modules and the struct would be private and inaccessible from main.rs.
Read the original → doc.rust-lang.org
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.