Modules

01. In the same file

Related code and data are grouped into a module and stored in the same file.

fn main() {
   greetings::hello();
}

mod greetings {
  // ⭐️ By default, everything inside a module is private
  pub fn hello() { // ⭐️ So function has to be public to access from outside
    println!("Hello, world!");
  }
}

Modules can also be nested.

fn main() { 
  phrases::greetings::hello();
}

mod phrases { 
  pub mod greetings { 
    pub fn hello() { 
      println!("Hello, world!");
    }
  }
}

Private functions can be called from the same module or from a child module.

// 01. Calling private functions of the same module
fn main() {
  phrases::greet();
}

mod phrases {
  pub fn greet() {
    hello(); // Or `self::hello();`
  }
  
  fn hello() {
    println!("Hello, world!");
  }
}

// 02. Calling private functions of the parent module
fn main() {
  phrases::greetings::hello();
}

mod phrases {
  fn private_fn() {
    println!("Hello, world!");
  }
  
  pub mod greetings {
    pub fn hello() {
      super::private_fn();
    }
  }
}

💡 The self keyword is used to refer the same module, while the super keyword is used to refer parent module. Also, the super keyword can be used to access root functions from inside a module.

fn main() {
  greetings::hello();
}

fn hello() {
  println!("Hello, world!");
}

mod greetings {
  pub fn hello() {
    super::hello();
  }
}

🔎 When writing tests it’s a good practice to write tests inside a test module because they compile only when running tests.

fn greet() -> String {
    "Hello, world!".to_string()
}

#[cfg(test)] // Only compiles when running tests
mod tests {
    use super::greet; // Import root greet function

    #[test]
    fn test_greet() {
        assert_eq!("Hello, world!", greet());
    }
}

02. In a different file, same directory

// ↳ main.rs
mod greetings; // Import greetings module

fn main() {
  greetings::hello();
}

// ↳ greetings.rs
// ⭐️ No need to wrap the code with a mod declaration. The file itself acts as a module.
pub fn hello() { // The function has to be public to access from outside
  println!("Hello, world!");
}

If we wrap file content with a mod declaration, it will act as a nested module.

// ↳ main.rs
mod phrases;

fn main() {
  phrases::greetings::hello();
}

// ↳ phrases.rs
pub mod greetings { // ⭐️ The module has to be public to access from outside
  pub fn hello() {
    println!("Hello, world!");
  }
}

03. In a different file, different directory

mod.rs in the directory module root is the entry point to the directory module. All other files in that directory root, act as sub-modules of the directory module.

// ↳ main.rs
mod greetings;

fn main() {
  greetings::hello();
}

// ↳ greetings/mod.rs
pub fn hello() { // ⭐️ The function has to be public to access from outside
  println!("Hello, world!");
}

Again, If we wrap file content with a mod declaration, it will act as a nested module.

// ↳ main.rs
mod phrases;

fn main() {
  phrases::greetings::hello();
}

// ↳ phrases/mod.rs
pub mod greetings { // ⭐️ The module has to be public to access from outside
  pub fn hello() {
    println!("Hello, world!");
  }
}

Other files in the directory module act as sub-modules for mod.rs.

// ↳ main.rs
mod phrases;

fn main() {
  phrases::hello()
}

// ↳ phrases/mod.rs
mod greetings;

pub fn hello() {
  greetings::hello()
}

// ↳ phrases/greetings.rs
pub fn hello() {
  println!("Hello, world!");
}

⭐️ If you need to access an element of phrases/greetings.rs from outside the module, you have to import the greetings module as a public module.

// ↳ main.rs
mod phrases;

fn main() {
    phrases::greetings::hello();
}

// ↳ phrases/mod.rs
pub mod greetings;  // ⭐️ `pub mod` instead `mod`

// ↳ phrases/greetings.rs
pub fn hello() {
  println!("Hello, world!");
}

🔎 It’s unable to import child file modules of directory modules to main.rs, so you can’t use mod phrases::greetings; from main.rs. But there is a way to import phrases::greetings::hello() to phrases module by re-exporting hello to phrases module. So you can call it directly as phrases::hello().

// ↳ phrases/greetings.rs
pub fn hello() {
  println!("Hello, world!");
}

// ↳ phrases/mod.rs
pub mod greetings;

pub use self::greetings::hello; // Re-export `greetings::hello` to phrases

// ↳ main.rs
mod phrases;

fn main() {
    phrases::hello(); // You can call `hello()` directly from phrases
}

This allows you to present an external interface that may not directly map to your internal code organization. If still it is not clear, don’t worry; We discuss the usages of use on an upcoming section in this post.