---
title: "13.1 Naming collisions, and why modules exist"
description: "As programs grow, two pieces of code want the same name; modules are Rust's way to organize code into named scopes so names don't collide."
url: "https://learnrust.net/chapter-13/naming-collisions-and-modules/"
last_updated: "2026-06-13"
---

# 13.1 Naming collisions, and why modules exist

Every program you've written has lived in one file, `main.rs`, and every function and type has had a unique name because you chose them all yourself. That works until it doesn't. Real programs have hundreds of functions written by many people across many files, and sooner or later two of them want to be called `connect`, or `parse`, or `new`. This lesson is about the problem that creates, and the tool Rust gives you to solve it: **modules**.

## The naming collision problem

Imagine you're writing a program that talks to both a database and a network service. Both naturally have a function called `connect`:

```rust
fn connect() {
    println!("connecting to the database");
}

fn connect() {
    println!("connecting to the network");
}

fn main() {
    connect();
}
```

```
error[E0428]: the name `connect` is defined multiple times
 --> src/main.rs:5:1
  |
1 | fn connect() {
  | ------------ previous definition of the value `connect` here
...
5 | fn connect() {
  | ^^^^^^^^^^^^ `connect` redefined here
  |
  = note: `connect` must be defined only once in the value namespace of this module
```

Two functions, one name, and the compiler refuses to choose. You could rename them `connect_database` and `connect_network`, and for two functions that's fine. But this approach falls apart at scale: prefixing every name with the area it belongs to is exactly the manual bookkeeping that programming tools are supposed to do for you. The error message even hints at the real answer with the phrase "namespace of this module." There's a better way than gluing prefixes onto names.

## Modules: named scopes for code

A **module** is a named container for code. You group related items (functions, types, other modules) inside a `mod` block, and their names then live *inside* that module rather than out in the open:

```rust
mod database {
    fn connect() {
        println!("connecting to the database");
    }
}

mod network {
    fn connect() {
        println!("connecting to the network");
    }
}
```

Now there are two functions named `connect`, and no collision, because one is `database::connect` and the other is `network::connect`. The module name and the `::` path separator (the same one from `String::from` and `TrafficLight::Red`) keep them distinct. Each module is its own little world; a name defined in one doesn't clash with the same name in another. This is the idea behind organizing any large codebase: carve the program into named regions so that names only have to be unique *within* a region.

> **Key insight**
>
> Modules solve the same problem at the code level that structs solved at the data level: organization. A struct groups related *values* under one name; a module groups related *code* under one name. Both let you stop juggling a flat pile of loose things and start working with meaningful, named groupings. As a program grows, this organization stops being a nicety and becomes the only thing keeping it comprehensible.

## What this chapter replaces

If you've heard that C and C++ have a reputation for fiddly project setup, this chapter is a large part of why Rust doesn't. To split a program across files and manage names, C++ needs header files, header guards (or `#pragma once`), forward declarations, the preprocessor's `#include` text-pasting, and a separate `namespace` feature, spread across many lessons in a course like learncpp. Rust folds all of that into one coherent system: modules for organization and namespacing, and a single line to pull in another file (lesson [13.4](https://learnrust.net/chapter-13/splitting-code-into-files/)). There are no headers, no include guards, and no preprocessor.

> **Author's note**
>
> This is the single biggest place where "the Rust course is shorter" stops being a slogan and becomes visible. A C++ curriculum spends a whole chapter on the mechanics of getting two files to see each other's functions without the linker complaining. We spend a few lessons, most of which are about *design* (how to organize code well) rather than *ceremony* (how to make the build system cooperate). The ceremony just isn't there.

## The road map for this chapter

Here's where the next lessons go. Lesson [13.2](https://learnrust.net/chapter-13/defining-modules/) shows how to define modules and refer to things inside them with paths and `use`. Lesson [13.3](https://learnrust.net/chapter-13/visibility-pub/) covers `pub`, the keyword that controls what's visible outside a module, which is how you build clean boundaries between parts of a program. Lesson [13.4](https://learnrust.net/chapter-13/splitting-code-into-files/) is the payoff: moving modules into separate files, the lesson that replaces that whole C++ chapter. After that, crates and `Cargo` (lessons [13.5](https://learnrust.net/chapter-13/binary-and-library-crates/) and [13.6](https://learnrust.net/chapter-13/cargo-in-depth/)), and finally Rust's documentation culture (lessons [13.7](https://learnrust.net/chapter-13/documentation-comments/) and [13.8](https://learnrust.net/chapter-13/reading-documentation/)).

For now, the takeaway is just the motivation: as code grows, names collide, and modules are the named scopes that prevent it.

## Quiz time

**Question #1**

Why does prefixing every function name (like `connect_database`, `connect_network`) not scale as a solution to naming collisions?

<details class="solution">
<summary>Show solution</summary>

It's manual bookkeeping that gets worse as the program grows: every name has to carry the region it belongs to, you have to remember and type those prefixes everywhere, and there's nothing stopping two people from choosing different prefixes for the same area. Modules do the grouping automatically, so names only need to be unique within their module, and the module name does the disambiguating.

</details>

**Question #2**

This is refused. Name the error and fix it with modules so both `area` functions can coexist.

```rust
fn area() { println!("circle"); }
fn area() { println!("square"); }
```

<details class="solution">
<summary>Show solution</summary>

E0428: the name `area` is defined multiple times. Put each in its own module:

```rust
mod circle {
    fn area() { println!("circle"); }
}

mod square {
    fn area() { println!("square"); }
}
```

Now they're `circle::area` and `square::area`, distinct names in distinct modules.

</details>

**Question #3**

In one sentence, what does a module do, and what familiar tool does it parallel?

<details class="solution">
<summary>Show solution</summary>

A module is a named container that groups related code so its names live inside that scope rather than out in the open. It parallels a struct: a struct groups related values under one name, a module groups related code under one name.

</details>

Modules organize code and prevent collisions. The next lesson gets concrete: defining modules, referring to their contents with paths like `crate::`, `self::`, and `super::`, and bringing names into scope with `use`.

## Sitemap

See the full [sitemap](https://learnrust.net/sitemap.md) for all pages.
