Skip to content

Core Concept: Modules & Crates ​

Updated Mar 2026

Overview ​

Rust's module system controls code organization, visibility, and namespacing. A crate is a compilation unit. A module groups related items within a crate.

Module Tree ​

Crate Types ​

rust
// src/main.rs — binary crate entry point
fn main() {
    println!("I'm an executable");
}

// src/lib.rs — library crate entry point
pub fn greet(name: &str) -> String {
    format!("Hello, {name}!")
}

Declaring Modules ​

Inline Modules ​

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

    fn internal_helper() -> i32 {
        42  // Private — only visible within math module
    }
}

pub fn use_math() {
    let sum = math::add(1, 2);  // Access public item
    // math::internal_helper();  // ERROR: private
}

File-Based Modules ​

src/
├── main.rs       # Declares modules
├── auth.rs       # mod auth (flat style)
├── api/
│   ├── mod.rs    # mod api (directory style)
│   ├── handlers.rs
│   └── middleware.rs
└── models.rs
rust
// src/main.rs
mod auth;        // Loads from src/auth.rs
mod api;         // Loads from src/api/mod.rs (or src/api.rs)
mod models;      // Loads from src/models.rs

fn main() {
    auth::login("user", "pass");
    api::handlers::get_users();
}
rust
// src/api/mod.rs
pub mod handlers;    // Loads src/api/handlers.rs
pub mod middleware;   // Loads src/api/middleware.rs

Modern File Layout (Rust 2018+) ​

src/
├── main.rs
├── auth.rs           # mod auth
├── api.rs            # mod api (declares submodules)
├── api/
│   ├── handlers.rs   # mod api::handlers
│   └── middleware.rs  # mod api::middleware
└── models.rs
rust
// src/api.rs (instead of src/api/mod.rs)
pub mod handlers;
pub mod middleware;

Visibility ​

rust
mod outer {
    pub struct Config {
        pub name: String,           // Public to everyone
        pub(crate) debug: bool,     // Public within the crate
        pub(super) version: u32,    // Public to parent module
        secret: String,             // Private (default)
    }

    pub(crate) fn crate_only() {
        // Visible within crate, not to external users
    }

    mod inner {
        pub(in crate::outer) fn outer_only() {
            // Only visible within outer module
        }
    }
}

use and Paths ​

rust
// Absolute path (from crate root)
use crate::auth::login;

// Relative path
use self::models::User;    // Same module
use super::helpers::format; // Parent module

// External crate
use std::collections::HashMap;
use serde::{Serialize, Deserialize};

// Rename to avoid conflicts
use std::fmt::Result as FmtResult;
use std::io::Result as IoResult;

// Glob import (avoid in production — use in tests/preludes)
use std::collections::*;

// Nested paths
use std::io::{self, Read, Write};
use std::collections::{HashMap, HashSet, BTreeMap};

Re-exports ​

rust
// src/lib.rs
mod internal {
    pub struct Database { ... }
    pub fn connect() -> Database { ... }
}

// Re-export for clean public API
pub use internal::Database;
pub use internal::connect;

// Users see: my_crate::Database, my_crate::connect
// NOT: my_crate::internal::Database

Prelude Pattern ​

rust
// src/prelude.rs
pub use crate::models::{User, Order};
pub use crate::error::AppError;
pub use crate::traits::{Validate, Serialize};

// Usage in other modules:
use crate::prelude::*;

Cargo.toml Dependencies ​

toml
[dependencies]
# From crates.io
serde = { version = "1.0", features = ["derive"] }
tokio = { version = "1", features = ["full"] }

# From git
my_crate = { git = "https://github.com/user/repo", branch = "main" }
my_crate = { git = "https://github.com/user/repo", rev = "abc123" }

# Local path (workspace or development)
shared = { path = "../shared" }

# Optional (for feature flags)
fancy = { version = "0.5", optional = true }

[dev-dependencies]
pretty_assertions = "1"

[build-dependencies]
cc = "1"

Workspaces ​

toml
# Root Cargo.toml
[workspace]
members = [
    "crates/core",
    "crates/api",
    "crates/cli",
]
resolver = "2"

[workspace.dependencies]
serde = { version = "1", features = ["derive"] }

Module Best Practices ​

PracticeWhy
Keep modules focused (single responsibility)Easier to navigate and test
Use pub(crate) over pub when possibleMinimize public API surface
Re-export important items from lib.rsClean API for consumers
Use prelude module for common importsReduce boilerplate
Prefer flat file layout over deep nestingEasier to find files
One type per file for large typesBetter git diffs

Built with VitePress | Rust SOP Documentation