Rust Modules In Less Than 5 Minutes

When I started learning Rust, the module system did not at first seem to be a shining beacon of intuitive design. The Rust documentation is phenomenal, but there are definitely some areas that I found difficult to follow; this being one such topic. So I thought I might take a stab at writing up a guide that I think would have helped me through the awkward growing pains a bit quicker.

This article is not intended to explain all of the intricacies of the Rust module system, nor is it for demonstrating proper project structure. It’s simply a quick overview of the actual mechanics around using modules in Rust.

Start your stop watch….now!

The View at 30,000 Feet

There are three general ways to declare a module in rust.

  1. Embedded in an existing source file.

With flexibility often comes complexity and confusion, so let’s unpack each of those.

Embedded Modules

These are modules that you would create to break up certain parts of your file into different namespaces. It looks something like this:

In case it wasn’t obvious before, modules are used for isolating and packaging up some code for use elsewhere. As the comments explain, only public members of the module are available to external callers.

In my somewhat limited experience writing Rust, this seems to be one of the least useful forms modules take. That said, it’s still important to know and could certainly be the right tool depending on what you’re building.

Module Files

These are typically modules that you want to separate from the rest of your code, but don’t contain any sub-modules of their own (although there is no such constraint*). They look something like this:

If you’re paying attention, you’ll notice that the code hasn’t really changed at all. We’ve moved what was in the old mod block into its own file named . The naming is important here! The mod declaration in lets the rust compiler know that it needs to look for a file specifically named and make that code available under the doorman:: namespace.

Module Folders

These are typically modules that have sub-modules within them. If you imagine having multiple, smaller libraries that make up a larger project, this is likely the approach to take. Here’s what the simplest example looks like:

Notice a difference? It’s subtle, right? The only change is we’ve moved src/ to src/doorman/ . So when you have a module declaration like mod doorman; , the Rust compiler is looking for either a or a doorman/ file in the same directory as the declaration.

Admittedly, this particular example might leave you asking “What’s the point? Why not just always use”.

Back when we were looking at the module files example, our program was made up of a main “module”,, and a doorman module, The same exact principles can be applied to a module itself. This becomes useful when organizing a big, complex project into smaller, bite-size pieces. In keeping with the doorman example, we could refactor into something like this:

Now lets remember what we’ve learned so far and see if we can figure out what the Rust compiler is going to do with this.

  1. The mod doorman; declaration in tells the Rust compiler that there’s a module named doorman somewhere in the src directory.

Final Thoughts

That’s it! Now you should be able to break that giant into dozens of little modules. Or not! That’s the power of the module system, once you’ve wrapped your head around it. As a programmer, you’re given the freedom to choose the project structure and levels of indirection that make sense for your program. But at the same time, just about every Rust project you come across will be structured predictably (albeit in some combination of the three methods we discussed today). There also isn’t any additional syntax you have to include in your files that tell Rust what module or package they should be in. It’s all driven by convention.

It’s also important to realize that none of this even touches on crates, which is another packaging/isolation construct that works at an even higher level than modules. Crates, however, are much more similar in principle to the code packaging you’re probably already familiar with from other languages. So I think you’ll find them much easier to grok if you haven’t already.

*There really aren’t any constraints to when you should use one form versus another. It’s entirely up to you as the programmer.

For more detailed information:

Just a programmer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store