]> git.proxmox.com Git - rustc.git/blob - src/doc/book/src/ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
New upstream version 1.61.0+dfsg1
[rustc.git] / src / doc / book / src / ch07-03-paths-for-referring-to-an-item-in-the-module-tree.md
1 ## Paths for Referring to an Item in the Module Tree
2
3 To show Rust where to find an item in a module tree, we use a path in the same
4 way we use a path when navigating a filesystem. If we want to call a function,
5 we need to know its path.
6
7 A path can take two forms:
8
9 * An *absolute path* starts from a crate root by using a crate name (for code
10 from an external crate) or a literal `crate` (for code from the current
11 crate).
12 * A *relative path* starts from the current module and uses `self`, `super`, or
13 an identifier in the current module.
14
15 Both absolute and relative paths are followed by one or more identifiers
16 separated by double colons (`::`).
17
18 Let’s return to the example in Listing 7-1. How do we call the
19 `add_to_waitlist` function? This is the same as asking, what’s the path of the
20 `add_to_waitlist` function? Listing 7-3 contains Listing 7-1 with some of the
21 modules and functions removed. We’ll show two ways to call the
22 `add_to_waitlist` function from a new function `eat_at_restaurant` defined in
23 the crate root. The `eat_at_restaurant` function is part of our library crate’s
24 public API, so we mark it with the `pub` keyword. In the [“Exposing Paths with
25 the `pub` Keyword”][pub]<!-- ignore --> section, we’ll go into more detail
26 about `pub`. Note that this example won’t compile just yet; we’ll explain why
27 in a bit.
28
29 <span class="filename">Filename: src/lib.rs</span>
30
31 ```rust,ignore,does_not_compile
32 {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-03/src/lib.rs}}
33 ```
34
35 <span class="caption">Listing 7-3: Calling the `add_to_waitlist` function using
36 absolute and relative paths</span>
37
38 The first time we call the `add_to_waitlist` function in `eat_at_restaurant`,
39 we use an absolute path. The `add_to_waitlist` function is defined in the same
40 crate as `eat_at_restaurant`, which means we can use the `crate` keyword to
41 start an absolute path.
42
43 After `crate`, we include each of the successive modules until we make our way
44 to `add_to_waitlist`. You can imagine a filesystem with the same structure, and
45 we’d specify the path `/front_of_house/hosting/add_to_waitlist` to run the
46 `add_to_waitlist` program; using the `crate` name to start from the crate root
47 is like using `/` to start from the filesystem root in your shell.
48
49 The second time we call `add_to_waitlist` in `eat_at_restaurant`, we use a
50 relative path. The path starts with `front_of_house`, the name of the module
51 defined at the same level of the module tree as `eat_at_restaurant`. Here the
52 filesystem equivalent would be using the path
53 `front_of_house/hosting/add_to_waitlist`. Starting with a name means that the
54 path is relative.
55
56 Choosing whether to use a relative or absolute path is a decision you’ll make
57 based on your project. The decision should depend on whether you’re more likely
58 to move item definition code separately from or together with the code that
59 uses the item. For example, if we move the `front_of_house` module and the
60 `eat_at_restaurant` function into a module named `customer_experience`, we’d
61 need to update the absolute path to `add_to_waitlist`, but the relative path
62 would still be valid. However, if we moved the `eat_at_restaurant` function
63 separately into a module named `dining`, the absolute path to the
64 `add_to_waitlist` call would stay the same, but the relative path would need to
65 be updated. Our preference is to specify absolute paths because it’s more
66 likely we’ll want to move code definitions and item calls independently of each
67 other.
68
69 Let’s try to compile Listing 7-3 and find out why it won’t compile yet! The
70 error we get is shown in Listing 7-4.
71
72 ```console
73 {{#include ../listings/ch07-managing-growing-projects/listing-07-03/output.txt}}
74 ```
75
76 <span class="caption">Listing 7-4: Compiler errors from building the code in
77 Listing 7-3</span>
78
79 The error messages say that module `hosting` is private. In other words, we
80 have the correct paths for the `hosting` module and the `add_to_waitlist`
81 function, but Rust won’t let us use them because it doesn’t have access to the
82 private sections.
83
84 Modules aren’t useful only for organizing your code. They also define Rust’s
85 *privacy boundary*: the line that encapsulates the implementation details
86 external code isn’t allowed to know about, call, or rely on. So, if you want to
87 make an item like a function or struct private, you put it in a module.
88
89 The way privacy works in Rust is that all items (functions, methods, structs,
90 enums, modules, and constants) are private by default. Items in a parent module
91 can’t use the private items inside child modules, but items in child modules
92 can use the items in their ancestor modules. The reason is that child modules
93 wrap and hide their implementation details, but the child modules can see the
94 context in which they’re defined. To continue with the restaurant metaphor,
95 think of the privacy rules as being like the back office of a restaurant: what
96 goes on in there is private to restaurant customers, but office managers can
97 see and do everything in the restaurant in which they operate.
98
99 Rust chose to have the module system function this way so that hiding inner
100 implementation details is the default. That way, you know which parts of the
101 inner code you can change without breaking outer code. But you can expose inner
102 parts of child modules’ code to outer ancestor modules by using the `pub`
103 keyword to make an item public.
104
105 ### Exposing Paths with the `pub` Keyword
106
107 Let’s return to the error in Listing 7-4 that told us the `hosting` module is
108 private. We want the `eat_at_restaurant` function in the parent module to have
109 access to the `add_to_waitlist` function in the child module, so we mark the
110 `hosting` module with the `pub` keyword, as shown in Listing 7-5.
111
112 <span class="filename">Filename: src/lib.rs</span>
113
114 ```rust,ignore,does_not_compile
115 {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-05/src/lib.rs}}
116 ```
117
118 <span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` to
119 use it from `eat_at_restaurant`</span>
120
121 Unfortunately, the code in Listing 7-5 still results in an error, as shown in
122 Listing 7-6.
123
124 ```console
125 {{#include ../listings/ch07-managing-growing-projects/listing-07-05/output.txt}}
126 ```
127
128 <span class="caption">Listing 7-6: Compiler errors from building the code in
129 Listing 7-5</span>
130
131 What happened? Adding the `pub` keyword in front of `mod hosting` makes the
132 module public. With this change, if we can access `front_of_house`, we can
133 access `hosting`. But the *contents* of `hosting` are still private; making the
134 module public doesn’t make its contents public. The `pub` keyword on a module
135 only lets code in its ancestor modules refer to it.
136
137 The errors in Listing 7-6 say that the `add_to_waitlist` function is private.
138 The privacy rules apply to structs, enums, functions, and methods as well as
139 modules.
140
141 Let’s also make the `add_to_waitlist` function public by adding the `pub`
142 keyword before its definition, as in Listing 7-7.
143
144 <span class="filename">Filename: src/lib.rs</span>
145
146 ```rust,noplayground,test_harness
147 {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-07/src/lib.rs}}
148 ```
149
150 <span class="caption">Listing 7-7: Adding the `pub` keyword to `mod hosting`
151 and `fn add_to_waitlist` lets us call the function from
152 `eat_at_restaurant`</span>
153
154 Now the code will compile! Let’s look at the absolute and the relative path and
155 double-check why adding the `pub` keyword lets us use these paths in
156 `add_to_waitlist` with respect to the privacy rules.
157
158 In the absolute path, we start with `crate`, the root of our crate’s module
159 tree. Then the `front_of_house` module is defined in the crate root. The
160 `front_of_house` module isn’t public, but because the `eat_at_restaurant`
161 function is defined in the same module as `front_of_house` (that is,
162 `eat_at_restaurant` and `front_of_house` are siblings), we can refer to
163 `front_of_house` from `eat_at_restaurant`. Next is the `hosting` module marked
164 with `pub`. We can access the parent module of `hosting`, so we can access
165 `hosting`. Finally, the `add_to_waitlist` function is marked with `pub` and we
166 can access its parent module, so this function call works!
167
168 In the relative path, the logic is the same as the absolute path except for the
169 first step: rather than starting from the crate root, the path starts from
170 `front_of_house`. The `front_of_house` module is defined within the same module
171 as `eat_at_restaurant`, so the relative path starting from the module in which
172 `eat_at_restaurant` is defined works. Then, because `hosting` and
173 `add_to_waitlist` are marked with `pub`, the rest of the path works, and this
174 function call is valid!
175
176 If you plan on sharing your library crate so other projects can use your code,
177 your public API is your contract with users of your crate about how they
178 interact with your code. There are many considerations around managing changes
179 to your public API to make it easier for people to depend on your crate. These
180 considerations are out of the scope of this book; if you’re interested in this
181 topic, see [The Rust API Guidelines][api-guidelines].
182
183 > #### Best Practices for Packages with a Binary and a Library
184 >
185 > We mentioned a package can contain both a *src/main.rs* binary crate root as
186 > well as a *src/lib.rs* library crate root, and both crates will have the
187 > package name by default. Typically, packages with this pattern will have just
188 > enough code in the binary crate to start an executable that calls code with
189 > the library crate. This lets other projects benefit from the most
190 > functionality that the package provides, because the library crate’s code can
191 > be shared.
192 >
193 > The module tree should be defined in *src/lib.rs*. Then, any public items can
194 > be used in the binary crate by starting paths with the name of the package.
195 > The binary crate becomes a user of the library crate just like a completely
196 > external crate would use the library crate: it can only use the public API.
197 > This helps you design a good API; not only are you the author, you’re also a
198 > client!
199 >
200 > In [Chapter 12][ch12]<!-- ignore -->, we’ll demonstrate this organizational
201 > practice with a command-line program that will contain both a binary crate
202 > and a library crate.
203
204 ### Starting Relative Paths with `super`
205
206 We can also construct relative paths that begin in the parent module by using
207 `super` at the start of the path. This is like starting a filesystem path with
208 the `..` syntax. Why would we want to do this?
209
210 Consider the code in Listing 7-8 that models the situation in which a chef
211 fixes an incorrect order and personally brings it out to the customer. The
212 function `fix_incorrect_order` defined in the `back_of_house` module calls the
213 function `deliver_order` defined in the parent module by specifying the path to
214 `deliver_order` starting with `super`:
215
216 <span class="filename">Filename: src/lib.rs</span>
217
218 ```rust,noplayground,test_harness
219 {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-08/src/lib.rs}}
220 ```
221
222 <span class="caption">Listing 7-8: Calling a function using a relative path
223 starting with `super`</span>
224
225 The `fix_incorrect_order` function is in the `back_of_house` module, so we can
226 use `super` to go to the parent module of `back_of_house`, which in this case
227 is `crate`, the root. From there, we look for `deliver_order` and find it.
228 Success! We think the `back_of_house` module and the `deliver_order` function
229 are likely to stay in the same relationship to each other and get moved
230 together should we decide to reorganize the crate’s module tree. Therefore, we
231 used `super` so we’ll have fewer places to update code in the future if this
232 code gets moved to a different module.
233
234 ### Making Structs and Enums Public
235
236 We can also use `pub` to designate structs and enums as public, but there are a
237 few extra details. If we use `pub` before a struct definition, we make the
238 struct public, but the struct’s fields will still be private. We can make each
239 field public or not on a case-by-case basis. In Listing 7-9, we’ve defined a
240 public `back_of_house::Breakfast` struct with a public `toast` field but a
241 private `seasonal_fruit` field. This models the case in a restaurant where the
242 customer can pick the type of bread that comes with a meal, but the chef
243 decides which fruit accompanies the meal based on what’s in season and in
244 stock. The available fruit changes quickly, so customers can’t choose the fruit
245 or even see which fruit they’ll get.
246
247 <span class="filename">Filename: src/lib.rs</span>
248
249 ```rust,noplayground
250 {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-09/src/lib.rs}}
251 ```
252
253 <span class="caption">Listing 7-9: A struct with some public fields and some
254 private fields</span>
255
256 Because the `toast` field in the `back_of_house::Breakfast` struct is public,
257 in `eat_at_restaurant` we can write and read to the `toast` field using dot
258 notation. Notice that we can’t use the `seasonal_fruit` field in
259 `eat_at_restaurant` because `seasonal_fruit` is private. Try uncommenting the
260 line modifying the `seasonal_fruit` field value to see what error you get!
261
262 Also, note that because `back_of_house::Breakfast` has a private field, the
263 struct needs to provide a public associated function that constructs an
264 instance of `Breakfast` (we’ve named it `summer` here). If `Breakfast` didn’t
265 have such a function, we couldn’t create an instance of `Breakfast` in
266 `eat_at_restaurant` because we couldn’t set the value of the private
267 `seasonal_fruit` field in `eat_at_restaurant`.
268
269 In contrast, if we make an enum public, all of its variants are then public. We
270 only need the `pub` before the `enum` keyword, as shown in Listing 7-10.
271
272 <span class="filename">Filename: src/lib.rs</span>
273
274 ```rust,noplayground
275 {{#rustdoc_include ../listings/ch07-managing-growing-projects/listing-07-10/src/lib.rs}}
276 ```
277
278 <span class="caption">Listing 7-10: Designating an enum as public makes all its
279 variants public</span>
280
281 Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
282 variants in `eat_at_restaurant`. Enums aren’t very useful unless their variants
283 are public; it would be annoying to have to annotate all enum variants with
284 `pub` in every case, so the default for enum variants is to be public. Structs
285 are often useful without their fields being public, so struct fields follow the
286 general rule of everything being private by default unless annotated with `pub`.
287
288 There’s one more situation involving `pub` that we haven’t covered, and that is
289 our last module system feature: the `use` keyword. We’ll cover `use` by itself
290 first, and then we’ll show how to combine `pub` and `use`.
291
292 [pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword
293 [api-guidelines]: https://rust-lang.github.io/api-guidelines/
294 [ch12]: ch12-00-an-io-project.html