---
title: What is the difference between mod and use
summary: mod defines a code namespace, while use imports items from that namespace into the current scope.
lang: en
slug: what-is-the-difference-between-mod-and-use
published: 2026-04-17T12:05:42+00:00
updated: 2026-04-25T22:00:13+00:00
canonical: https://www.rustfaq.org/en/what-is-the-difference-between-mod-and-use/
---

# What is the difference between mod and use



## The wall between files

You are building a text adventure. Your `main.rs` has grown to four hundred lines. You have a `Player` struct, a `Weapon` enum, and a `calculate_damage` function all tangled together. Scrolling takes too long. You decide to move the weapon logic into its own file. You create `weapon.rs`. You paste the code. You try to compile. The compiler screams that `Weapon` is not found. You have hit the wall between files and modules.

Rust does not automatically merge files. Every file is isolated until you explicitly tell the compiler how they connect. This isolation is a feature. It prevents name collisions and keeps your project organized. But it means you have to learn two distinct tools: `mod` and `use`. One builds the structure. The other cleans up your typing.

## Structure versus shortcuts

The `mod` keyword defines a module. A module is a namespace. It groups related code together and creates a boundary. When you write `mod weapon`, you are declaring a new box in your program's architecture. The compiler now expects code to live inside that box. If you provide the code inline, it goes there. If you use a semicolon, the compiler looks for a file named `weapon.rs` or a directory `weapon/mod.rs`.

The `use` keyword brings items into the current scope. It is a convenience shortcut. When you write `use weapon::Weapon`, you are telling the compiler: "In this function, whenever I type `Weapon`, look inside the `weapon` module for a public item with that name." It does not copy the code. It does not change visibility. It just creates a reference in the symbol table so you don't have to type the full path every time.

Think of `mod` as the architect drawing the floor plan. It defines where the kitchen is, where the bedroom is, and which doors are locked. `use` is you walking into the kitchen and deciding to call the fridge "fridge" instead of "kitchen::fridge". The fridge doesn't move. The kitchen doesn't change. You just saved yourself some typing.

`mod` organizes the codebase. `use` organizes your local scope. They solve different problems.

## A minimal example

Here is the pattern in its simplest form. You define a module with a public function. You bring that function into scope. You call it.

```rust
/// Defines a module named `math_utils`.
/// This creates a namespace. Code inside is private by default.
mod math_utils {
    /// Returns the square of a number.
    /// The `pub` keyword makes this accessible outside the module.
    pub fn square(x: i32) -> i32 {
        x * x
    }
}

/// Brings `square` into the current scope.
/// Now we can call `square()` instead of `math_utils::square()`.
use math_utils::square;

fn main() {
    // Without `use`, this line would need `math_utils::square(5)`.
    let result = square(5);
    println!("5 squared is {}", result);
}
```

The `mod` block creates the namespace. The `pub` on the function opens the door. The `use` statement creates the shortcut. Remove any one of these, and the code breaks.

Don't treat `use` as a substitute for structure. Get the modules right first. Then clean up the noise.

## How the compiler resolves paths

When you compile, Rust builds a module tree. The root is the crate. Every `mod` adds a branch. Every `use` adds a leaf to your current branch.

Consider this structure:

```rust
mod game {
    pub mod player {
        pub struct Hero {
            pub name: String,
        }
    }
}

use game::player::Hero;

fn main() {
    let hero = Hero { name: "Alice".to_string() };
}
```

The compiler sees `mod game`. It creates a `game` branch. Inside `game`, it sees `mod player`. It creates a `player` branch. Inside `player`, it sees `pub struct Hero`. It adds `Hero` to the `player` namespace.

The `use game::player::Hero;` statement walks that tree. It starts at the current scope, goes down to `game`, then to `player`, and finds `Hero`. Since `Hero` is `pub`, and `player` is `pub`, and `game` is `pub`, the path is valid. The compiler creates an alias. When you type `Hero` in `main`, the compiler resolves it to `game::player::Hero`.

If any part of the chain is missing `pub`, the walk stops. The compiler rejects the import. Visibility is transitive. You can only access what is explicitly exposed at every level.

`use` does not execute code. It is a compile-time operation. It affects zero runtime performance. It only changes how the compiler resolves names.

## Real code across files

In a real project, modules usually live in separate files. This keeps files manageable. The syntax changes slightly. You declare the module with a semicolon, and the compiler looks for the file.

