Syntax Cache
BlogMethodFeaturesHow It WorksBuild a Game
  1. Home
  2. Rust
  3. Rust Modules & Crates Practice: mod, use, pub, Crate Structure
Rust44 exercises

Rust Modules & Crates Practice: mod, use, pub, Crate Structure

Master Rust module system including mod declarations, use imports, visibility with pub, and crate organization patterns.

Common ErrorsQuick ReferencePractice
Warm-up1 / 2

Can you write this from memory?

Declare a module named `utils`.

On this page
  1. 1Package vs Crate vs Module vs Workspace
  2. 2Compiler Error E0432: Unresolved Import
  3. 3Compiler Error E0603: Function Is Private
  4. 4Compiler Error E0583: File Not Found for Module
  5. 5How Rust Finds Module Files
  6. 6The "main.rs + lib.rs = Two Crates" Gotcha
  7. 7Path Prefixes: crate::, super::, self::
  8. 8Visibility Levels
  9. The Privacy Rule Beginners Miss
  10. 9Re-exports and API Surfacing with pub use
  11. The Prelude Pattern
  12. 10Further Reading
Package vs Crate vs Module vs WorkspaceCompiler Error E0432: Unresolved ImportCompiler Error E0603: Function Is PrivateCompiler Error E0583: File Not Found for ModuleHow Rust Finds Module FilesThe "main.rs + lib.rs = Two Crates" GotchaPath Prefixes: crate::, super::, self::Visibility LevelsRe-exports and API Surfacing with pub useFurther Reading

Rust's module system organizes code into namespaces with explicit visibility. The mod keyword declares modules, use brings items into scope, and pub controls what's accessible outside.

The rules seem simple until you're actually structuring a project: Does mod foo; look for foo.rs or foo/mod.rs? What's the difference between use crate:: and use super::? When do you need pub use for re-exports?

This page focuses on module syntax and patterns until declaring modules, importing items, controlling visibility, and organizing crates are automatic.

Related Rust Topics
Rust Foundations: Variables, Types & Basic SyntaxRust Traits & Generics: Trait Bounds, impl Trait, TurbofishRust Testing: #[test], assert!, Unit & Integration Tests

A package has a Cargo.toml. A crate is the compilation unit (rooted at lib.rs or main.rs). A module is a namespace inside a crate. Don't confuse them—mod declares modules, cargo new creates packages.

People confuse these constantly. Here is the hierarchy:

TermWhat it isContains
PackageHas a Cargo.tomlUp to 1 library crate + multiple binary crates
CrateCompilation unitA module tree rooted at lib.rs or main.rs
ModuleNamespace inside a crateItems (functions, structs, traits, submodules)
WorkspaceHas a root Cargo.toml with [workspace]Multiple packages developed together

A package is what you cargo new. A crate is what the compiler builds. A module is how you organize code inside a crate.

Ready to practice?

Start practicing Rust Modules & Crates: mod, use, pub, Crate Structure with spaced repetition

The most common module mistake is trying to use a module you never declared:

// WRONG: using without declaring
// use crate::utils::helper; // error[E0432]: unresolved import

// RIGHT: declare the module first
mod utils;  // tells Rust to look for src/utils.rs
use crate::utils::helper;

Without mod utils;, the compiler has no idea utils exists. The mod declaration is what makes Rust load the file.

Making the module pub does not make its contents public. Visibility is per-item:

// In lib.rs
pub mod utils;  // module is public

// In utils.rs
fn helper() { }  // WRONG: function is private — error[E0603]

pub fn helper() { }  // RIGHT: function is also public

A public module can contain entirely private items. You must mark each item that should be accessible. Struct field visibility follows the same rules -- see structs and enums for the pub field pattern.

Rust cannot find the file matching your mod declaration:

// src/lib.rs
mod utils;  // error[E0583] if neither src/utils.rs nor src/utils/mod.rs exists

Check: file name must exactly match the module name, and it must be in the right directory relative to the parent module's location.

mod utils; looks for src/utils.rs (modern, preferred) or src/utils/mod.rs (older). For submodules, use the directory approach: network.rs plus a network/ directory.

When you write mod utils;, Rust looks for:

  • src/utils.rs (modern style, preferred)
  • src/utils/mod.rs (older style, still works)

If utils has submodules, use the directory approach:

// src/lib.rs
mod network;

// src/network.rs (or src/network/mod.rs)
pub mod client;
pub mod server;

// src/network/client.rs
pub fn connect() { }

