Skip to content
Modules and Visibility
step 1/6

Reading — step 1 of 6

Learn

~2 min readModules and Threads

Rust's module system organizes code into a hierarchy and controls visibility. Every Rust file defines a module; modules can nest and form a crate.

Defining modules

// In src/lib.rs or src/main.rs
mod math {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
    
    fn private_helper() {}
}

fn main() {
    let sum = math::add(3, 4);
    // math::private_helper();   // ✗ private
}

mod declares a module. Items are private by defaultpub exposes them.

Files and modules

A module can be in its own file:

// src/main.rs:
mod math;        // declares module from math.rs (or math/mod.rs)

fn main() {
    println!("{}", math::add(3, 4));
}

// src/math.rs:
pub fn add(a: i32, b: i32) -> i32 { a + b }

For nested modules:

src/
  main.rs
  math/
    mod.rs           // or math.rs (modern style)
    geometry.rs       // submodule math::geometry
// src/math/mod.rs (or src/math.rs):
pub mod geometry;     // expose submodule
pub fn add(a: i32, b: i32) -> i32 { a + b }

Visibility levels

fn private() {}                  // visible only in this module
pub fn public() {}                // visible everywhere
pub(crate) fn crate_only() {}     // visible within this crate
pub(super) fn parent_only() {}    // visible in parent module
pub(in path) fn restricted() {}   // visible in specific path

Least-privilege by default. Promote items to pub only when consumers need them.

use statements

Bring names into scope to avoid long paths:

use std::collections::HashMap;
use std::io::{self, Read, Write};   // multiple from one path
use std::fmt::Display as Disp;        // alias

// In a function:
let mut map: HashMap<String, i32> = HashMap::new();

Crates and Cargo

A crate is a compilation unit — either a binary (with main) or a library. Cargo (Rust's package manager) handles dependencies via Cargo.toml:

[package]
name = "my_project"
version = "0.1.0"
edition = "2021"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

cargo build, cargo run, cargo test, cargo check are the daily workflow.

Re-exports

A library can curate its public API by re-exporting:

// src/lib.rs:
mod internal;
pub use internal::PublicType;   // surface only this from the internal module

Keeps the internal layout flexible while presenting a stable API.

Common mistakes

  • Forgetting pub on items consumers need — "private item" errors.
  • Confusing the file name and module namesrc/foo.rs defines module foo (parent of foo declares mod foo;).
  • Importing the entire module instead of specific items — bloats compile times in big projects.
  • use statements at function scope — works but is unconventional. Put them at top of file or module.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…