]> 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.38.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 or a
10 literal `crate`.
11 * A *relative path* starts from the current module and uses `self`, `super`, or
12 an identifier in the current module.
13
14 Both absolute and relative paths are followed by one or more identifiers
15 separated by double colons (`::`).
16
17 Let’s return to the example in Listing 7-1. How do we call the
18 `add_to_waitlist` function? This is the same as asking, what’s the path of the
19 `add_to_waitlist` function? In Listing 7-3, we simplified our code a bit by
20 removing some of the modules and functions. We’ll show two ways to call the
21 `add_to_waitlist` function from a new function `eat_at_restaurant` defined in
22 the crate root. The `eat_at_restaurant` function is part of our library crate’s
23 public API, so we mark it with the `pub` keyword. In the [”Exposing Paths with
24 the `pub` Keyword”][pub]<!-- ignore --> section, we’ll go into more detail
25 about `pub`. Note that this example won’t compile just yet; we’ll explain why
26 in a bit.
27
28 <span class="filename">Filename: src/lib.rs</span>
29
30 ```rust,ignore,does_not_compile
31 mod front_of_house {
32 mod hosting {
33 fn add_to_waitlist() {}
34 }
35 }
36
37 pub fn eat_at_restaurant() {
38 // Absolute path
39 crate::front_of_house::hosting::add_to_waitlist();
40
41 // Relative path
42 front_of_house::hosting::add_to_waitlist();
43 }
44 ```
45
46 <span class="caption">Listing 7-3: Calling the `add_to_waitlist` function using
47 absolute and relative paths</span>
48
49 The first time we call the `add_to_waitlist` function in `eat_at_restaurant`,
50 we use an absolute path. The `add_to_waitlist` function is defined in the same
51 crate as `eat_at_restaurant`, which means we can use the `crate` keyword to
52 start an absolute path.
53
54 After `crate`, we include each of the successive modules until we make our way
55 to `add_to_waitlist`. You can imagine a filesystem with the same structure, and
56 we’d specify the path `/front_of_house/hosting/add_to_waitlist` to run the
57 `add_to_waitlist` program; using the `crate` name to start from the crate root
58 is like using `/` to start from the filesystem root in your shell.
59
60 The second time we call `add_to_waitlist` in `eat_at_restaurant`, we use a
61 relative path. The path starts with `front_of_house`, the name of the module
62 defined at the same level of the module tree as `eat_at_restaurant`. Here the
63 filesystem equivalent would be using the path
64 `front_of_house/hosting/add_to_waitlist`. Starting with a name means that the
65 path is relative.
66
67 Choosing whether to use a relative or absolute path is a decision you’ll make
68 based on your project. The decision should depend on whether you’re more likely
69 to move item definition code separately from or together with the code that
70 uses the item. For example, if we move the `front_of_house` module and the
71 `eat_at_restaurant` function into a module named `customer_experience`, we’d
72 need to update the absolute path to `add_to_waitlist`, but the relative path
73 would still be valid. However, if we moved the `eat_at_restaurant` function
74 separately into a module named `dining`, the absolute path to the
75 `add_to_waitlist` call would stay the same, but the relative path would need to
76 be updated. Our preference is to specify absolute paths because it’s more
77 likely to move code definitions and item calls independently of each other.
78
79 Let’s try to compile Listing 7-3 and find out why it won’t compile yet! The
80 error we get is shown in Listing 7-4.
81
82 ```text
83 $ cargo build
84 Compiling restaurant v0.1.0 (file:///projects/restaurant)
85 error[E0603]: module `hosting` is private
86 --> src/lib.rs:9:28
87 |
88 9 | crate::front_of_house::hosting::add_to_waitlist();
89 | ^^^^^^^
90
91 error[E0603]: module `hosting` is private
92 --> src/lib.rs:12:21
93 |
94 12 | front_of_house::hosting::add_to_waitlist();
95 | ^^^^^^^
96 ```
97
98 <span class="caption">Listing 7-4: Compiler errors from building the code in
99 Listing 7-3</span>
100
101 The error messages say that module `hosting` is private. In other words, we
102 have the correct paths for the `hosting` module and the `add_to_waitlist`
103 function, but Rust won’t let us use them because it doesn’t have access to the
104 private sections.
105
106 Modules aren’t useful only for organizing your code. They also define Rust’s
107 *privacy boundary*: the line that encapsulates the implementation details
108 external code isn’t allowed to know about, call, or rely on. So, if you want to
109 make an item like a function or struct private, you put it in a module.
110
111 The way privacy works in Rust is that all items (functions, methods, structs,
112 enums, modules, and constants) are private by default. Items in a parent module
113 can’t use the private items inside child modules, but items in child modules
114 can use the items in their ancestor modules. The reason is that child modules
115 wrap and hide their implementation details, but the child modules can see the
116 context in which they’re defined. To continue with the restaurant metaphor,
117 think of the privacy rules as being like the back office of a restaurant: what
118 goes on in there is private to restaurant customers, but office managers can
119 see and do everything in the restaurant in which they operate.
120
121 Rust chose to have the module system function this way so that hiding inner
122 implementation details is the default. That way, you know which parts of the
123 inner code you can change without breaking outer code. But you can expose inner
124 parts of child modules code to outer ancestor modules by using the `pub`
125 keyword to make an item public.
126
127 ### Exposing Paths with the `pub` Keyword
128
129 Let’s return to the error in Listing 7-4 that told us the `hosting` module is
130 private. We want the `eat_at_restaurant` function in the parent module to have
131 access to the `add_to_waitlist` function in the child module, so we mark the
132 `hosting` module with the `pub` keyword, as shown in Listing 7-5.
133
134 <span class="filename">Filename: src/lib.rs</span>
135
136 ```rust,ignore,does_not_compile
137 mod front_of_house {
138 pub mod hosting {
139 fn add_to_waitlist() {}
140 }
141 }
142
143 pub fn eat_at_restaurant() {
144 // Absolute path
145 crate::front_of_house::hosting::add_to_waitlist();
146
147 // Relative path
148 front_of_house::hosting::add_to_waitlist();
149 }
150 ```
151
152 <span class="caption">Listing 7-5: Declaring the `hosting` module as `pub` to
153 use it from `eat_at_restaurant`</span>
154
155 Unfortunately, the code in Listing 7-5 still results in an error, as shown in
156 Listing 7-6.
157
158 ```text
159 $ cargo build
160 Compiling restaurant v0.1.0 (file:///projects/restaurant)
161 error[E0603]: function `add_to_waitlist` is private
162 --> src/lib.rs:9:37
163 |
164 9 | crate::front_of_house::hosting::add_to_waitlist();
165 | ^^^^^^^^^^^^^^^
166
167 error[E0603]: function `add_to_waitlist` is private
168 --> src/lib.rs:12:30
169 |
170 12 | front_of_house::hosting::add_to_waitlist();
171 | ^^^^^^^^^^^^^^^
172 ```
173
174 <span class="caption">Listing 7-6: Compiler errors from building the code in
175 Listing 7-5</span>
176
177 What happened? Adding the `pub` keyword in front of `mod hosting` makes the
178 module public. With this change, if we can access `front_of_house`, we can
179 access `hosting`. But the *contents* of `hosting` are still private; making the
180 module public doesn’t make its contents public. The `pub` keyword on a module
181 only lets code in its ancestor modules refer to it.
182
183 The errors in Listing 7-6 say that the `add_to_waitlist` function is private.
184 The privacy rules apply to structs, enums, functions, and methods as well as
185 modules.
186
187 Let’s also make the `add_to_waitlist` function public by adding the `pub`
188 keyword before its definition, as in Listing 7-7.
189
190 <span class="filename">Filename: src/lib.rs</span>
191
192 ```rust
193 mod front_of_house {
194 pub mod hosting {
195 pub fn add_to_waitlist() {}
196 }
197 }
198
199 pub fn eat_at_restaurant() {
200 // Absolute path
201 crate::front_of_house::hosting::add_to_waitlist();
202
203 // Relative path
204 front_of_house::hosting::add_to_waitlist();
205 }
206 # fn main() {}
207 ```
208
209 <span class="caption">Listing 7-7: Adding the `pub` keyword to `mod hosting`
210 and `fn add_to_waitlist` lets us call the function from
211 `eat_at_restaurant`</span>
212
213 Now the code will compile! Let’s look at the absolute and the relative path and
214 double-check why adding the `pub` keyword lets us use these paths in
215 `add_to_waitlist` with respect to the privacy rules.
216
217 In the absolute path, we start with `crate`, the root of our crate’s module
218 tree. Then the `front_of_house` module is defined in the crate root. The
219 `front_of_house` module isn’t public, but because the `eat_at_restaurant`
220 function is defined in the same module as `front_of_house` (that is,
221 `eat_at_restaurant` and `front_of_house` are siblings), we can refer to
222 `front_of_house` from `eat_at_restaurant`. Next is the `hosting` module marked
223 with `pub`. We can access the parent module of `hosting`, so we can access
224 `hosting`. Finally, the `add_to_waitlist` function is marked with `pub` and we
225 can access its parent module, so this function call works!
226
227 In the relative path, the logic is the same as the absolute path except for the
228 first step: rather than starting from the crate root, the path starts from
229 `front_of_house`. The `front_of_house` module is defined within the same module
230 as `eat_at_restaurant`, so the relative path starting from the module in which
231 `eat_at_restaurant` is defined works. Then, because `hosting` and
232 `add_to_waitlist` are marked with `pub`, the rest of the path works, and this
233 function call is valid!
234
235 ### Starting Relative Paths with `super`
236
237 We can also construct relative paths that begin in the parent module by using
238 `super` at the start of the path. This is like starting a filesystem path with
239 the `..` syntax. Why would we want to do this?
240
241 Consider the code in Listing 7-8 that models the situation in which a chef
242 fixes an incorrect order and personally brings it out to the customer. The
243 function `fix_incorrect_order` calls the function `serve_order` by specifying
244 the path to `serve_order` starting with `super`:
245
246 <span class="filename">Filename: src/lib.rs</span>
247
248 ```rust
249 fn serve_order() {}
250
251 mod back_of_house {
252 fn fix_incorrect_order() {
253 cook_order();
254 super::serve_order();
255 }
256
257 fn cook_order() {}
258 }
259 # fn main() {}
260 ```
261
262 <span class="caption">Listing 7-8: Calling a function using a relative path
263 starting with `super`</span>
264
265 The `fix_incorrect_order` function is in the `back_of_house` module, so we can
266 use `super` to go to the parent module of `back_of_house`, which in this case
267 is `crate`, the root. From there, we look for `serve_order` and find it.
268 Success! We think the `back_of_house` module and the `serve_order` function are
269 likely to stay in the same relationship to each other and get moved together
270 should we decide to reorganize the crate’s module tree. Therefore, we used
271 `super` so we’ll have fewer places to update code in the future if this code
272 gets moved to a different module.
273
274 ### Making Structs and Enums Public
275
276 We can also use `pub` to designate structs and enums as public, but there are a
277 few extra details. If we use `pub` before a struct definition, we make the
278 struct public, but the struct’s fields will still be private. We can make each
279 field public or not on a case-by-case basis. In Listing 7-9, we’ve defined a
280 public `back_of_house::Breakfast` struct with a public `toast` field but a
281 private `seasonal_fruit` field. This models the case in a restaurant where the
282 customer can pick the type of bread that comes with a meal, but the chef
283 decides which fruit accompanies the meal based on what’s in season and in
284 stock. The available fruit changes quickly, so customers can’t choose the fruit
285 or even see which fruit they’ll get.
286
287 <span class="filename">Filename: src/lib.rs</span>
288
289 ```rust
290 mod back_of_house {
291 pub struct Breakfast {
292 pub toast: String,
293 seasonal_fruit: String,
294 }
295
296 impl Breakfast {
297 pub fn summer(toast: &str) -> Breakfast {
298 Breakfast {
299 toast: String::from(toast),
300 seasonal_fruit: String::from("peaches"),
301 }
302 }
303 }
304 }
305
306 pub fn eat_at_restaurant() {
307 // Order a breakfast in the summer with Rye toast
308 let mut meal = back_of_house::Breakfast::summer("Rye");
309 // Change our mind about what bread we'd like
310 meal.toast = String::from("Wheat");
311 println!("I'd like {} toast please", meal.toast);
312
313 // The next line won't compile if we uncomment it; we're not allowed
314 // to see or modify the seasonal fruit that comes with the meal
315 // meal.seasonal_fruit = String::from("blueberries");
316 }
317 ```
318
319 <span class="caption">Listing 7-9: A struct with some public fields and some
320 private fields</span>
321
322 Because the `toast` field in the `back_of_house::Breakfast` struct is public,
323 in `eat_at_restaurant` we can write and read to the `toast` field using dot
324 notation. Notice that we can’t use the `seasonal_fruit` field in
325 `eat_at_restaurant` because `seasonal_fruit` is private. Try uncommenting the
326 line modifying the `seasonal_fruit` field value to see what error you get!
327
328 Also, note that because `back_of_house::Breakfast` has a private field, the
329 struct needs to provide a public associated function that constructs an
330 instance of `Breakfast` (we’ve named it `summer` here). If `Breakfast` didn’t
331 have such a function, we couldn’t create an instance of `Breakfast` in
332 `eat_at_restaurant` because we couldn’t set the value of the private
333 `seasonal_fruit` field in `eat_at_restaurant`.
334
335 In contrast, if we make an enum public, all of its variants are then public. We
336 only need the `pub` before the `enum` keyword, as shown in Listing 7-10.
337
338 <span class="filename">Filename: src/lib.rs</span>
339
340 ```rust
341 mod back_of_house {
342 pub enum Appetizer {
343 Soup,
344 Salad,
345 }
346 }
347
348 pub fn eat_at_restaurant() {
349 let order1 = back_of_house::Appetizer::Soup;
350 let order2 = back_of_house::Appetizer::Salad;
351 }
352 ```
353
354 <span class="caption">Listing 7-10: Designating an enum as public makes all its
355 variants public</span>
356
357 Because we made the `Appetizer` enum public, we can use the `Soup` and `Salad`
358 variants in `eat_at_restaurant`. Enums aren’t very useful unless their variants
359 are public; it would be annoying to have to annotate all enum variants with
360 `pub` in every case, so the default for enum variants is to be public. Structs
361 are often useful without their fields being public, so struct fields follow the
362 general rule of everything being private by default unless annotated with `pub`.
363
364 There’s one more situation involving `pub` that we haven’t covered, and that is
365 our last module system feature: the `use` keyword. We’ll cover `use` by itself
366 first, and then we’ll show how to combine `pub` and `use`.
367
368 [pub]: ch07-03-paths-for-referring-to-an-item-in-the-module-tree.html#exposing-paths-with-the-pub-keyword