Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I include modules "sideways" in Rust?

Tags:

rust

I want to split a Rust program into multiple files, but the use of mod doesn't see to allow me to reference files in the same directory from files other than main.rs.

For example, if I have main.rs, game.rs, and matrix.rs in the same folder, I can reference structs/functions from game.rs or matrix.rs in main.rs with a mod game; or mod matrix;. I can't, however, reference matrix.rs from game.rs with a statement like mod matrix.

I've looked at several resources and all of them only have modules structures like trees that don't reference each other. Is it possible to use structs/functions from files in each other in Rust, or is that against the rules? If so, why doesn't Rust let you do that?

like image 839
Rak Avatar asked Feb 11 '16 05:02

Rak


1 Answers

mod is module declaration. This directive declares a module and all of its contents. It just so happens that these contents may be located in another file. So this:

mod game;
mod matrix;

is roughly equivalent to this:

mod game {
    // game.rs contents
}

mod matrix {
    // matrix.rs contents
}

Naturally, since mod is a declaration of a module, you can't do it multiple times for the same module. That is, you can try and write something like

mod game {
    mod matrix;
    ...
}

mod matrix;

but, as you can see, matrix and game::matrix are different modules, and naturally rustc requires different paths to their respective files, if they are external.

use, however, is import declaration. use declarations pull names from other modules for use in the current module. You can use any module and any public items from it any number of times from anywhere this module is accessible.

So, in order to reference matrix from game you need to use it:

// game.rs
use matrix;

Naturally, in order for this to work matrix should be declared with mod in the crate root.

As a side note, I personally think that the simplest way to understand Rust module system is to first forget that modules can be put in different files at all. That is, think as if a crate can only be defined in a single file. In Rust mod directives can have bodies and can nest, so nested mods actually define the module system of a crate:

mod foo {
    mod bax {
        ...
    }
    mod baz {
        ...
    }
}
mod bar {
    mod qux {
        mod zux {
            ...
        }
    }
}

If you only have a single file, you can easily see how mod and use directives would work, and relationship between modules should become clear.

And now you only need to add to the picture the fact that if a module is declared without a body, like in mod name;, its content is loaded either from name.rs or name/mod.rs, whatever is available. However, the full picture does not change in the slightest - these still are nested modules which can always be represented as a single source file with nested mod directives. In fact, cargo rustc -Z unstable-options --pretty=normal will print your crate in this form, after all modules in external source files are assembled into a single document. I suggest running this command on some crates with complex module structure to see how it looks in practice.

like image 62
Vladimir Matveev Avatar answered Oct 05 '22 18:10

Vladimir Matveev