The modern style is network.rs with a network/ directory for submodules. Since Rust 2018, foo.rs and a foo/ directory can coexist, so mod.rs is no longer required.

If your package has both src/main.rs and src/lib.rs, Cargo builds two separate crates — a binary and a library — each with its own module tree:

// src/lib.rs
pub mod config;  // only visible to the library crate's tree

// src/main.rs
// WRONG: main.rs can't see lib.rs modules directly
// use config::Settings;  // error[E0432]

// RIGHT: main.rs must use the library crate by its package name
use my_package::config::Settings;

This is why "I declared it in lib.rs but main.rs can't see it" happens. The binary crate depends on the library crate like any external dependency.

PrefixStarts fromAnalogy
crate::Crate root (lib.rs or main.rs)Absolute path /
super::Parent moduleRelative ../
self::Current moduleRelative ./
// From src/network/client.rs
use crate::config::Settings;     // absolute: starts at crate root
use super::server::listen;       // relative: goes up to network, then into server
use self::helpers::parse_url;    // explicit current module (rarely needed)

Since Rust 2018, extern crate is no longer needed in most cases — the compiler resolves crate names automatically from Cargo.toml dependencies. The Facade design pattern applies naturally here: re-export a simplified API from your crate root while hiding complex internal module structure.

Items are private by default. pub exposes to everyone, pub(crate) to the crate only, pub(super) to the parent module. Making a module pub does NOT make its contents public—each item needs its own pub.

VisibilityAccessible fromUse for
pubAnywhere (including dependents)Public API
pub(crate)Anywhere in the crateInternal shared utilities
pub(super)Parent module onlyHelpers for parent
pub(in crate::some::path)Specified ancestor module and its childrenScoped internal API
(none)Current module onlyImplementation details
pub fn public_api() { }                          // visible to everyone
pub(crate) fn internal_only() { }                // crate-wide, hidden from dependents
pub(super) fn parent_only() { }                  // parent module only
pub(in crate::network) fn network_only() { }     // visible within crate::network subtree
fn private_helper() { }                          // current module only

The Privacy Rule Beginners Miss

Items are private by default. Child modules can access private items of their ancestor modules, but parents cannot access private items of children. The testing guide shows how #[cfg(test)] mod tests uses this rule to test private functions from a child module:

mod parent {
    fn secret() { }

    mod child {
        fn peek() {
            super::secret();  // OK: child can see parent's private items
        }
    }

    fn try_peek() {
        // child::peek();  // ERROR: parent can't see child's private items
    }
}

Keep internal modules private and re-export the public API from lib.rs:

// src/lib.rs — clean public API
mod internal;
mod config;
pub use internal::Config;     // users write my_crate::Config
pub use config::Settings;     // users write my_crate::Settings

The Prelude Pattern

For crates with many public types, create a prelude module:

// src/prelude.rs
pub use crate::Config;
pub use crate::Error;
pub use crate::Result;

// Users can do:
// use my_crate::prelude::*;

  • The Rust Book: Modules — packages, crates, modules, paths
  • Rust By Example: Modules — practical module examples
  • Rust Reference: Visibility — pub, pub(crate), pub(in path) rules
  • Rust Reference: Items and Modules — module file lookup, inline modules

When to Use Rust Modules & Crates: mod, use, pub, Crate Structure

  • Use `mod` to declare modules and organize code.
  • Use `use` to bring items into scope without full paths.
  • Use `pub` to expose items outside their module.
  • Use `pub(crate)` for crate-internal APIs.
  • Use `pub use` to re-export items at a different path.

Check Your Understanding: Rust Modules & Crates: mod, use, pub, Crate Structure

Prompt

Explain the difference between mod and use in Rust.

What a strong answer looks like

`mod` declares/defines a module (creates a namespace). `use` brings items into scope (creates shortcuts). You need `mod` first to make the module exist, then `use` to conveniently access its items.

What You'll Practice: Rust Modules & Crates: mod, use, pub, Crate Structure

Declare modules with modImport items with use and nested pathsControl visibility with pub, pub(crate), pub(super), pub(in path)Re-export with pub useUnderstand crate:: vs super:: vs self::Organize multi-file cratesUnderstand package vs crate vs moduleHandle the main.rs + lib.rs two-crate patternCreate prelude modules for crate-wide imports

