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