Modules and Visibility
Absolute and Relative Paths
To call a function, construct a type, or import an item located in a module, you specify its path in the module tree using either an absolute path (starting from the crate root or an external crate name) or a relative path (starting from the current module).
Comparing Absolute and Relative Paths
| Path Kind | Starting Segment | Example | Best Used When |
|---|---|---|---|
| Absolute (current crate) | crate:: |
crate::billing::invoice::create() |
Referencing items in other subsystems of your crate; remains valid if the calling code is moved to a different module |
| Absolute (external crate) | std:: or ::crate_name:: |
std::collections::HashMap |
Referencing items from the standard library or Cargo dependencies |
| Relative (child module) | child_mod:: or self::child_mod:: |
invoice::create() |
Referencing a direct child module or an item already in scope |
| Relative (parent module) | super:: |
super::shared_helper() |
Referencing an item in the immediate parent module (especially in mod tests) |
Reaching `crate::audio::mixer::set_gain` from `crate::audio::effects::reverb`:
crate
└── mod audio
├── mod mixer
│ └── pub fn set_gain()
└── mod effects
└── mod reverb
├── Absolute path: `crate::audio::mixer::set_gain()`
└── Relative path: `super::super::mixer::set_gain()`
Absolute and Relative Paths in Action
mod audio {
pub mod mixer {
pub fn master_volume() -> u8 {
85
}
}
pub mod output {
pub fn status_line() -> String {
// 1. Absolute path from the crate root (`crate::...`):
let vol_abs = crate::audio::mixer::master_volume();
// 2. Relative path via parent module (`super::...`):
let vol_rel = super::mixer::master_volume();
assert_eq!(vol_abs, vol_rel);
format!("Audio output active at volume {vol_abs}%")
}
}
}
fn main() {
// Relative path from `main` (which is at the crate root) into child `audio`:
println!("{}", audio::output::status_line());
// Absolute path from `main` into `crate::audio`:
println!("Master volume: {}%", crate::audio::mixer::master_volume());
}
Audio output active at volume 85%
Master volume: 85%
Choosing Between crate:: and Relative Paths
- Prefer
crate::when crossing subsystem boundaries: Ifcrate::api::handlerscalls intocrate::db::users, writinguse crate::db::users;makes it immediately clear whereuserslives in the project and continues to work ifhandlersis later split intohandlers::v1. - Prefer relative paths (
child::...orsuper::...) for tightly coupled parent/child modules: When a parent module delegates to its own child module (child::run()) or a unit test submodule imports its parent (use super::*;), relative paths keep the parent and child portable as a unit if the entire folder is moved.
Disambiguating External Crate Names with a Leading ::
If your current module contains a child module with the same name as an external dependency crate (for example, mod serde;), prefixing the external crate name with a leading double colon (::serde::Serialize) forces the compiler to resolve serde as the external crate rather than the local serde module.