If you ever fought against Rust modules, you probably already googled for terms such as "*rust modules*" or "*rust modules structure*". And you probably stumbled upon the Rust book. But after reading the articles, you're maybe in a situation were you still don't grab the whole idea, and according to the new article called Path Clarity:

... why it's so confusing to many: while there are simple and consistent rules defining the module system, their consequences can feel inconsistent, counterintuitive and mysterious.

For modules defined inside a source *.rs* file, that's OK. But if you're a seasoned developer, you're used to break down your code into different source files.

I wrote this article, with a simple example, to better understand the Rust module system. I'm referring to the last version of Rust called Rust 2018.

So let's create a simple project structure using *cargo*, with a hierarchical structure

```
$ cargo new rust_modules --bin
```

Let's create a simple module hierarchical structure based on maths:

```
// main.rs
mod math {
pub mod arithmetic {
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
pub fn mul(x: i32, y: i32) -> i32 {
x * y
}
}
pub mod trigonometry {
pub mod ordinary {
pub fn sin(x: f32) -> f32 {
x.sin()
}
pub fn cos(x: f32) -> f32 {
x.cos()
}
}
pub mod hyperbolic {
pub fn sinh(x: f32) -> f32 {
(x.exp() - (-x).exp()) / 2f32
}
pub fn cosh(x: f32) -> f32 {
(x.exp() + (-x).exp()) / 2f32
}
}
}
}
fn main() {
use math::arithmetic::{add, mul};
use math::trigonometry::hyperbolic::{cosh, sinh};
use math::trigonometry::ordinary::{cos, sin};
}
```

This code compiles because it's located in the same source file. Things are getting more complicated if you want to split the module into different source files:

```
// src/math.rs or src/math/mod.rs
pub mod arithmetic {
pub fn add(x: i32, y: i32) -> i32 {
x + y
}
pub fn mul(x: i32, y: i32) -> i32 {
x * y
}
}
pub mod trigonometry {
pub mod ordinary {
pub fn sin(x: f32) -> f32 {
x.sin()
}
pub fn cos(x: f32) -> f32 {
x.cos()
}
}
pub mod hyperbolic {
pub fn sinh(x: f32) -> f32 {
(x.exp() - (-x).exp()) / 2f32
}
pub fn cosh(x: f32) -> f32 {
(x.exp() + (-x).exp()) / 2f32
}
}
}
```

You can put the internal of the math module into a single file in *src/math.rs* (filename has the same name of the module without extension) or in *src/math/mod.rs*. Then the

*main.rs* becomes:

```
// math module internals is either in src/math.rs or src/math/mod.rs
mod math;
fn main() {
use math::arithmetic::{add, mul};
use math::trigonometry::hyperbolic::{cosh, sinh};
use math::trigonometry::ordinary::{cos, sin};
}
```

You can even use the new path attribute to move your source code wherever you want:

```
// the source code containing the math module is moved to /tmp/math.rs
#[path="/tmp/math.rs"]
mod math;
fn main() {
use math::arithmetic::{add, mul};
use math::trigonometry::hyperbolic::{cosh, sinh};
use math::trigonometry::ordinary::{cos, sin};
}
```

So using the *mod.rs* technique, you could breakdown the *math* module into several source files:

```
├── main.rs
└── math
├── arithmetic.rs
├── mod.rs
└── trigonometry
├── hyperbolic.rs
├── mod.rs
└── ordinary.rs
```

with the following *mod.rs* files:

```
// src/math/mod.rs
pub mod arithmetic;
pub mod trigonometry;
```

```
// src/math/trigonometry/mod.rs
pub mod hyperbolic;
pub mod ordinary;
```

I should say this is not the most straightforward module strategy, but once you get acquainted to it, it feels more natural. So the key takeaways are:

- the
*mod*&*use*keywords are like*import*or*require*in popular languages - a module named
*mymod*reflects either a filename similar to*mymod.rs*or*mymod/mod.rs*

Photo by Timo Volz on Unsplash

## Top comments (3)

I think the confusion starts when you want to use modules within each other but don't want to have like 10 layer deep structure. That's why when I use rust I use a more flatten out structure. By creating standalone modules in the code root directory and then use the use the

`use create`

i.e.

Thanks for your reply.

I like things to be tidy, that's why I much prefer a hierarchical structure. But that's just a personal opinion.

Why are we not using the

`use crate::..`

syntax to get the access the modules?