]> git.proxmox.com Git - rustc.git/blame - src/doc/book/second-edition/nostarch/chapter07.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / book / second-edition / nostarch / chapter07.md
CommitLineData
cc61c64b
XL
1
2[TOC]
3
7cac9316 4# Using Modules to Reuse and Organize Code
cc61c64b
XL
5
6When you start writing programs in Rust, your code might live solely in the
7cac9316
XL
7`main` function. As your code grows, you’ll eventually move functionality into
8other functions for reuse and better organization. By splitting your code into
9smaller chunks, each chunk is easier to understand on its own. But what happens
10if you have too many functions? Rust has a module system that enables the reuse
11of code in an organized fashion.
cc61c64b
XL
12
13In the same way that you extract lines of code into a function, you can extract
7cac9316 14functions (and other code, like structs and enums) into different modules. A
cc61c64b
XL
15*module* is a namespace that contains definitions of functions or types, and
16you can choose whether those definitions are visible outside their module
17(public) or not (private). Here’s an overview of how modules work:
18
7cac9316 19* The `mod` keyword declares a new module. Code within the module appears
abe05a73 20 either immediately following this declaration within curly brackets or in
7cac9316
XL
21 another file.
22* By default, functions, types, constants, and modules are private. The `pub`
23 keyword makes an item public and therefore visible outside its namespace.
24* The `use` keyword brings modules, or the definitions inside modules, into
25 scope so it’s easier to refer to them.
cc61c64b 26
7cac9316 27We’ll look at each of these parts to see how they fit into the whole.
cc61c64b
XL
28
29## `mod` and the Filesystem
30
31We’ll start our module example by making a new project with Cargo, but instead
7cac9316
XL
32of creating a binary crate, we’ll make a library crate: a project that other
33people can pull into their projects as a dependency. For example, the `rand`
abe05a73
XL
34crate discussed in Chapter 2 is a library crate that we used as a dependency in
35the guessing game project.
7cac9316 36
cc61c64b 37We’ll create a skeleton of a library that provides some general networking
7cac9316
XL
38functionality; we’ll concentrate on the organization of the modules and
39functions but we won’t worry about what code goes in the function bodies. We’ll
40call our library `communicator`. By default, Cargo will create a library unless
41another type of project is specified: if we omit the `--bin` option that we’ve
42been using in all of the chapters preceding this one, our project will be a
43library:
cc61c64b 44
7cac9316 45```
cc61c64b
XL
46$ cargo new communicator
47$ cd communicator
48```
49
50Notice that Cargo generated *src/lib.rs* instead of *src/main.rs*. Inside
7cac9316 51*src/lib.rs* we’ll find the following:
cc61c64b 52
7cac9316 53Filename: src/lib.rs
cc61c64b 54
7cac9316 55```
cc61c64b
XL
56#[cfg(test)]
57mod tests {
58 #[test]
59 fn it_works() {
abe05a73 60 assert_eq!(2 + 2, 4);
cc61c64b
XL
61 }
62}
63```
64
abe05a73
XL
65Cargo creates an example test to help us get our library started, rather than
66the “Hello, world!” binary that we get when we use the `--bin` option. We’ll
67look at the `#[]` and `mod tests` syntax in the “Using `super` to Access a
68Parent Module” section later in this chapter, but for now, leave this code at
69the bottom of *src/lib.rs*.
cc61c64b 70
7cac9316
XL
71Because we don’t have a *src/main.rs* file, there’s nothing for Cargo to
72execute with the `cargo run` command. Therefore, we’ll use the `cargo build`
73command to compile our library crate’s code.
74
75We’ll look at different options for organizing your library’s code that will be
76suitable in a variety of situations, depending on the intent of the code.
cc61c64b
XL
77
78### Module Definitions
79
7cac9316
XL
80For our `communicator` networking library, we’ll first define a module named
81`network` that contains the definition of a function called `connect`. Every
82module definition in Rust starts with the `mod` keyword. Add this code to the
83beginning of the *src/lib.rs* file, above the test code:
cc61c64b 84
7cac9316 85Filename: src/lib.rs
cc61c64b 86
7cac9316 87```
cc61c64b
XL
88mod network {
89 fn connect() {
90 }
91}
92```
93
7cac9316 94After the `mod` keyword, we put the name of the module, `network`, and then a
abe05a73 95block of code in curly brackets. Everything inside this block is inside the
7cac9316 96namespace `network`. In this case, we have a single function, `connect`. If we
abe05a73 97wanted to call this function from code outside the `network` module, we
7cac9316
XL
98would need to specify the module and use the namespace syntax `::`, like so:
99`network::connect()` rather than just `connect()`.
cc61c64b 100
7cac9316
XL
101We can also have multiple modules, side by side, in the same *src/lib.rs* file.
102For example, to also have a `client` module that has a function named `connect`
103as well, we can add it as shown in Listing 7-1:
cc61c64b 104
7cac9316 105Filename: src/lib.rs
cc61c64b 106
7cac9316 107```
cc61c64b
XL
108mod network {
109 fn connect() {
110 }
111}
112
113mod client {
114 fn connect() {
115 }
116}
117```
118
7cac9316 119Listing 7-1: The `network` module and the `client` module defined side by side
cc61c64b
XL
120in *src/lib.rs*
121
cc61c64b
XL
122Now we have a `network::connect` function and a `client::connect` function.
123These can have completely different functionality, and the function names do
7cac9316
XL
124not conflict with each other because they’re in different modules.
125
126In this case, because we’re building a library, the file that serves as the
127entry point for building our library is *src/lib.rs*. However, in respect to
128creating modules, there’s nothing special about *src/lib.rs*. We could also
3b2f2976 129create modules in *src/main.rs* for a binary crate in the same way as we’re
7cac9316
XL
130creating modules in *src/lib.rs* for the library crate. In fact, we can put
131modules inside of modules, which can be useful as your modules grow to keep
132related functionality organized together and separate functionality apart. The
133choice of how you organize your code depends on how you think about the
134relationship between the parts of your code. For instance, the `client` code
135and its `connect` function might make more sense to users of our library if
136they were inside the `network` namespace instead, as in Listing 7-2:
137
138Filename: src/lib.rs
139
140```
cc61c64b
XL
141mod network {
142 fn connect() {
143 }
144
145 mod client {
146 fn connect() {
147 }
148 }
149}
150```
151
7cac9316 152Listing 7-2: Moving the `client` module inside the `network` module
cc61c64b
XL
153
154In your *src/lib.rs* file, replace the existing `mod network` and `mod client`
7cac9316
XL
155definitions with the ones in Listing 7-2, which have the `client` module as an
156inner module of `network`. Now we have the functions `network::connect` and
cc61c64b 157`network::client::connect`: again, the two functions named `connect` don’t
7cac9316 158conflict with each other because they’re in different namespaces.
cc61c64b
XL
159
160In this way, modules form a hierarchy. The contents of *src/lib.rs* are at the
161topmost level, and the submodules are at lower levels. Here’s what the
7cac9316
XL
162organization of our example in Listing 7-1 looks like when thought of as a
163hierarchy:
cc61c64b 164
7cac9316 165```
cc61c64b
XL
166communicator
167 ├── network
168 └── client
169```
170
7cac9316 171And here’s the hierarchy corresponding to the example in Listing 7-2:
cc61c64b 172
7cac9316 173```
cc61c64b
XL
174communicator
175 └── network
176 └── client
177```
178
7cac9316
XL
179The hierarchy shows that in Listing 7-2, `client` is a child of the `network`
180module rather than a sibling. More complicated projects can have many modules,
181and they’ll need to be organized logically in order to keep track of them. What
182“logically” means in your project is up to you and depends on how you and your
183library’s users think about your project’s domain. Use the techniques shown
184here to create side-by-side modules and nested modules in whatever structure
185you would like.
cc61c64b
XL
186
187### Moving Modules to Other Files
188
189Modules form a hierarchical structure, much like another structure in computing
7cac9316
XL
190that you’re used to: filesystems! We can use Rust’s module system along with
191multiple files to split up Rust projects so not everything lives in
192*src/lib.rs* or *src/main.rs*. For this example, let’s start with the code in
193Listing 7-3:
cc61c64b 194
7cac9316 195Filename: src/lib.rs
cc61c64b 196
7cac9316 197```
cc61c64b
XL
198mod client {
199 fn connect() {
200 }
201}
202
203mod network {
204 fn connect() {
205 }
206
207 mod server {
208 fn connect() {
209 }
210 }
211}
212```
213
cc61c64b
XL
214Listing 7-3: Three modules, `client`, `network`, and `network::server`, all
215defined in *src/lib.rs*
216
7cac9316 217The file *src/lib.rs* has this module hierarchy:
cc61c64b 218
7cac9316 219```
cc61c64b
XL
220communicator
221 ├── client
222 └── network
223 └── server
224```
225
7cac9316
XL
226If these modules had many functions, and those functions were becoming lengthy,
227it would be difficult to scroll through this file to find the code we wanted to
abe05a73
XL
228work with. Because the functions are nested inside one or more `mod` blocks,
229the lines of code inside the functions will start getting lengthy as well.
230These would be good reasons to separate the `client`, `network`, and `server`
231modules from *src/lib.rs* and place them into their own files.
cc61c64b 232
abe05a73
XL
233First, replace the `client` module code with only the declaration of the
234`client` module, so that your *src/lib.rs* looks like the following:
cc61c64b 235
7cac9316 236Filename: src/lib.rs
cc61c64b 237
7cac9316 238```
cc61c64b
XL
239mod client;
240
241mod network {
242 fn connect() {
243 }
244
245 mod server {
246 fn connect() {
247 }
248 }
249}
250```
251
7cac9316
XL
252We’re still *declaring* the `client` module here, but by replacing the block
253with a semicolon, we’re telling Rust to look in another location for the code
254defined within the scope of the `client` module. In other words, the line `mod
255client;` means:
256
257```
258mod client {
259 // contents of client.rs
260}
261```
cc61c64b 262
7cac9316
XL
263Now we need to create the external file with that module name. Create a
264*client.rs* file in your *src/* directory and open it. Then enter the
cc61c64b
XL
265following, which is the `connect` function in the `client` module that we
266removed in the previous step:
267
7cac9316 268Filename: src/client.rs
cc61c64b 269
7cac9316 270```
cc61c64b
XL
271fn connect() {
272}
273```
274
7cac9316
XL
275Note that we don’t need a `mod` declaration in this file because we already
276declared the `client` module with `mod` in *src/lib.rs*. This file just
cc61c64b
XL
277provides the *contents* of the `client` module. If we put a `mod client` here,
278we’d be giving the `client` module its own submodule named `client`!
279
280Rust only knows to look in *src/lib.rs* by default. If we want to add more
281files to our project, we need to tell Rust in *src/lib.rs* to look in other
282files; this is why `mod client` needs to be defined in *src/lib.rs* and can’t
283be defined in *src/client.rs*.
284
7cac9316
XL
285Now the project should compile successfully, although you’ll get a few
286warnings. Remember to use `cargo build` instead of `cargo run` because we have
287a library crate rather than a binary crate:
cc61c64b 288
7cac9316 289```
cc61c64b
XL
290$ cargo build
291 Compiling communicator v0.1.0 (file:///projects/communicator)
abe05a73 292warning: function is never used: `connect`
cc61c64b
XL
293 --> src/client.rs:1:1
294 |
abe05a73
XL
2951 | / fn connect() {
2962 | | }
297 | |_^
298 |
299 = note: #[warn(dead_code)] on by default
cc61c64b 300
abe05a73 301warning: function is never used: `connect`
cc61c64b
XL
302 --> src/lib.rs:4:5
303 |
abe05a73
XL
3044 | / fn connect() {
3055 | | }
306 | |_____^
cc61c64b 307
abe05a73 308warning: function is never used: `connect`
cc61c64b
XL
309 --> src/lib.rs:8:9
310 |
abe05a73
XL
3118 | / fn connect() {
3129 | | }
313 | |_________^
cc61c64b
XL
314```
315
316These warnings tell us that we have functions that are never used. Don’t worry
abe05a73
XL
317about these warnings for now; we’ll address them later in this chapter in the
318“Controlling Visibility with `pub`” section. The good news is that they’re just
7cac9316
XL
319warnings; our project built successfully!
320
7cac9316 321Next, let’s extract the `network` module into its own file using the same
cc61c64b
XL
322pattern. In *src/lib.rs*, delete the body of the `network` module and add a
323semicolon to the declaration, like so:
324
7cac9316 325Filename: src/lib.rs
cc61c64b 326
7cac9316 327```
cc61c64b
XL
328mod client;
329
330mod network;
331```
332
333Then create a new *src/network.rs* file and enter the following:
334
7cac9316 335Filename: src/network.rs
cc61c64b 336
7cac9316 337```
cc61c64b
XL
338fn connect() {
339}
340
341mod server {
342 fn connect() {
343 }
344}
345```
346
347Notice that we still have a `mod` declaration within this module file; this is
7cac9316 348because we still want `server` to be a submodule of `network`.
cc61c64b 349
7cac9316
XL
350Run `cargo build` again. Success! We have one more module to extract: `server`.
351Because it’s a submodule—that is, a module within a module—our current tactic
352of extracting a module into a file named after that module won’t work. We’ll
353try anyway so you can see the error. First, change *src/network.rs* to have
354`mod server;` instead of the `server` module’s contents:
cc61c64b 355
7cac9316 356Filename: src/network.rs
cc61c64b 357
7cac9316 358```
cc61c64b
XL
359fn connect() {
360}
361
362mod server;
363```
364
365Then create a *src/server.rs* file and enter the contents of the `server`
366module that we extracted:
367
7cac9316 368Filename: src/server.rs
cc61c64b 369
7cac9316 370```
cc61c64b
XL
371fn connect() {
372}
373```
374
375When we try to `cargo build`, we’ll get the error shown in Listing 7-4:
376
7cac9316 377```
cc61c64b
XL
378$ cargo build
379 Compiling communicator v0.1.0 (file:///projects/communicator)
380error: cannot declare a new module at this location
381 --> src/network.rs:4:5
382 |
3834 | mod server;
384 | ^^^^^^
385 |
abe05a73 386note: maybe move this module `src/network.rs` to its own directory via `src/network/mod.rs`
cc61c64b
XL
387 --> src/network.rs:4:5
388 |
3894 | mod server;
390 | ^^^^^^
391note: ... or maybe `use` the module `server` instead of possibly redeclaring it
392 --> src/network.rs:4:5
393 |
3944 | mod server;
395 | ^^^^^^
396```
397
cc61c64b
XL
398Listing 7-4: Error when trying to extract the `server` submodule into
399*src/server.rs*
400
cc61c64b
XL
401The error says we `cannot declare a new module at this location` and is
402pointing to the `mod server;` line in *src/network.rs*. So *src/network.rs* is
7cac9316 403different than *src/lib.rs* somehow: keep reading to understand why.
cc61c64b 404
7cac9316
XL
405The note in the middle of Listing 7-4 is actually very helpful because it
406points out something we haven’t yet talked about doing:
cc61c64b 407
7cac9316
XL
408```
409note: maybe move this module `network` to its own directory via
410`network/mod.rs`
cc61c64b
XL
411```
412
413Instead of continuing to follow the same file naming pattern we used
414previously, we can do what the note suggests:
415
7cac9316
XL
4161. Make a new *directory* named *network*, the parent module’s name.
4172. Move the *src/network.rs* file into the new *network* directory, and
abe05a73 418 rename it to *src/network/mod.rs*.
7cac9316 4193. Move the submodule file *src/server.rs* into the *network* directory.
cc61c64b
XL
420
421Here are commands to carry out these steps:
422
7cac9316 423```
cc61c64b
XL
424$ mkdir src/network
425$ mv src/network.rs src/network/mod.rs
426$ mv src/server.rs src/network
427```
428
7cac9316 429Now when we try to run `cargo build`, compilation will work (we’ll still have
cc61c64b
XL
430warnings though). Our module layout still looks like this, which is exactly the
431same as it did when we had all the code in *src/lib.rs* in Listing 7-3:
432
7cac9316 433```
cc61c64b
XL
434communicator
435 ├── client
436 └── network
437 └── server
438```
439
440The corresponding file layout now looks like this:
441
7cac9316 442```
cc61c64b 443├── src
7cac9316
XL
444│ ├── client.rs
445│ ├── lib.rs
446│ └── network
447│ ├── mod.rs
448│ └── server.rs
cc61c64b
XL
449```
450
451So when we wanted to extract the `network::server` module, why did we have to
7cac9316
XL
452also change the *src/network.rs* file to the *src/network/mod.rs* file and put
453the code for `network::server` in the *network* directory in
454*src/network/server.rs* instead of just being able to extract the
cc61c64b 455`network::server` module into *src/server.rs*? The reason is that Rust wouldn’t
7cac9316
XL
456be able to recognize that `server` was supposed to be a submodule of `network`
457if the *server.rs* file was in the *src* directory. To clarify Rust’s behavior
458here, let’s consider a different example with the following module hierarchy,
459where all the definitions are in *src/lib.rs*:
cc61c64b 460
7cac9316 461```
cc61c64b
XL
462communicator
463 ├── client
464 └── network
465 └── client
466```
467
7cac9316
XL
468In this example, we have three modules again: `client`, `network`, and
469`network::client`. Following the same steps we did earlier for extracting
470modules into files, we would create *src/client.rs* for the `client` module.
471For the `network` module, we would create *src/network.rs*. But we wouldn’t be
472able to extract the `network::client` module into a *src/client.rs* file
473because that already exists for the top-level `client` module! If we could put
474the code for *both* the `client` and `network::client` modules in the
475*src/client.rs* file, Rust wouldn’t have any way to know whether the code was
476for `client` or for `network::client`.
477
478Therefore, in order to extract a file for the `network::client` submodule of
479the `network` module, we needed to create a directory for the `network` module
480instead of a *src/network.rs* file. The code that is in the `network` module
481then goes into the *src/network/mod.rs* file, and the submodule
cc61c64b
XL
482`network::client` can have its own *src/network/client.rs* file. Now the
483top-level *src/client.rs* is unambiguously the code that belongs to the
484`client` module.
485
7cac9316 486### Rules of Module Filesystems
cc61c64b 487
7cac9316 488Let’s summarize the rules of modules with regard to files:
cc61c64b
XL
489
490* If a module named `foo` has no submodules, you should put the declarations
491 for `foo` in a file named *foo.rs*.
492* If a module named `foo` does have submodules, you should put the declarations
493 for `foo` in a file named *foo/mod.rs*.
494
7cac9316
XL
495These rules apply recursively, so if a module named `foo` has a submodule named
496`bar` and `bar` does not have submodules, you should have the following files
497in your *src* directory:
cc61c64b 498
7cac9316 499```
cc61c64b 500├── foo
7cac9316
XL
501│ ├── bar.rs (contains the declarations in `foo::bar`)
502│ └── mod.rs (contains the declarations in `foo`, including `mod bar`)
cc61c64b
XL
503```
504
7cac9316
XL
505The modules should be declared in their parent module’s file using the `mod`
506keyword.
cc61c64b 507
7cac9316 508Next, we’ll talk about the `pub` keyword and get rid of those warnings!
cc61c64b
XL
509
510## Controlling Visibility with `pub`
511
512We resolved the error messages shown in Listing 7-4 by moving the `network` and
513`network::server` code into the *src/network/mod.rs* and
514*src/network/server.rs* files, respectively. At that point, `cargo build` was
7cac9316 515able to build our project, but we still get warning messages about the
cc61c64b
XL
516`client::connect`, `network::connect`, and `network::server::connect` functions
517not being used:
518
7cac9316 519```
abe05a73
XL
520warning: function is never used: `connect`
521 --> src/client.rs:1:1
522 |
5231 | / fn connect() {
5242 | | }
525 | |_^
cc61c64b 526 |
abe05a73 527 = note: #[warn(dead_code)] on by default
cc61c64b 528
abe05a73 529warning: function is never used: `connect`
cc61c64b
XL
530 --> src/network/mod.rs:1:1
531 |
abe05a73
XL
5321 | / fn connect() {
5332 | | }
534 | |_^
cc61c64b 535
abe05a73 536warning: function is never used: `connect`
cc61c64b
XL
537 --> src/network/server.rs:1:1
538 |
abe05a73
XL
5391 | / fn connect() {
5402 | | }
541 | |_^
cc61c64b
XL
542```
543
544So why are we receiving these warnings? After all, we’re building a library
7cac9316
XL
545with functions that are intended to be used by our *users*, not necessarily by
546us within our own project, so it shouldn’t matter that these `connect`
cc61c64b 547functions go unused. The point of creating them is that they will be used by
7cac9316 548another project, not our own.
cc61c64b
XL
549
550To understand why this program invokes these warnings, let’s try using the
7cac9316
XL
551`connect` library from another project, calling it externally. To do that,
552we’ll create a binary crate in the same directory as our library crate by
553making a *src/main.rs* file containing this code:
cc61c64b 554
7cac9316 555Filename: src/main.rs
cc61c64b 556
7cac9316 557```
cc61c64b
XL
558extern crate communicator;
559
560fn main() {
561 communicator::client::connect();
562}
563```
564
565We use the `extern crate` command to bring the `communicator` library crate
7cac9316
XL
566into scope. Our package now contains *two* crates. Cargo treats *src/main.rs*
567as the root file of a binary crate, which is separate from the existing library
568crate whose root file is *src/lib.rs*. This pattern is quite common for
569executable projects: most functionality is in a library crate, and the binary
570crate uses that library crate. As a result, other programs can also use the
571library crate, and it’s a nice separation of concerns.
572
573From the point of view of a crate outside the `communicator` library looking
574in, all the modules we’ve been creating are within a module that has the same
575name as the crate, `communicator`. We call the top-level module of a crate the
576*root module*.
577
578Also note that even if we’re using an external crate within a submodule of our
cc61c64b
XL
579project, the `extern crate` should go in our root module (so in *src/main.rs*
580or *src/lib.rs*). Then, in our submodules, we can refer to items from external
581crates as if the items are top-level modules.
582
7cac9316
XL
583Right now, our binary crate just calls our library’s `connect` function from
584the `client` module. However, invoking `cargo build` will now give us an error
cc61c64b
XL
585after the warnings:
586
7cac9316 587```
abe05a73 588error[E0603]: module `client` is private
cc61c64b
XL
589 --> src/main.rs:4:5
590 |
5914 | communicator::client::connect();
592 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
593```
594
7cac9316
XL
595Ah ha! This error tells us that the `client` module is private, which is the
596crux of the warnings. It’s also the first time we’ve run into the concepts of
cc61c64b
XL
597*public* and *private* in the context of Rust. The default state of all code in
598Rust is private: no one else is allowed to use the code. If you don’t use a
7cac9316
XL
599private function within your program, because your program is the only code
600allowed to use that function, Rust will warn you that the function has gone
601unused.
602
603After we specify that a function like `client::connect` is public, not only
604will our call to that function from our binary crate be allowed, but the
605warning that the function is unused will go away. Marking a function as public
606lets Rust know that the function will be used by code outside of our program.
607Rust considers the theoretical external usage that’s now possible as the
abe05a73
XL
608function “being used.” Thus, when a function is marked public, Rust will not
609require that it be used in our program and will stop warning that the function
610is unused.
cc61c64b
XL
611
612### Making a Function Public
613
abe05a73
XL
614To tell Rust to make a function public, we add the `pub` keyword to the start
615of the declaration. We’ll focus on fixing the warning that indicates
616`client::connect` has gone unused for now, as well as the `` module `client` is
617private `` error from our binary crate. Modify *src/lib.rs* to make the
618`client` module public, like so:
cc61c64b 619
7cac9316 620Filename: src/lib.rs
cc61c64b 621
7cac9316 622```
cc61c64b
XL
623pub mod client;
624
625mod network;
626```
627
7cac9316 628The `pub` keyword is placed right before `mod`. Let’s try building again:
cc61c64b 629
7cac9316 630```
abe05a73 631error[E0603]: function `connect` is private
cc61c64b
XL
632 --> src/main.rs:4:5
633 |
6344 | communicator::client::connect();
635 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
636```
637
638Hooray! We have a different error! Yes, different error messages are a cause
3b2f2976
XL
639for celebration. The new error shows `` function `connect` is private ``, so
640let’s edit *src/client.rs* to make `client::connect` public too:
cc61c64b 641
7cac9316 642Filename: src/client.rs
cc61c64b 643
7cac9316 644```
cc61c64b
XL
645pub fn connect() {
646}
647```
648
7cac9316 649Now run `cargo build` again:
cc61c64b 650
7cac9316 651```
abe05a73 652warning: function is never used: `connect`
cc61c64b
XL
653 --> src/network/mod.rs:1:1
654 |
abe05a73
XL
6551 | / fn connect() {
6562 | | }
657 | |_^
658 |
659 = note: #[warn(dead_code)] on by default
cc61c64b 660
abe05a73 661warning: function is never used: `connect`
cc61c64b
XL
662 --> src/network/server.rs:1:1
663 |
abe05a73
XL
6641 | / fn connect() {
6652 | | }
666 | |_^
cc61c64b
XL
667```
668
7cac9316
XL
669The code compiled, and the warning about `client::connect` not being used is
670gone!
cc61c64b 671
7cac9316
XL
672Unused code warnings don’t always indicate that an item in your code needs to
673be made public: if you *didn’t* want these functions to be part of your public
674API, unused code warnings could be alerting you to code you no longer need that
675you can safely delete. They could also be alerting you to a bug if you had just
cc61c64b
XL
676accidentally removed all places within your library where this function is
677called.
678
7cac9316
XL
679But in this case, we *do* want the other two functions to be part of our
680crate’s public API, so let’s mark them as `pub` as well to get rid of the
681remaining warnings. Modify *src/network/mod.rs* to look like the following:
cc61c64b 682
7cac9316 683Filename: src/network/mod.rs
cc61c64b 684
7cac9316 685```
cc61c64b
XL
686pub fn connect() {
687}
688
689mod server;
690```
691
7cac9316 692Then compile the code:
cc61c64b 693
7cac9316 694```
abe05a73 695warning: function is never used: `connect`
cc61c64b
XL
696 --> src/network/mod.rs:1:1
697 |
abe05a73
XL
6981 | / pub fn connect() {
6992 | | }
700 | |_^
701 |
702 = note: #[warn(dead_code)] on by default
cc61c64b 703
abe05a73 704warning: function is never used: `connect`
cc61c64b
XL
705 --> src/network/server.rs:1:1
706 |
abe05a73
XL
7071 | / fn connect() {
7082 | | }
709 | |_^
cc61c64b
XL
710```
711
7cac9316
XL
712Hmmm, we’re still getting an unused function warning, even though
713`network::connect` is set to `pub`. The reason is that the function is public
cc61c64b 714within the module, but the `network` module that the function resides in is not
7cac9316 715public. We’re working from the interior of the library out this time, whereas
cc61c64b 716with `client::connect` we worked from the outside in. We need to change
7cac9316 717*src/lib.rs* to make `network` public too, like so:
cc61c64b 718
7cac9316 719Filename: src/lib.rs
cc61c64b 720
7cac9316 721```
cc61c64b
XL
722pub mod client;
723
724pub mod network;
725```
726
7cac9316 727Now when we compile, that warning is gone:
cc61c64b 728
7cac9316 729```
abe05a73 730warning: function is never used: `connect`
cc61c64b
XL
731 --> src/network/server.rs:1:1
732 |
abe05a73
XL
7331 | / fn connect() {
7342 | | }
735 | |_^
736 |
737 = note: #[warn(dead_code)] on by default
cc61c64b
XL
738```
739
7cac9316 740Only one warning is left! Try to fix this one on your own!
cc61c64b
XL
741
742### Privacy Rules
743
744Overall, these are the rules for item visibility:
745
7461. If an item is public, it can be accessed through any of its parent modules.
3b2f2976
XL
7472. If an item is private, it can be accessed only by its immediate parent
748 module and any of the parent’s child modules.
cc61c64b
XL
749
750### Privacy Examples
751
7cac9316
XL
752Let’s look at a few more privacy examples to get some practice. Create a new
753library project and enter the code in Listing 7-5 into your new project’s
754*src/lib.rs*:
cc61c64b 755
7cac9316 756Filename: src/lib.rs
cc61c64b 757
7cac9316 758```
cc61c64b
XL
759mod outermost {
760 pub fn middle_function() {}
761
762 fn middle_secret_function() {}
763
764 mod inside {
765 pub fn inner_function() {}
766
767 fn secret_function() {}
768 }
769}
770
771fn try_me() {
772 outermost::middle_function();
773 outermost::middle_secret_function();
774 outermost::inside::inner_function();
775 outermost::inside::secret_function();
776}
777```
778
cc61c64b
XL
779Listing 7-5: Examples of private and public functions, some of which are
780incorrect
781
7cac9316
XL
782Before you try to compile this code, make a guess about which lines in the
783`try_me` function will have errors. Then, try compiling the code to see whether
784you were right, and read on for the discussion of the errors!
cc61c64b
XL
785
786#### Looking at the Errors
787
788The `try_me` function is in the root module of our project. The module named
7cac9316
XL
789`outermost` is private, but the second privacy rule states that the `try_me`
790function is allowed to access the `outermost` module because `outermost` is in
791the current (root) module, as is `try_me`.
cc61c64b 792
7cac9316
XL
793The call to `outermost::middle_function` will work because `middle_function` is
794public, and `try_me` is accessing `middle_function` through its parent module
795`outermost`. We determined in the previous paragraph that this module is
796accessible.
cc61c64b
XL
797
798The call to `outermost::middle_secret_function` will cause a compilation error.
799`middle_secret_function` is private, so the second rule applies. The root
800module is neither the current module of `middle_secret_function` (`outermost`
801is), nor is it a child module of the current module of `middle_secret_function`.
802
803The module named `inside` is private and has no child modules, so it can only
7cac9316
XL
804be accessed by its current module `outermost`. That means the `try_me` function
805is not allowed to call `outermost::inside::inner_function` or
806`outermost::inside::secret_function`.
cc61c64b
XL
807
808#### Fixing the Errors
809
810Here are some suggestions for changing the code in an attempt to fix the
811errors. Before you try each one, make a guess as to whether it will fix the
7cac9316
XL
812errors, and then compile the code to see whether or not you’re right, using the
813privacy rules to understand why.
cc61c64b
XL
814
815* What if the `inside` module was public?
816* What if `outermost` was public and `inside` was private?
817* What if, in the body of `inner_function`, you called
818 `::outermost::middle_secret_function()`? (The two colons at the beginning mean
819 that we want to refer to the modules starting from the root module.)
820
821Feel free to design more experiments and try them out!
822
7cac9316 823Next, let’s talk about bringing items into scope with the `use` keyword.
cc61c64b 824
abe05a73 825## Referring to Names in Different Modules
cc61c64b
XL
826
827We’ve covered how to call functions defined within a module using the module
828name as part of the call, as in the call to the `nested_modules` function shown
7cac9316 829here in Listing 7-6:
cc61c64b 830
7cac9316 831Filename: src/main.rs
cc61c64b 832
7cac9316 833```
cc61c64b
XL
834pub mod a {
835 pub mod series {
836 pub mod of {
837 pub fn nested_modules() {}
838 }
839 }
840}
841
842fn main() {
843 a::series::of::nested_modules();
844}
845```
846
7cac9316 847Listing 7-6: Calling a function by fully specifying its enclosing module’s path
cc61c64b
XL
848
849As you can see, referring to the fully qualified name can get quite lengthy.
7cac9316 850Fortunately, Rust has a keyword to make these calls more concise.
cc61c64b 851
abe05a73 852### Bringing Names into Scope with the `use` Keyword
cc61c64b 853
7cac9316
XL
854Rust’s `use` keyword shortens lengthy function calls by bringing the modules of
855the function you want to call into scope. Here’s an example of bringing the
856`a::series::of` module into a binary crate’s root scope:
cc61c64b 857
7cac9316 858Filename: src/main.rs
cc61c64b 859
7cac9316 860```
cc61c64b
XL
861pub mod a {
862 pub mod series {
863 pub mod of {
864 pub fn nested_modules() {}
865 }
866 }
867}
868
869use a::series::of;
870
871fn main() {
872 of::nested_modules();
873}
874```
875
876The line `use a::series::of;` means that rather than using the full
877`a::series::of` path wherever we want to refer to the `of` module, we can use
878`of`.
879
7cac9316
XL
880The `use` keyword brings only what we’ve specified into scope: it does not
881bring children of modules into scope. That’s why we still have to use
cc61c64b
XL
882`of::nested_modules` when we want to call the `nested_modules` function.
883
7cac9316
XL
884We could have chosen to bring the function into scope by instead specifying the
885function in the `use` as follows:
cc61c64b 886
7cac9316 887```
cc61c64b
XL
888pub mod a {
889 pub mod series {
890 pub mod of {
891 pub fn nested_modules() {}
892 }
893 }
894}
895
896use a::series::of::nested_modules;
897
898fn main() {
899 nested_modules();
900}
901```
902
7cac9316 903Doing so allows us to exclude all the modules and reference the function
cc61c64b
XL
904directly.
905
abe05a73
XL
906Because enums also form a sort of namespace like modules, we can bring an
907enum’s variants into scope with `use` as well. For any kind of `use` statement,
908if you’re bringing multiple items from one namespace into scope, you can list
909them using curly brackets and commas in the last position, like so:
cc61c64b 910
7cac9316 911```
cc61c64b
XL
912enum TrafficLight {
913 Red,
914 Yellow,
915 Green,
916}
917
918use TrafficLight::{Red, Yellow};
919
920fn main() {
921 let red = Red;
922 let yellow = Yellow;
7cac9316 923 let green = TrafficLight::Green;
cc61c64b
XL
924}
925```
926
3b2f2976
XL
927We’re still specifying the `TrafficLight` namespace for the `Green` variant
928because we didn’t include `Green` in the `use` statement.
7cac9316 929
abe05a73 930### Bringing All Names into Scope with a Glob
cc61c64b 931
abe05a73
XL
932To bring all the items in a namespace into scope at once, we can use the `*`
933syntax, which is called the *glob operator*. This example brings all the
934variants of an enum into scope without having to list each specifically:
cc61c64b 935
7cac9316 936```
cc61c64b
XL
937enum TrafficLight {
938 Red,
939 Yellow,
940 Green,
941}
942
943use TrafficLight::*;
944
945fn main() {
946 let red = Red;
947 let yellow = Yellow;
948 let green = Green;
949}
950```
951
abe05a73 952The `*` will bring into scope all the visible items in the `TrafficLight`
7cac9316
XL
953namespace. You should use globs sparingly: they are convenient, but this might
954also pull in more items than you expected and cause naming conflicts.
cc61c64b
XL
955
956### Using `super` to Access a Parent Module
957
7cac9316
XL
958As we saw at the beginning of this chapter, when you create a library crate,
959Cargo makes a `tests` module for you. Let’s go into more detail about that now.
960In your `communicator` project, open *src/lib.rs*:
cc61c64b 961
7cac9316 962Filename: src/lib.rs
cc61c64b 963
7cac9316 964```
cc61c64b
XL
965pub mod client;
966
967pub mod network;
968
969#[cfg(test)]
970mod tests {
971 #[test]
972 fn it_works() {
abe05a73 973 assert_eq!(2 + 2, 4);
cc61c64b
XL
974 }
975}
976```
977
7cac9316 978Chapter 11 explains more about testing, but parts of this example should make
cc61c64b
XL
979sense now: we have a module named `tests` that lives next to our other modules
980and contains one function named `it_works`. Even though there are special
981annotations, the `tests` module is just another module! So our module hierarchy
982looks like this:
983
7cac9316 984```
cc61c64b
XL
985communicator
986 ├── client
987 ├── network
988 | └── client
989 └── tests
990```
991
992Tests are for exercising the code within our library, so let’s try to call our
7cac9316 993`client::connect` function from this `it_works` function, even though we won’t
abe05a73 994be checking any functionality right now. This won't work yet:
cc61c64b 995
7cac9316 996Filename: src/lib.rs
cc61c64b 997
7cac9316 998```
cc61c64b
XL
999#[cfg(test)]
1000mod tests {
1001 #[test]
1002 fn it_works() {
1003 client::connect();
1004 }
1005}
1006```
1007
1008Run the tests by invoking the `cargo test` command:
1009
7cac9316 1010```
cc61c64b
XL
1011$ cargo test
1012 Compiling communicator v0.1.0 (file:///projects/communicator)
1013error[E0433]: failed to resolve. Use of undeclared type or module `client`
1014 --> src/lib.rs:9:9
1015 |
10169 | client::connect();
abe05a73 1017 | ^^^^^^ Use of undeclared type or module `client`
cc61c64b
XL
1018```
1019
1020The compilation failed, but why? We don’t need to place `communicator::` in
1021front of the function like we did in *src/main.rs* because we are definitely
1022within the `communicator` library crate here. The reason is that paths are
1023always relative to the current module, which here is `tests`. The only
1024exception is in a `use` statement, where paths are relative to the crate root
1025by default. Our `tests` module needs the `client` module in its scope!
1026
7cac9316
XL
1027So how do we get back up one module in the module hierarchy to call the
1028`client::connect` function in the `tests` module? In the `tests` module, we can
1029either use leading colons to let Rust know that we want to start from the root
1030and list the whole path, like this:
cc61c64b 1031
7cac9316 1032```
cc61c64b
XL
1033::client::connect();
1034```
1035
7cac9316
XL
1036Or, we can use `super` to move up one module in the hierarchy from our current
1037module, like this:
cc61c64b 1038
7cac9316 1039```
cc61c64b
XL
1040super::client::connect();
1041```
1042
7cac9316
XL
1043These two options don’t look that different in this example, but if you’re
1044deeper in a module hierarchy, starting from the root every time would make your
1045code lengthy. In those cases, using `super` to get from the current module to
1046sibling modules is a good shortcut. Plus, if you’ve specified the path from the
1047root in many places in your code and then you rearrange your modules by moving
1048a subtree to another place, you’d end up needing to update the path in several
1049places, which would be tedious.
cc61c64b 1050
7cac9316
XL
1051It would also be annoying to have to type `super::` in each test, but you’ve
1052already seen the tool for that solution: `use`! The `super::` functionality
1053changes the path you give to `use` so it is relative to the parent module
1054instead of to the root module.
cc61c64b
XL
1055
1056For these reasons, in the `tests` module especially, `use super::something` is
7cac9316 1057usually the best solution. So now our test looks like this:
cc61c64b 1058
7cac9316 1059Filename: src/lib.rs
cc61c64b 1060
7cac9316 1061```
cc61c64b
XL
1062#[cfg(test)]
1063mod tests {
1064 use super::client;
1065
1066 #[test]
1067 fn it_works() {
1068 client::connect();
1069 }
1070}
1071```
1072
7cac9316
XL
1073When we run `cargo test` again, the test will pass and the first part of the
1074test result output will be the following:
cc61c64b 1075
7cac9316 1076```
cc61c64b
XL
1077$ cargo test
1078 Compiling communicator v0.1.0 (file:///projects/communicator)
1079 Running target/debug/communicator-92007ddb5330fa5a
1080
1081running 1 test
1082test tests::it_works ... ok
1083
1084test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
1085```
1086
1087## Summary
1088
7cac9316
XL
1089Now you know some new techniques for organizing your code! Use these techniques
1090to group related functionality together, keep files from becoming too long, and
1091present a tidy public API to your library users.
1092
1093Next, we’ll look at some collection data structures in the standard library
1094that you can use in your nice, neat code!
cc61c64b 1095