```rust
// main.rs

/// Declares the `utils` module.
/// The compiler looks for `utils.rs` in the same directory.
mod utils;

/// Imports `format_greeting` so we don't type `utils::format_greeting`.
use utils::format_greeting;

fn main() {
    let msg = format_greeting("Alice");
    println!("{}", msg);
}
```

```rust
// utils.rs

/// Formats a greeting string.
/// Must be `pub` to be accessible outside this module.
pub fn format_greeting(name: &str) -> String {
    format!("Hello, {}!", name)
}
```

The `mod utils;` in `main.rs` is the bridge. It tells the compiler to include `utils.rs` in the build. Without that line, `utils.rs` is just a text file on disk. The compiler ignores it.

Community convention is to group `use` statements at the top of the file. It keeps imports visible and makes dependencies obvious. You can group multiple items with curly braces to save space:

```rust
use std::collections::{HashMap, HashSet};
```

This is equivalent to two separate `use` lines. It reduces vertical clutter. The compiler treats them identically.

Another convention is `pub use`. This lets a module re-export an item. It flattens the API surface. If you have a deep module tree, you can expose items at a higher level:

```rust
mod internal {
    pub struct SecretData { /* ... */ }
}

pub use internal::SecretData;
```

Now users can write `crate::SecretData` instead of `crate::internal::SecretData`. This is how `std::vec::Vec` becomes available as `std::Vec`. You use `pub use` to design a clean public interface while keeping implementation details hidden.

Visibility is the gatekeeper. `mod` and `use` are just the map.

## Pitfalls and compiler errors

New Rust code often trips over visibility and path resolution. The compiler catches these early, but the errors can be confusing if you don't know what to look for.

**Private items block imports.** You move a function to a new file. You add `mod utils;`. You try to `use utils::helper;`. The compiler rejects you with `error[E0603]: module or function is private`. The fix is to add `pub` to the item. Items are private by default. `mod` creates the box, but the door is locked unless you open it.

**Missing `mod` declarations.** You create `weapon.rs`. You try to `use weapon::Weapon;`. The compiler says `error[E0432]: unresolved import`. You forgot to declare the module. Add `mod weapon;` to the parent file. The compiler needs the declaration to know the file exists.

**`use` does not change visibility.** You can't `use` a private item from a parent module. The compiler will flag this immediately. `use` is a shortcut, not a permission slip. If the item isn't accessible, the import fails.

**Shadowing.** You can `use` a name that already exists. The new name shadows the old one. This is usually a mistake. The compiler warns about unused imports, but shadowing can hide bugs. Be careful with `use` in nested scopes.

**Circular dependencies.** You have `mod a;` and `mod b;`. `a` uses `b`, and `b` uses `a`. Rust handles this fine at the module level. The compiler builds the whole tree before checking dependencies. Circular imports are allowed as long as the types resolve. This is different from some other languages. You don't need to worry about import order.

Trust the borrow checker. It usually has a point. The module system is equally strict. Respect the boundaries.

## When to use what

Choosing between `mod`, `use`, and full paths depends on your goal. Follow this decision matrix to keep your code clean and maintainable.

Use `mod` to define a namespace and organize code into logical groups. Use `mod` to declare external files so the compiler includes them in the build. Use `mod` when you want to encapsulate implementation details and expose only a public API. Use `mod` with a semicolon when the module lives in a separate file. Use `mod` with a block when the module is small and inline makes sense.

Use `use` to bring items into the current scope and reduce typing. Use `use` when you reference a type or function frequently and the full path is verbose. Use `use` to create aliases with `as` when names clash or the original name is confusing. Use `use` to group imports at the top of the file for readability. Use `pub use` to re-export items and flatten your public API.

Use full paths like `crate::utils::helper` when you want to be explicit about where a name comes from. Use full paths when two modules export the same name and you don't want to manage aliases. Use full paths in documentation examples to show the complete structure. Use full paths when the item is used only once and the path is short.

Structure first, shortcuts second. Get the modules right, then clean up the noise.

## Where to go next

- [What Is the Difference Between mod.rs and Named Files in Rust 2018+?](/en/what-is-the-difference-between-modrs-and-named-files-in-rust-2018/)
- [How to Use the pub(crate) and pub(super) Visibility Modifiers](/en/how-to-use-the-pubcrate-and-pubsuper-visibility-modifiers/)
- [How to organize a large Rust project](/en/how-to-organize-a-large-rust-project/)