Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to avoid using `mod.rs` files?

Tags:

rust

I read the mod document and found that I must add mod.rs in each folder, for example I have to define mod like this in my project structure:

src/
  models/
    login.rs
    mod.rs
  routes/
    login_route.rs
    mod.rs
  services/
    login_service.rs
    mod.rs
  main.rs

and use it like this in main.rs:

mod models;
mod routes;
mod services;

Why do it like that? Why design like that? If the project increase, the project has many mod.rs file just for expose mod? It is a good practice? I did not understand. What is the advantage about do it like this way? If we just do it like this way:

crate::models::login;

it is so clear and easy to understand.

like image 520
Dolphin Avatar asked Dec 27 '25 20:12

Dolphin


2 Answers

Some of this is explained in What is the purpose of a mod.rs file?

Essentially Rust does not make any assumptions about the file structure and won't consider other .rs files without the developer declaring them. Instead it is intended that they use the module system to build up an organizational structure within their code.

While this differs from some other languages, this gives more control to the developer. Since import paths are decoupled the file structure, your modules, structs, functions, etc. can be re-organized and re-exported as necessary. This also allows you to declare exactly what is compiled, which can aid in conditional compilation.

So when does Rust use the file structure? When you declare a module without a body:

mod models;

It will look for a file to use for that module.

  • from a normal file, like utils.rs for example, it will look for a nested file/directory:

    ./utils/models.rs
    ./utils/models/mod.rs
    
  • from mod.rs or top-level lib.rs or main.rs (they are special in this regard), it will look for a sibling file/directory:

    ./models.rs
    ./models/mod.rs
    

The use of mod.rs conceptually allows you to use a directory as if it were a file (it is similar to index.js if you're familiar with Javascript).


Is there a way to avoid all these mod.rs files?

There are two decent alternatives:

  1. Use models.rs instead of models/mod.rs

    Simply move your mod.rs files up one level and rename them to match their directory. You do not have to modify contents of main.rs or any file. Your structure could look like this:

    src/
      models/
        login.rs
      routes/
        login_route.rs
      services/
        login_service.rs
      main.rs
      models.rs
      routes.rs
      services.rs
    

    This is slowly becoming the preferred method[citation needed] since it gives the files more descriptive names.

  2. Simply declare your module structure within main.rs:

    This is a bit unconventional, but nested module declarations will find nested files. You don't need mod.rs anywhere:

    src/
      models/
        login.rs
      routes/
        login_route.rs
      services/
        login_service.rs
      main.rs
    

    If you declare your modules in main.rs like so:

    mod models {
        mod login; // this will use ./models/login.rs
    }
    mod routes {
        mod login_route; // this will use ./routes/login_route.rs
    }
    mod services {
        mod login_service; // this will use ./services/login_service.rs
    }
    

    This isn't particularly recommended. It may work fine in small projects, but will become unwieldy as your codebase gets larger. You'll probably want to reach for mod.rs or the method shown above as a way keep your code composed.


Lastly, these transitive modules are not just for declaring other files. They're a convenient place to:

  • put shared code used within its sub-modules
  • include documentation for how its contained structs, traits, etc. are designed and/or meant to be used
  • re-export deeply nested items so they are more accessible to the rest of your code

Overall, the module system is just another level of abstraction to keep your code well-encapsulated.

like image 122
kmdreko Avatar answered Dec 30 '25 15:12

kmdreko


Since Rust 2018 edition, the mod.rs file is optional:

In Rust 2015, if you have a sub-module:

// This `mod` declaration looks for the `foo` module in
// `foo.rs` or `foo/mod.rs`.
mod foo;

It can live in foo.rs or foo/mod.rs. If it has sub-modules of its own, it must be foo/mod.rs. So a bar sub-module of foo would live at foo/bar.rs.

In Rust 2018 the restriction that a module with sub-modules must be named mod.rs is lifted. foo.rs can just be foo.rs, and the sub-module is still foo/bar.rs. This eliminates the special name, and if you have a bunch of files open in your editor, you can clearly see their names, instead of having a bunch of tabs named mod.rs.

Other resources:

  • Rust's reference
  • Edition Guide
like image 24
Svetlin Zarev Avatar answered Dec 30 '25 16:12

Svetlin Zarev



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!