1 % The Rust Crates and Modules Guide
3 When a project starts getting large, it's considered a good software
4 engineering practice to split it up into a bunch of smaller pieces, and then
5 fit them together. It's also important to have a well-defined interface, so
6 that some of your functionality is private, and some is public. To facilitate
7 these kinds of things, Rust has a module system.
9 # Basic terminology: Crates and Modules
11 Rust has two distinct terms that relate to the module system: "crate" and
12 "module." A crate is synonymous with a 'library' or 'package' in other
13 languages. Hence "Cargo" as the name of Rust's package management tool: you
14 ship your crates to others with Cargo. Crates can produce an executable or a
15 shared library, depending on the project.
17 Each crate has an implicit "root module" that contains the code for that crate.
18 You can then define a tree of sub-modules under that root module. Modules allow
19 you to partition your code within the crate itself.
21 As an example, let's make a "phrases" crate, which will give us various phrases
22 in different languages. To keep things simple, we'll stick to "greetings" and
23 "farewells" as two kinds of phrases, and use English and Japanese (日本語) as
24 two languages for those phrases to be in. We'll use this module layout:
32 +---------+ | +-----------+
34 +---------+ | +-----------+
36 +---------+ | +-----------+
38 +----------+ | +-----------+
46 In this example, `phrases` is the name of our crate. All of the rest are
47 modules. You can see that they form a tree, branching out from the crate
48 "root", which is the root of the tree: `phrases` itself.
50 Now that we have a plan, let's define these modules in code. To start,
51 generate a new crate with Cargo:
58 If you remember, this generates a simple project for us:
70 `src/lib.rs` is our crate root, corresponding to the `phrases` in our diagram
75 To define each of our modules, we use the `mod` keyword. Let's make our
76 `src/lib.rs` look like this:
102 After the `mod` keyword, you give the name of the module. Module names follow
103 the conventions for other Rust identifiers: `lower_snake_case`. The contents of
104 each module are within curly braces (`{}`).
106 Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
107 with double-colon (`::`) notation: our four nested modules are
108 `english::greetings`, `english::farewells`, `japanese::greetings`, and
109 `japanese::farewells`. Because these sub-modules are namespaced under their
110 parent module, the names don't conflict: `english::greetings` and
111 `japanese::greetings` are distinct, even though their names are both
114 Because this crate does not have a `main()` function, and is called `lib.rs`,
115 Cargo will build this crate as a library:
119 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
121 deps libphrases-a7448e02a0468eaa.rlib native
124 `libphrase-hash.rlib` is the compiled crate. Before we see how to use this
125 crate from another crate, let's break it up into multiple files.
127 # Multiple file crates
129 If each crate were just one file, these files would get very large. It's often
130 easier to split up crates into multiple files, and Rust supports this in two
133 Instead of declaring a module like this:
137 // contents of our module go here
141 We can instead declare our module like this:
147 If we do that, Rust will expect to find either a `english.rs` file, or a
148 `english/mod.rs` file with the contents of our module:
151 // contents of our module go here
154 Note that in these files, you don't need to re-declare the module: that's
155 already been done with the initial `mod` declaration.
157 Using these two techniques, we can break up our crate into two directories and
177 ├── libphrases-a7448e02a0468eaa.rlib
181 `src/lib.rs` is our crate root, and looks like this:
191 These two declarations tell Rust to look for either `src/english.rs` and
192 `src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
193 on our preference. In this case, because our modules have sub-modules, we've
194 chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
198 // both src/english/mod.rs and src/japanese/mod.rs
205 Again, these declarations tell Rust to look for either
206 `src/english/greetings.rs` and `src/japanese/greetings.rs` or
207 `src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because
208 these sub-modules don't have their own sub-modules, we've chosen to make them
209 `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
211 Right now, the contents of `src/english/greetings.rs` and
212 `src/japanese/farewells.rs` are both empty at the moment. Let's add some
215 Put this in `src/english/greetings.rs`:
218 // in src/english/greetings.rs
220 fn hello() -> String {
225 Put this in `src/english/farewells.rs`:
228 // in src/english/farewells.rs
230 fn goodbye() -> String {
231 "Goodbye.".to_string()
235 Put this in `src/japanese/greetings.rs`:
238 // in src/japanese/greetings.rs
240 fn hello() -> String {
245 Of course, you can copy and paste this from this web page, or just type
246 something else. It's not important that you actually put "konnichiwa" to learn
247 about the module system.
249 Put this in `src/japanese/farewells.rs`:
252 // in src/japanese/farewells.rs
254 fn goodbye() -> String {
259 (This is "Sayoonara", if you're curious.)
261 Now that we have our some functionality in our crate, let's try to use it from
264 # Importing External Crates
266 We have a library crate. Let's make an executable crate that imports and uses
269 Make a `src/main.rs` and put this in it: (it won't quite compile yet)
274 extern crate phrases;
277 println!("Hello in English: {}", phrases::english::greetings::hello());
278 println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
280 println!("Hello in Japanese: {}", phrases::japanese::greetings::hello());
281 println!("Goodbye in Japanese: {}", phrases::japanese::farewells::goodbye());
285 The `extern crate` declaration tells Rust that we need to compile and link to
286 the `phrases` crate. We can then use `phrases`' modules in this one. As we
287 mentioned earlier, you can use double colons to refer to sub-modules and the
288 functions inside of them.
290 Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
291 rather than a library crate. Once we compile `src/main.rs`, we'll get an
292 executable that we can run. Our package now has two crates: `src/lib.rs` and
293 `src/main.rs`. This pattern is quite common for executable crates: most
294 functionality is in a library crate, and the executable crate uses that
295 library. This way, other programs can also use the library crate, and it's also
296 a nice separation of concerns.
298 This doesn't quite work yet, though. We get four errors that look similar to
303 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
304 /home/you/projects/phrases/src/main.rs:4:38: 4:72 error: function `hello` is private
305 /home/you/projects/phrases/src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello());
306 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
307 note: in expansion of format_args!
308 <std macros>:2:23: 2:77 note: expansion site
309 <std macros>:1:1: 3:2 note: in expansion of println!
310 /home/you/projects/phrases/src/main.rs:4:5: 4:76 note: expansion site
314 By default, everything is private in Rust. Let's talk about this in some more
317 # Exporting a Public Interface
319 Rust allows you to precisely control which aspects of your interface are
320 public, and so private is the default. To make things public, you use the `pub`
321 keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs`
327 extern crate phrases;
330 println!("Hello in English: {}", phrases::english::greetings::hello());
331 println!("Goodbye in English: {}", phrases::english::farewells::goodbye());
335 In our `src/lib.rs`, let's add `pub` to the `english` module declaration:
345 And in our `src/english/mod.rs`, let's make both `pub`:
348 // in src/english/mod.rs
355 In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration:
358 // in src/english/greetings.rs
360 pub fn hello() -> String {
365 And also in `src/english/farewells.rs`:
368 // in src/english/farewells.rs
370 pub fn goodbye() -> String {
371 "Goodbye.".to_string()
375 Now, our crate compiles, albeit with warnings about not using the `japanese`
380 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
381 /home/you/projects/phrases/src/japanese/greetings.rs:1:1: 3:2 warning: code is never used: `hello`, #[warn(dead_code)] on by default
382 /home/you/projects/phrases/src/japanese/greetings.rs:1 fn hello() -> String {
383 /home/you/projects/phrases/src/japanese/greetings.rs:2 "こんにちは".to_string()
384 /home/you/projects/phrases/src/japanese/greetings.rs:3 }
385 /home/you/projects/phrases/src/japanese/farewells.rs:1:1: 3:2 warning: code is never used: `goodbye`, #[warn(dead_code)] on by default
386 /home/you/projects/phrases/src/japanese/farewells.rs:1 fn goodbye() -> String {
387 /home/you/projects/phrases/src/japanese/farewells.rs:2 "さようなら".to_string()
388 /home/you/projects/phrases/src/japanese/farewells.rs:3 }
389 Running `target/phrases`
390 Hello in English: Hello!
391 Goodbye in English: Goodbye.
394 Now that our functions are public, we can use them. Great! However, typing out
395 `phrases::english::greetings::hello()` is very long and repetitive. Rust has
396 another keyword for importing names into the current scope, so that you can
397 refer to them with shorter names. Let's talk about `use`.
399 # Importing Modules with `use`
401 Rust has a `use` keyword, which allows us to import names into our local scope.
402 Let's change our `src/main.rs` to look like this:
407 extern crate phrases;
409 use phrases::english::greetings;
410 use phrases::english::farewells;
413 println!("Hello in English: {}", greetings::hello());
414 println!("Goodbye in English: {}", farewells::goodbye());
418 The two `use` lines import each module into the local scope, so we can refer to
419 the functions by a much shorter name. By convention, when importing functions, it's
420 considered best practice to import the module, rather than the function directly. In
421 other words, you _can_ do this:
424 extern crate phrases;
426 use phrases::english::greetings::hello;
427 use phrases::english::farewells::goodbye;
430 println!("Hello in English: {}", hello());
431 println!("Goodbye in English: {}", goodbye());
435 But it is not idiomatic. This is significantly more likely to introducing a
436 naming conflict. In our short program, it's not a big deal, but as it grows, it
437 becomes a problem. If we have conflicting names, Rust will give a compilation
438 error. For example, if we made the `japanese` functions public, and tried to do
442 extern crate phrases;
444 use phrases::english::greetings::hello;
445 use phrases::japanese::greetings::hello;
448 println!("Hello in English: {}", hello());
449 println!("Hello in Japanese: {}", hello());
453 Rust will give us a compile-time error:
456 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
457 /home/you/projects/phrases/src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module
458 /home/you/projects/phrases/src/main.rs:4 use phrases::japanese::greetings::hello;
459 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
460 error: aborting due to previous error
461 Could not compile `phrases`.
464 If we're importing multiple names from the same module, we don't have to type it out
465 twice. Rust has a shortcut syntax for writing this:
468 use phrases::english::greetings;
469 use phrases::english::farewells;
472 You use curly braces:
475 use phrases::english::{greetings, farewells};
478 These two declarations are equivalent, but the second is a lot less typing.
480 ## Re-exporting with `pub use`
482 You don't just use `use` to shorten identifiers. You can also use it inside of your crate
483 to re-export a function inside another module. This allows you to present an external
484 interface that may not directly map to your internal code organization.
486 Let's look at an example. Modify your `src/main.rs` to read like this:
491 extern crate phrases;
493 use phrases::english::{greetings,farewells};
494 use phrases::japanese;
497 println!("Hello in English: {}", greetings::hello());
498 println!("Goodbye in English: {}", farewells::goodbye());
500 println!("Hello in Japanese: {}", japanese::hello());
501 println!("Goodbye in Japanese: {}", japanese::goodbye());
505 Then, modify your `src/lib.rs` to make the `japanese` mod public:
515 Next, make the two functions public, first in `src/japanese/greetings.rs`:
518 // in src/japanese/greetings.rs
520 pub fn hello() -> String {
525 And then in `src/japanese/farewells.rs`:
528 // in src/japanese/farewells.rs
530 pub fn goodbye() -> String {
535 Finally, modify your `src/japanese/mod.rs` to read like this:
538 // in src/japanese/mod.rs
540 pub use self::greetings::hello;
541 pub use self::farewells::goodbye;
548 The `pub use` declaration brings the function into scope at this part of our
549 module hierarchy. Because we've `pub use`d this inside of our `japanese`
550 module, we now have a `phrases::japanese::hello()` function and a
551 `phrases::japanese::goodbye()` function, even though the code for them lives in
552 `phrases::japanese::greetings::hello()` and
553 `phrases::japanese::farewells::goodbye()`. Our internal organization doesn't
554 define our external interface.
556 Also, note that we `pub use`d before we declared our `mod`s. Rust requires that
557 `use` declarations go first.
559 This will build and run:
563 Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
564 Running `target/phrases`
565 Hello in English: Hello!
566 Goodbye in English: Goodbye.
567 Hello in Japanese: こんにちは
568 Goodbye in Japanese: さようなら