Common Rust Modules & Crates: mod, use, pub, Crate Structure Pitfalls

  • You see `error[E0432]: unresolved import` -- you wrote `use crate::utils::helper` but never declared the module. Add `mod utils;` in your `lib.rs` or `main.rs` before the `use` statement.
  • You see `error[E0603]: function is private` -- you made the module `pub` but not the item inside it. Add `pub` to the function or struct definition, not just to the `mod` declaration.
  • You see `error[E0583]: file not found for module` -- Rust expects `src/utils.rs` or `src/utils/mod.rs` and cannot find either. Check spelling and file location.
  • You write `mod foo;` and `use foo;` and get confused about which does what -- `mod` declares a module (loads the file), `use` brings items into scope (creates shortcuts). For modules in your crate source tree, declare with `mod` before importing items from them.
  • You declared a module in `lib.rs` but `main.rs` cannot see it -- if your package has both `main.rs` and `lib.rs`, they are separate crates. From `main.rs`, import via the package name: `use my_package::my_module::Thing;`.
  • You get a Cargo error about cyclic dependencies -- Cargo does not support cyclic crate dependencies. If two crates need each other, extract shared traits or types into a third crate. Cross-references between modules inside the same crate are fine.

Rust Modules & Crates: mod, use, pub, Crate Structure FAQ

Where does mod foo; look for the file?

Either `foo.rs` in the same directory, or `foo/mod.rs`. Modern Rust prefers `foo.rs` with `foo/` directory for submodules. The `foo/mod.rs` style is older but still works.

What is the difference between crate::, super::, and self::?

`crate::` starts from the crate root. `super::` goes up one module level (like `..` in paths). `self::` refers to the current module (rarely needed but useful in some use statements).

What is pub use for?

Re-exporting: making something available at a different path. `pub use internal::Thing;` lets users write `crate::Thing` instead of `crate::internal::Thing`. Great for flattening APIs.

What is pub(crate)?

Visible within the crate but not to external users. More restrictive than `pub` but more permissive than private. Good for internal APIs that multiple modules need.

What is the prelude?

Items automatically imported into every Rust program: Option, Result, common traits, etc. Defined in `std::prelude`. You can create your own prelude module with `pub use` re-exports for crate-wide imports.

Why can't main.rs see modules declared in lib.rs?

If your package has both main.rs and lib.rs, they are separate crates with separate module trees. From main.rs, import via the package name: `use my_package::module::Item;`.

What is pub(in path)?

`pub(in crate::some::module)` restricts visibility to that module and its children. More precise than `pub(crate)` but less common. Useful for scoping internal APIs within a specific subtree.

Rust Modules & Crates: mod, use, pub, Crate Structure Syntax Quick Reference

Module declaration
mod utils;
mod models;
mod handlers;
Inline module
mod helpers {
    pub fn do_thing() {
        println!("did thing");
    }
}
Basic use
use std::collections::HashMap;
Nested use
use std::{io, fs, path::Path};
Glob import
use std::io::prelude::*;
Crate path
use crate::models::User;
Super path
use super::utils::helper;
Re-export
pub use internal::Config;
pub(crate)
pub(crate) fn internal_helper() -> i32 {
    42
}
pub(in path)
pub(in crate::network) fn scoped_helper() { }
Alias
use std::io::Result as IoResult;
Module file structure
// src/lib.rs
mod network;

// src/network.rs
pub mod client;
pub mod server;

// src/network/client.rs
pub fn connect() -> &'static str {
    "connected"
}

Rust Modules & Crates: mod, use, pub, Crate Structure Sample Exercises

Example 1Difficulty: 1/5

Fill in the keyword to bring HashMap into scope.

use
Example 2Difficulty: 2/5

Fill in the keyword to make the function public.

pub
Example 3Difficulty: 2/5

Fill in the keyword for the crate root in a path.

crate

+ 41 more exercises

Further Reading

  • Rust Newtype Pattern: Catch Unit Bugs at Compile Time18 min read

Start practicing Rust Modules & Crates: mod, use, pub, Crate Structure

Free daily exercises with spaced repetition. No credit card required.

← Back to Rust Syntax Practice
Syntax Cache

Build syntax muscle memory with spaced repetition.

Product

  • Pricing
  • Our Method
  • Daily Practice
  • Design Patterns
  • Interview Prep

Resources

  • Blog
  • Compare
  • Cheat Sheets
  • Vibe Coding
  • Muscle Memory

Languages

  • Python
  • JavaScript
  • TypeScript
  • Rust
  • SQL
  • GDScript

Legal

  • Terms
  • Privacy
  • Contact

© 2026 Syntax Cache

Cancel anytime in 2 clicks. Keep access until the end of your billing period.

No refunds for partial billing periods.