Modules

01. In 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();
    }
  }
}

💡 self keyword is used to refer same module, while super keyword is used to refer parent module. Also 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 of 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 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. File itself acts as a module.
pub fn hello() { // 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 { // ⭐️ module has to be public to access from outside
  pub fn hello() {
    println!("Hello, world!");
  }
}

03. In 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() { // ⭐️ 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 { // ⭐️ 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 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.

Last updated