Modules and Packages

Modules and visibility, use paths, Cargo features, and how a workspace splits one product into crates.

Modules and packages

Structs and private fields only make sense once a module hides them. This lesson is the crate, then Cargo’s dependency file. Generics come after, because they are a language feature, not a package feature.

Modules and visibility

A crate is one compilation unit, a binary or a library. A package is the Cargo.toml that builds one or more crates. A module is a namespace inside a crate.

Cargo.tomlpackagesrc/lib.rscrate rootauthmoduleroutesmodule
StatusThe package points at the crate

lib.rs is the root. mod auth; loads auth.rs or auth/mod.rs. mod routes; does the same. An inline mod { } is the same idea in one file, which is all a single lesson file can show.

MarkWho can see the name
(none)Only the parent module
pubOutside the module
pub(crate)The whole crate
pub(super)The parent module
pub(in path)One path you name

Private fields plus public methods are how a type keeps its invariant.

PathStarts from
crate::auth::loginThis crate
super::helpersThe parent module
std::collections::HashMapThe standard library
asRenames an import
pub use auth::UserRe-exports a name so callers do not need the inner path
The preludeAlready imports Option, Result, Vec, and the other names you have been using without a use line
A workspaceLists members, one lockfile, and one target directory. That is how a monorepo shares versions.
01_modules_visibility.rsRust
mod inventory {
    pub struct Item {
        pub name: String,
        sku: String,
    }

    impl Item {
        pub fn new(name: &str, sku: &str) -> Self {
            Self { name: name.to_string(), sku: sku.to_string() }
        }

        pub fn sku(&self) -> &str {
            &self.sku
        }
    }
}

fn main() {
    let item = inventory::Item::new("bolt", "B-1");
    println!("{} {}", item.name, item.sku());
}

Dependencies, features, and versions

Cargo.toml tableUsed for
dependenciesThe program itself
dev-dependenciesTests
build-dependenciesBuild scripts

A version of 1.2.3 for a 1.0 crate means compatible updates inside 1.x. A 0.x crate may break between minor numbers. Prefer a caret range such as "1" and let Cargo.lock pin the exact build for a binary. Commit that lockfile.

your-binpackageaxumdependencyserdedependencyhypertransitive
StatusYou name direct dependencies

Features are compile-time flags: serde with derive, tokio with a runtime. cfg(feature = "json") compiles a module only when that flag is on.

02_cargo_features_workspaces.rsRust
fn main() {
    println!("dependencies live in Cargo.toml, not in this file");
    println!("cargo tree, cargo update, and cargo check are the daily tools");
}