I’m going to answer this question too, for anyone else who finds this and is (like me) totally confused by the difficult-to-comprehend answers.
It boils down to two things I feel are poorly explained in the tutorial:
-
The
mod blah;
syntax imports a file for the compiler. You must use this on all the files you want to compile. -
As well as shared libraries, any local module that is defined can be imported into the current scope using
use blah::blah;
.
A typical example would be:
src/main.rs
src/one/one.rs
src/two/two.rs
In this case, you can have code in one.rs
from two.rs
by using use
:
use two::two; // <-- Imports two::two into the local scope as 'two::'
pub fn bar() {
println!("one");
two::foo();
}
However, main.rs
will have to be something like:
use one::one::bar; // <-- Use one::one::bar
mod one { pub mod one; } // <-- Awkwardly import one.rs as a file to compile.
// Notice how we have to awkwardly import two/two.rs even though we don't
// actually use it in this file; if we don't, then the compiler will never
// load it, and one/one.rs will be unable to resolve two::two.
mod two { pub mod two; }
fn main() {
bar();
}
Notice that you can use the blah/mod.rs
file to somewhat alleviate the awkwardness, by placing a file like one/mod.rs
, because mod x;
attempts x.rs
and x/mod.rs
as loads.
// one/mod.rs
pub mod one.rs
You can reduce the awkward file imports at the top of main.rs to:
use one::one::bar;
mod one; // <-- Loads one/mod.rs, which loads one/one.rs.
mod two; // <-- This is still awkward since we don't two, but unavoidable.
fn main() {
bar();
}
There’s an example project doing this on Github.
It’s worth noting that modules are independent of the files the code blocks are contained in; although it would appear the only way to load a file blah.rs
is to create a module called blah
, you can use the #[path]
to get around this, if you need to for some reason. Unfortunately, it doesn’t appear to support wildcards, aggregating functions from multiple files into a top-level module is rather tedious.