]> git.proxmox.com Git - rustc.git/blame - src/doc/book/second-edition/src/ch07-02-controlling-visibility-with-pub.md
New upstream version 1.23.0+dfsg1
[rustc.git] / src / doc / book / second-edition / src / ch07-02-controlling-visibility-with-pub.md
CommitLineData
cc61c64b
XL
1## Controlling Visibility with `pub`
2
3We resolved the error messages shown in Listing 7-4 by moving the `network` and
4`network::server` code into the *src/network/mod.rs* and
5*src/network/server.rs* files, respectively. At that point, `cargo build` was
7cac9316 6able to build our project, but we still get warning messages about the
cc61c64b
XL
7`client::connect`, `network::connect`, and `network::server::connect` functions
8not being used:
9
10```text
abe05a73
XL
11warning: function is never used: `connect`
12 --> src/client.rs:1:1
cc61c64b 13 |
abe05a73
XL
141 | / fn connect() {
152 | | }
16 | |_^
17 |
18 = note: #[warn(dead_code)] on by default
cc61c64b 19
abe05a73 20warning: function is never used: `connect`
cc61c64b
XL
21 --> src/network/mod.rs:1:1
22 |
abe05a73
XL
231 | / fn connect() {
242 | | }
25 | |_^
cc61c64b 26
abe05a73 27warning: function is never used: `connect`
cc61c64b
XL
28 --> src/network/server.rs:1:1
29 |
abe05a73
XL
301 | / fn connect() {
312 | | }
32 | |_^
cc61c64b
XL
33```
34
35So why are we receiving these warnings? After all, we’re building a library
7cac9316
XL
36with functions that are intended to be used by our *users*, not necessarily by
37us within our own project, so it shouldn’t matter that these `connect`
cc61c64b 38functions go unused. The point of creating them is that they will be used by
7cac9316 39another project, not our own.
cc61c64b
XL
40
41To understand why this program invokes these warnings, let’s try using the
7cac9316
XL
42`connect` library from another project, calling it externally. To do that,
43we’ll create a binary crate in the same directory as our library crate by
44making a *src/main.rs* file containing this code:
cc61c64b
XL
45
46<span class="filename">Filename: src/main.rs</span>
47
48```rust,ignore
49extern crate communicator;
50
51fn main() {
52 communicator::client::connect();
53}
54```
55
56We use the `extern crate` command to bring the `communicator` library crate
7cac9316
XL
57into scope. Our package now contains *two* crates. Cargo treats *src/main.rs*
58as the root file of a binary crate, which is separate from the existing library
59crate whose root file is *src/lib.rs*. This pattern is quite common for
60executable projects: most functionality is in a library crate, and the binary
61crate uses that library crate. As a result, other programs can also use the
62library crate, and it’s a nice separation of concerns.
63
64From the point of view of a crate outside the `communicator` library looking
65in, all the modules we’ve been creating are within a module that has the same
66name as the crate, `communicator`. We call the top-level module of a crate the
67*root module*.
68
69Also note that even if we’re using an external crate within a submodule of our
cc61c64b
XL
70project, the `extern crate` should go in our root module (so in *src/main.rs*
71or *src/lib.rs*). Then, in our submodules, we can refer to items from external
72crates as if the items are top-level modules.
73
7cac9316
XL
74Right now, our binary crate just calls our library’s `connect` function from
75the `client` module. However, invoking `cargo build` will now give us an error
cc61c64b
XL
76after the warnings:
77
78```text
abe05a73 79error[E0603]: module `client` is private
cc61c64b
XL
80 --> src/main.rs:4:5
81 |
824 | communicator::client::connect();
83 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
84```
85
7cac9316
XL
86Ah ha! This error tells us that the `client` module is private, which is the
87crux of the warnings. It’s also the first time we’ve run into the concepts of
cc61c64b
XL
88*public* and *private* in the context of Rust. The default state of all code in
89Rust is private: no one else is allowed to use the code. If you don’t use a
7cac9316
XL
90private function within your program, because your program is the only code
91allowed to use that function, Rust will warn you that the function has gone
92unused.
93
94After we specify that a function like `client::connect` is public, not only
95will our call to that function from our binary crate be allowed, but the
96warning that the function is unused will go away. Marking a function as public
97lets Rust know that the function will be used by code outside of our program.
98Rust considers the theoretical external usage that’s now possible as the
abe05a73
XL
99function “being used.” Thus, when a function is marked public, Rust will not
100require that it be used in our program and will stop warning that the function
101is unused.
cc61c64b
XL
102
103### Making a Function Public
104
abe05a73
XL
105To tell Rust to make a function public, we add the `pub` keyword to the start
106of the declaration. We’ll focus on fixing the warning that indicates
107`client::connect` has gone unused for now, as well as the `` module `client` is
108private `` error from our binary crate. Modify *src/lib.rs* to make the
109`client` module public, like so:
cc61c64b
XL
110
111<span class="filename">Filename: src/lib.rs</span>
112
113```rust,ignore
114pub mod client;
115
116mod network;
117```
118
7cac9316 119The `pub` keyword is placed right before `mod`. Let’s try building again:
cc61c64b
XL
120
121```text
abe05a73 122error[E0603]: function `connect` is private
cc61c64b
XL
123 --> src/main.rs:4:5
124 |
1254 | communicator::client::connect();
126 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127```
128
129Hooray! We have a different error! Yes, different error messages are a cause
7cac9316
XL
130for celebration. The new error shows `` function `connect` is private ``, so
131let’s edit *src/client.rs* to make `client::connect` public too:
cc61c64b
XL
132
133<span class="filename">Filename: src/client.rs</span>
134
135```rust
136pub fn connect() {
137}
138```
139
7cac9316 140Now run `cargo build` again:
cc61c64b
XL
141
142```text
abe05a73 143warning: function is never used: `connect`
cc61c64b
XL
144 --> src/network/mod.rs:1:1
145 |
abe05a73
XL
1461 | / fn connect() {
1472 | | }
148 | |_^
149 |
150 = note: #[warn(dead_code)] on by default
cc61c64b 151
abe05a73 152warning: function is never used: `connect`
cc61c64b
XL
153 --> src/network/server.rs:1:1
154 |
abe05a73
XL
1551 | / fn connect() {
1562 | | }
157 | |_^
cc61c64b
XL
158```
159
7cac9316
XL
160The code compiled, and the warning about `client::connect` not being used is
161gone!
cc61c64b 162
7cac9316
XL
163Unused code warnings don’t always indicate that an item in your code needs to
164be made public: if you *didn’t* want these functions to be part of your public
165API, unused code warnings could be alerting you to code you no longer need that
166you can safely delete. They could also be alerting you to a bug if you had just
cc61c64b
XL
167accidentally removed all places within your library where this function is
168called.
169
7cac9316
XL
170But in this case, we *do* want the other two functions to be part of our
171crate’s public API, so let’s mark them as `pub` as well to get rid of the
172remaining warnings. Modify *src/network/mod.rs* to look like the following:
cc61c64b
XL
173
174<span class="filename">Filename: src/network/mod.rs</span>
175
176```rust,ignore
177pub fn connect() {
178}
179
180mod server;
181```
182
7cac9316 183Then compile the code:
cc61c64b
XL
184
185```text
abe05a73 186warning: function is never used: `connect`
cc61c64b
XL
187 --> src/network/mod.rs:1:1
188 |
abe05a73
XL
1891 | / pub fn connect() {
1902 | | }
191 | |_^
192 |
193 = note: #[warn(dead_code)] on by default
cc61c64b 194
abe05a73 195warning: function is never used: `connect`
cc61c64b
XL
196 --> src/network/server.rs:1:1
197 |
abe05a73
XL
1981 | / fn connect() {
1992 | | }
200 | |_^
cc61c64b
XL
201```
202
7cac9316
XL
203Hmmm, we’re still getting an unused function warning, even though
204`network::connect` is set to `pub`. The reason is that the function is public
cc61c64b 205within the module, but the `network` module that the function resides in is not
7cac9316 206public. We’re working from the interior of the library out this time, whereas
cc61c64b 207with `client::connect` we worked from the outside in. We need to change
7cac9316 208*src/lib.rs* to make `network` public too, like so:
cc61c64b
XL
209
210<span class="filename">Filename: src/lib.rs</span>
211
212```rust,ignore
213pub mod client;
214
215pub mod network;
216```
217
7cac9316 218Now when we compile, that warning is gone:
cc61c64b
XL
219
220```text
abe05a73 221warning: function is never used: `connect`
cc61c64b
XL
222 --> src/network/server.rs:1:1
223 |
abe05a73
XL
2241 | / fn connect() {
2252 | | }
226 | |_^
227 |
228 = note: #[warn(dead_code)] on by default
cc61c64b
XL
229```
230
7cac9316 231Only one warning is left! Try to fix this one on your own!
cc61c64b
XL
232
233### Privacy Rules
234
235Overall, these are the rules for item visibility:
236
2371. If an item is public, it can be accessed through any of its parent modules.
3b2f2976
XL
2382. If an item is private, it can be accessed only by its immediate parent
239 module and any of the parent’s child modules.
cc61c64b
XL
240
241### Privacy Examples
242
7cac9316
XL
243Let’s look at a few more privacy examples to get some practice. Create a new
244library project and enter the code in Listing 7-5 into your new project’s
245*src/lib.rs*:
cc61c64b
XL
246
247<span class="filename">Filename: src/lib.rs</span>
248
249```rust,ignore
250mod outermost {
251 pub fn middle_function() {}
252
253 fn middle_secret_function() {}
254
255 mod inside {
256 pub fn inner_function() {}
257
258 fn secret_function() {}
259 }
260}
261
262fn try_me() {
263 outermost::middle_function();
264 outermost::middle_secret_function();
265 outermost::inside::inner_function();
266 outermost::inside::secret_function();
267}
268```
269
270<span class="caption">Listing 7-5: Examples of private and public functions,
271some of which are incorrect</span>
272
7cac9316
XL
273Before you try to compile this code, make a guess about which lines in the
274`try_me` function will have errors. Then, try compiling the code to see whether
275you were right, and read on for the discussion of the errors!
cc61c64b
XL
276
277#### Looking at the Errors
278
279The `try_me` function is in the root module of our project. The module named
7cac9316
XL
280`outermost` is private, but the second privacy rule states that the `try_me`
281function is allowed to access the `outermost` module because `outermost` is in
282the current (root) module, as is `try_me`.
cc61c64b 283
7cac9316
XL
284The call to `outermost::middle_function` will work because `middle_function` is
285public, and `try_me` is accessing `middle_function` through its parent module
286`outermost`. We determined in the previous paragraph that this module is
287accessible.
cc61c64b
XL
288
289The call to `outermost::middle_secret_function` will cause a compilation error.
290`middle_secret_function` is private, so the second rule applies. The root
291module is neither the current module of `middle_secret_function` (`outermost`
292is), nor is it a child module of the current module of `middle_secret_function`.
293
294The module named `inside` is private and has no child modules, so it can only
7cac9316
XL
295be accessed by its current module `outermost`. That means the `try_me` function
296is not allowed to call `outermost::inside::inner_function` or
297`outermost::inside::secret_function`.
cc61c64b
XL
298
299#### Fixing the Errors
300
301Here are some suggestions for changing the code in an attempt to fix the
302errors. Before you try each one, make a guess as to whether it will fix the
7cac9316
XL
303errors, and then compile the code to see whether or not you’re right, using the
304privacy rules to understand why.
cc61c64b
XL
305
306* What if the `inside` module was public?
307* What if `outermost` was public and `inside` was private?
308* What if, in the body of `inner_function`, you called
309 `::outermost::middle_secret_function()`? (The two colons at the beginning mean
310 that we want to refer to the modules starting from the root module.)
311
312Feel free to design more experiments and try them out!
313
7cac9316 314Next, let’s talk about bringing items into scope with the `use` keyword.