In Rust, code is organized into modules, which form a tree-like structure. To access items (functions, structs, enums, etc.) defined in other modules, you need to specify their 'paths'. Paths can be either absolute or relative.
Absolute Paths
An absolute path starts from the crate root. The crate root is the top-level module of your current crate. You can refer to items using:
* `crate::`: For items defined within the current binary or library crate.
* `std::` or `rand::` (or any other external crate name): For items defined in an external crate that you've listed as a dependency.
Syntax: `crate::module_name::sub_module::item_name` or `external_crate_name::module_name::item_name`.
Absolute paths are generally preferred for clarity, as they clearly indicate the item's location from the root of the crate.
Relative Paths
A relative path starts from the current module and uses `self` or `super` keywords to navigate the module tree.
* `self::`: Refers to items within the current module or its submodules.
* `super::`: Refers to items in the parent module of the current module. You can chain `super::` multiple times (e.g., `super::super::`) to go up multiple levels.
Syntax: `self::sub_module::item_name` or `super::sibling_module::item_name`.
Relative paths can be useful when moving code around within a module or when referring to items that are closely related in the module tree.
The `use` Keyword
The `use` keyword allows you to bring a path into scope, making it so you don't have to write the full path every time you want to use an item. Once an item is brought into scope with `use`, you can refer to it directly by its name.
Syntax: `use path::to::item;`
Best Practices for `use`:
* Functions, Structs, and other Items: It's idiomatic to bring the parent module of the item into scope rather than the item itself for functions, structs, and other types, e.g., `use crate::front_of_house::hosting;` then `hosting::add_to_waitlist();`. This helps avoid name collisions and clarifies the item's origin.
* Enums: For enums, it's common to bring the enum itself into scope, e.g., `use crate::back_of_house::Appetizer;` then `Appetizer::Soup`.
* Glob Operator (`*`): `use path::to::*;` brings all public items defined in `path::to` into scope. Use sparingly, as it can lead to name collisions and make code harder to read.
* Nested Paths: You can use nested paths to bring multiple items from the same parent into scope in one line, e.g., `use std::{cmp::Ordering, io};`.
* `as` Keyword: You can rename items when bringing them into scope to avoid name collisions or to provide a more convenient name, e.g., `use std::fmt::Result as FmtResult;`.
Re-exporting with `pub use`
The `pub use` combination is used to re-export an item. This means that when an external code uses your crate, it can access the re-exported item not only at its original path but also at the path where it was re-exported. This is useful for creating a more convenient public API for your crate, especially if internal structure is complex but you want to expose a simpler interface.
Example Code
```rust
// main.rs (crate root)
mod front_of_house { // Module 'front_of_house' defined at crate root
pub mod hosting { // Public submodule 'hosting'
pub fn add_to_waitlist() { // Public function
println!("\tAdding to waitlist in front_of_house::hosting");
}
fn seat_at_table() {
println!("\tSeating at table in front_of_house::hosting");
}
}
mod serving { // Private submodule 'serving'
fn take_order() {
println!("\tTaking order in front_of_house::serving");
super::hosting::seat_at_table(); // Relative path to parent module's item
}
fn serve_order() {
println!("\tServing order in front_of_house::serving");
}
fn take_payment() {
println!("\tTaking payment in front_of_house::serving");
}
}
// Re-export 'add_to_waitlist' so it can be accessed directly via `crate::add_to_waitlist`
pub use self::hosting::add_to_waitlist;
}
mod back_of_house { // Module 'back_of_house' defined at crate root
pub fn cook_order() {
println!("\tCooking order in back_of_house");
}
pub struct Breakfast {
pub toast: String,
seasonal_fruit: String,
}
impl Breakfast {
pub fn summer(toast: &str) -> Breakfast {
Breakfast {
toast: String::from(toast),
seasonal_fruit: String::from("peaches"),
}
}
}
pub enum Appetizer {
Soup,
Salad,
}
mod chef_station { // Private submodule
pub fn prepare_ingredients() {
println!("\t\tPreparing ingredients in back_of_house::chef_station");
// Using a relative path to an item in the parent module
super::cook_order();
}
}
pub use chef_station::prepare_ingredients; // Re-export 'prepare_ingredients'
}
// --- Start of `main` function (entry point) ---
fn main() {
println!("--- Demonstrating Paths ---");
// --- Absolute Paths ---
println!("\n--- Using Absolute Paths ---");
crate::front_of_house::hosting::add_to_waitlist();
crate::back_of_house::cook_order();
// --- Using `use` statements ---
println!("\n--- Using `use` statements ---");
// Idiomatic: Bring parent module into scope for functions/structs
use crate::front_of_house::hosting;
hosting::add_to_waitlist();
// Idiomatic: Bring enum directly into scope
use crate::back_of_house::Appetizer;
let order1 = Appetizer::Soup;
let order2 = Appetizer::Salad;
println!("\tOrdered: {:?} and {:?}", order1, order2);
// Using `use` with `as` to rename
use crate::front_of_house::hosting::add_to_waitlist as add_to_waitlist_alias;
add_to_waitlist_alias();
// Using `use` with nested paths
use crate::back_of_house::{Breakfast, cook_order};
let mut meal = Breakfast::summer("Rye");
meal.toast = String::from("Wheat");
println!("\tI'd like {} toast please, with {:?}", meal.toast, meal.seasonal_fruit); // seasonal_fruit is private
cook_order();
// Using glob operator (use sparingly)
use crate::back_of_house::chef_station::*;
prepare_ingredients(); // No need for full path here due to glob `*`
// --- Relative Paths from a function inside main.rs ---
println!("\n--- Using Relative Paths (from main::eat_at_restaurant) ---");
eat_at_restaurant();
// --- Re-exported items ---
println!("\n--- Using Re-exported Items ---");
// `front_of_house::add_to_waitlist` was re-exported as `crate::add_to_waitlist`
crate::front_of_house::add_to_waitlist(); // Access through original path
crate::add_to_waitlist(); // Access through new, re-exported path
// `back_of_house::chef_station::prepare_ingredients` was re-exported as `crate::back_of_house::prepare_ingredients`
crate::back_of_house::prepare_ingredients();
}
// A function to demonstrate relative paths *within* the crate root
fn eat_at_restaurant() {
// Relative path using `self` (refers to items within the current module, which is `crate` for main.rs)
self::front_of_house::hosting::add_to_waitlist();
self::back_of_house::cook_order();
// You could also technically use `crate::` here as `self` in the crate root is `crate`
crate::front_of_house::hosting::add_to_waitlist();
println!("\tEating at restaurant function finished.");
}
```








Paths for Referring to an Item in the Module Tree