Can you write this from memory?
Declare a module named `utils`.
Rust's module system organizes code into namespaces with explicit visibility. The mod keyword declares modules, use brings items into scope, and pub controls what's accessible outside.
The rules seem simple until you're actually structuring a project: Does mod foo; look for foo.rs or foo/mod.rs? What's the difference between use crate:: and use super::? When do you need pub use for re-exports?
This page focuses on module syntax and patterns until declaring modules, importing items, controlling visibility, and organizing crates are automatic.
People confuse these constantly. Here is the hierarchy:
| Term | What it is | Contains |
|---|---|---|
| Package | Has a Cargo.toml | Up to 1 library crate + multiple binary crates |
| Crate | Compilation unit | A module tree rooted at lib.rs or main.rs |
| Module | Namespace inside a crate | Items (functions, structs, traits, submodules) |
| Workspace | Has a root Cargo.toml with [workspace] | Multiple packages developed together |
A package is what you cargo new. A crate is what the compiler builds. A module is how you organize code inside a crate.
The most common module mistake is trying to use a module you never declared:
// WRONG: using without declaring
// use crate::utils::helper; // error[E0432]: unresolved import
// RIGHT: declare the module first
mod utils; // tells Rust to look for src/utils.rs
use crate::utils::helper;
Without mod utils;, the compiler has no idea utils exists. The mod declaration is what makes Rust load the file.
Making the module pub does not make its contents public. Visibility is per-item:
// In lib.rs
pub mod utils; // module is public
// In utils.rs
fn helper() { } // WRONG: function is private — error[E0603]
pub fn helper() { } // RIGHT: function is also public
A public module can contain entirely private items. You must mark each item that should be accessible. Struct field visibility follows the same rules -- see structs and enums for the pub field pattern.
Rust cannot find the file matching your mod declaration:
// src/lib.rs
mod utils; // error[E0583] if neither src/utils.rs nor src/utils/mod.rs exists
Check: file name must exactly match the module name, and it must be in the right directory relative to the parent module's location.
When you write mod utils;, Rust looks for:
src/utils.rs(modern style, preferred)src/utils/mod.rs(older style, still works)
If utils has submodules, use the directory approach:
// src/lib.rs
mod network;
// src/network.rs (or src/network/mod.rs)
pub mod client;
pub mod server;
// src/network/client.rs
pub fn connect() { }
The modern style is network.rs with a network/ directory for submodules. Since Rust 2018, foo.rs and a foo/ directory can coexist, so mod.rs is no longer required.
If your package has both src/main.rs and src/lib.rs, Cargo builds two separate crates — a binary and a library — each with its own module tree:
// src/lib.rs
pub mod config; // only visible to the library crate's tree
// src/main.rs
// WRONG: main.rs can't see lib.rs modules directly
// use config::Settings; // error[E0432]
// RIGHT: main.rs must use the library crate by its package name
use my_package::config::Settings;
This is why "I declared it in lib.rs but main.rs can't see it" happens. The binary crate depends on the library crate like any external dependency.
| Prefix | Starts from | Analogy |
|---|---|---|
crate:: | Crate root (lib.rs or main.rs) | Absolute path / |
super:: | Parent module | Relative ../ |
self:: | Current module | Relative ./ |
// From src/network/client.rs
use crate::config::Settings; // absolute: starts at crate root
use super::server::listen; // relative: goes up to network, then into server
use self::helpers::parse_url; // explicit current module (rarely needed)
Since Rust 2018, extern crate is no longer needed in most cases — the compiler resolves crate names automatically from Cargo.toml dependencies. The Facade design pattern applies naturally here: re-export a simplified API from your crate root while hiding complex internal module structure.
| Visibility | Accessible from | Use for |
|---|---|---|
pub | Anywhere (including dependents) | Public API |
pub(crate) | Anywhere in the crate | Internal shared utilities |
pub(super) | Parent module only | Helpers for parent |
pub(in crate::some::path) | Specified ancestor module and its children | Scoped internal API |
| (none) | Current module only | Implementation details |
pub fn public_api() { } // visible to everyone
pub(crate) fn internal_only() { } // crate-wide, hidden from dependents
pub(super) fn parent_only() { } // parent module only
pub(in crate::network) fn network_only() { } // visible within crate::network subtree
fn private_helper() { } // current module only
The Privacy Rule Beginners Miss
Items are private by default. Child modules can access private items of their ancestor modules, but parents cannot access private items of children. The testing guide shows how #[cfg(test)] mod tests uses this rule to test private functions from a child module:
mod parent {
fn secret() { }
mod child {
fn peek() {
super::secret(); // OK: child can see parent's private items
}
}
fn try_peek() {
// child::peek(); // ERROR: parent can't see child's private items
}
}
Keep internal modules private and re-export the public API from lib.rs:
// src/lib.rs — clean public API
mod internal;
mod config;
pub use internal::Config; // users write my_crate::Config
pub use config::Settings; // users write my_crate::Settings
The Prelude Pattern
For crates with many public types, create a prelude module:
// src/prelude.rs
pub use crate::Config;
pub use crate::Error;
pub use crate::Result;
// Users can do:
// use my_crate::prelude::*;
- The Rust Book: Modules — packages, crates, modules, paths
- Rust By Example: Modules — practical module examples
- Rust Reference: Visibility — pub, pub(crate), pub(in path) rules
- Rust Reference: Items and Modules — module file lookup, inline modules
When to Use Rust Modules & Crates: mod, use, pub, Crate Structure
- Use `mod` to declare modules and organize code.
- Use `use` to bring items into scope without full paths.
- Use `pub` to expose items outside their module.
- Use `pub(crate)` for crate-internal APIs.
- Use `pub use` to re-export items at a different path.
Check Your Understanding: Rust Modules & Crates: mod, use, pub, Crate Structure
Explain the difference between mod and use in Rust.
`mod` declares/defines a module (creates a namespace). `use` brings items into scope (creates shortcuts). You need `mod` first to make the module exist, then `use` to conveniently access its items.
What You'll Practice: Rust Modules & Crates: mod, use, pub, Crate Structure
Common Rust Modules & Crates: mod, use, pub, Crate Structure Pitfalls
- You see `error[E0432]: unresolved import` -- you wrote `use crate::utils::helper` but never declared the module. Add `mod utils;` in your `lib.rs` or `main.rs` before the `use` statement.
- You see `error[E0603]: function is private` -- you made the module `pub` but not the item inside it. Add `pub` to the function or struct definition, not just to the `mod` declaration.
- You see `error[E0583]: file not found for module` -- Rust expects `src/utils.rs` or `src/utils/mod.rs` and cannot find either. Check spelling and file location.
- You write `mod foo;` and `use foo;` and get confused about which does what -- `mod` declares a module (loads the file), `use` brings items into scope (creates shortcuts). For modules in your crate source tree, declare with `mod` before importing items from them.
- You declared a module in `lib.rs` but `main.rs` cannot see it -- if your package has both `main.rs` and `lib.rs`, they are separate crates. From `main.rs`, import via the package name: `use my_package::my_module::Thing;`.
- You get a Cargo error about cyclic dependencies -- Cargo does not support cyclic crate dependencies. If two crates need each other, extract shared traits or types into a third crate. Cross-references between modules inside the same crate are fine.
Rust Modules & Crates: mod, use, pub, Crate Structure FAQ
Where does mod foo; look for the file?
Either `foo.rs` in the same directory, or `foo/mod.rs`. Modern Rust prefers `foo.rs` with `foo/` directory for submodules. The `foo/mod.rs` style is older but still works.
What is the difference between crate::, super::, and self::?
`crate::` starts from the crate root. `super::` goes up one module level (like `..` in paths). `self::` refers to the current module (rarely needed but useful in some use statements).
What is pub use for?
Re-exporting: making something available at a different path. `pub use internal::Thing;` lets users write `crate::Thing` instead of `crate::internal::Thing`. Great for flattening APIs.
What is pub(crate)?
Visible within the crate but not to external users. More restrictive than `pub` but more permissive than private. Good for internal APIs that multiple modules need.
What is the prelude?
Items automatically imported into every Rust program: Option, Result, common traits, etc. Defined in `std::prelude`. You can create your own prelude module with `pub use` re-exports for crate-wide imports.
Why can't main.rs see modules declared in lib.rs?
If your package has both main.rs and lib.rs, they are separate crates with separate module trees. From main.rs, import via the package name: `use my_package::module::Item;`.
What is pub(in path)?
`pub(in crate::some::module)` restricts visibility to that module and its children. More precise than `pub(crate)` but less common. Useful for scoping internal APIs within a specific subtree.
Rust Modules & Crates: mod, use, pub, Crate Structure Syntax Quick Reference
mod utils;
mod models;
mod handlers;mod helpers {
pub fn do_thing() {
println!("did thing");
}
}use std::collections::HashMap;use std::{io, fs, path::Path};use std::io::prelude::*;use crate::models::User;use super::utils::helper;pub use internal::Config;pub(crate) fn internal_helper() -> i32 {
42
}pub(in crate::network) fn scoped_helper() { }use std::io::Result as IoResult;// src/lib.rs
mod network;
// src/network.rs
pub mod client;
pub mod server;
// src/network/client.rs
pub fn connect() -> &'static str {
"connected"
}Rust Modules & Crates: mod, use, pub, Crate Structure Sample Exercises
Fill in the keyword to bring HashMap into scope.
useFill in the keyword to make the function public.
pubFill in the keyword for the crate root in a path.
crate+ 41 more exercises