]> git.proxmox.com Git - rustc.git/blame - src/doc/reference/src/visibility-and-privacy.md
New upstream version 1.28.0~beta.14+dfsg1
[rustc.git] / src / doc / reference / src / visibility-and-privacy.md
CommitLineData
8bb4bdeb
XL
1# Visibility and Privacy
2
3b2f2976
XL
3> **<sup>Syntax<sup>**
4> _Visibility_ :
5> &nbsp;&nbsp; &nbsp;&nbsp; EMPTY
6> &nbsp;&nbsp; | `pub`
7> &nbsp;&nbsp; | `pub` `(` `crate` `)`
8> &nbsp;&nbsp; | `pub` `(` `in` _ModulePath_ `)`
9> &nbsp;&nbsp; | `pub` `(` `in`<sup>?</sup> `self` `)`
10> &nbsp;&nbsp; | `pub` `(` `in`<sup>?</sup> `super` `)`
11
8bb4bdeb
XL
12These two terms are often used interchangeably, and what they are attempting to
13convey is the answer to the question "Can this item be used at this location?"
14
15Rust's name resolution operates on a global hierarchy of namespaces. Each level
16in the hierarchy can be thought of as some item. The items are one of those
17mentioned above, but also include external crates. Declaring or defining a new
18module can be thought of as inserting a new tree into the hierarchy at the
19location of the definition.
20
21To control whether interfaces can be used across modules, Rust checks each use
22of an item to see whether it should be allowed or not. This is where privacy
23warnings are generated, or otherwise "you used a private item of another module
24and weren't allowed to."
25
26By default, everything in Rust is *private*, with two exceptions: Associated
27items in a `pub` Trait are public by default; Enum variants
28in a `pub` enum are also public by default. When an item is declared as `pub`,
29it can be thought of as being accessible to the outside world. For example:
30
cc61c64b 31```rust
8bb4bdeb
XL
32# fn main() {}
33// Declare a private struct
34struct Foo;
35
36// Declare a public struct with a private field
37pub struct Bar {
38 field: i32,
39}
40
41// Declare a public enum with two public variants
42pub enum State {
43 PubliclyAccessibleState,
44 PubliclyAccessibleState2,
45}
46```
47
48With the notion of an item being either public or private, Rust allows item
49accesses in two cases:
50
cc61c64b
XL
511. If an item is public, then it can be accessed externally from some module
52 `m` if you can access all the item's parent modules from `m`. You can
53 also potentially be able to name the item through re-exports. See below.
8bb4bdeb
XL
542. If an item is private, it may be accessed by the current module and its
55 descendants.
56
57These two cases are surprisingly powerful for creating module hierarchies
58exposing public APIs while hiding internal implementation details. To help
59explain, here's a few use cases and what they would entail:
60
61* A library developer needs to expose functionality to crates which link
62 against their library. As a consequence of the first case, this means that
63 anything which is usable externally must be `pub` from the root down to the
64 destination item. Any private item in the chain will disallow external
65 accesses.
66
67* A crate needs a global available "helper module" to itself, but it doesn't
68 want to expose the helper module as a public API. To accomplish this, the
69 root of the crate's hierarchy would have a private module which then
70 internally has a "public API". Because the entire crate is a descendant of
71 the root, then the entire local crate can access this private module through
72 the second case.
73
74* When writing unit tests for a module, it's often a common idiom to have an
75 immediate child of the module to-be-tested named `mod test`. This module
76 could access any items of the parent module through the second case, meaning
77 that internal implementation details could also be seamlessly tested from the
78 child module.
79
80In the second case, it mentions that a private item "can be accessed" by the
81current module and its descendants, but the exact meaning of accessing an item
82depends on what the item is. Accessing a module, for example, would mean
83looking inside of it (to import more items). On the other hand, accessing a
84function would mean that it is invoked. Additionally, path expressions and
85import statements are considered to access an item in the sense that the
86import/expression is only valid if the destination is in the current visibility
87scope.
88
89Here's an example of a program which exemplifies the three cases outlined
90above:
91
cc61c64b 92```rust
8bb4bdeb
XL
93// This module is private, meaning that no external crate can access this
94// module. Because it is private at the root of this current crate, however, any
95// module in the crate may access any publicly visible item in this module.
96mod crate_helper_module {
97
98 // This function can be used by anything in the current crate
99 pub fn crate_helper() {}
100
101 // This function *cannot* be used by anything else in the crate. It is not
102 // publicly visible outside of the `crate_helper_module`, so only this
103 // current module and its descendants may access it.
104 fn implementation_detail() {}
105}
106
107// This function is "public to the root" meaning that it's available to external
108// crates linking against this one.
109pub fn public_api() {}
110
111// Similarly to 'public_api', this module is public so external crates may look
112// inside of it.
113pub mod submodule {
114 use crate_helper_module;
115
116 pub fn my_method() {
117 // Any item in the local crate may invoke the helper module's public
118 // interface through a combination of the two rules above.
119 crate_helper_module::crate_helper();
120 }
121
122 // This function is hidden to any module which is not a descendant of
123 // `submodule`
124 fn my_implementation() {}
125
126 #[cfg(test)]
127 mod test {
128
129 #[test]
130 fn test_my_implementation() {
131 // Because this module is a descendant of `submodule`, it's allowed
132 // to access private items inside of `submodule` without a privacy
133 // violation.
134 super::my_implementation();
135 }
136 }
137}
138
139# fn main() {}
140```
141
142For a Rust program to pass the privacy checking pass, all paths must be valid
143accesses given the two rules above. This includes all use statements,
144expressions, types, etc.
145
cc61c64b
XL
146## `pub(in path)`, `pub(crate)`, `pub(super)`, and `pub(self)`
147
148In addition to public and private, Rust allows users to declare an item as
149visible within a given scope. The rules for `pub` restrictions are as follows:
150- `pub(in path)` makes an item visible within the provided `path`. `path` must
151be a parent module of the item whose visibility is being declared.
152- `pub(crate)` makes an item visible within the current crate.
94b46f34
XL
153- `pub(super)` makes an item visible to the parent module. This is equivalent
154 to `pub(in super)`.
cc61c64b
XL
155- `pub(self)` makes an item visible to the current module. This is equivalent
156to `pub(in self)`.
157
158Here's an example:
159
160```rust
161pub mod outer_mod {
162 pub mod inner_mod {
163 // This function is visible within `outer_mod`
164 pub(in outer_mod) fn outer_mod_visible_fn() {}
165
166 // This function is visible to the entire crate
167 pub(crate) fn crate_visible_fn() {}
168
169 // This function is visible within `outer_mod`
170 pub(super) fn super_mod_visible_fn() {
171 // This function is visible since we're in the same `mod`
172 inner_mod_visible_fn();
173 }
174
175 // This function is visible
176 pub(self) fn inner_mod_visible_fn() {}
177 }
178 pub fn foo() {
179 inner_mod::outer_mod_visible_fn();
180 inner_mod::crate_visible_fn();
181 inner_mod::super_mod_visible_fn();
182
183 // This function is no longer visible since we're outside of `inner_mod`
184 // Error! `inner_mod_visible_fn` is private
185 //inner_mod::inner_mod_visible_fn();
186 }
187}
188
189fn bar() {
190 // This function is still visible since we're in the same crate
191 outer_mod::inner_mod::crate_visible_fn();
192
193 // This function is no longer visible since we're outside of `outer_mod`
194 // Error! `super_mod_visible_fn` is private
195 //outer_mod::inner_mod::super_mod_visible_fn();
196
197 // This function is no longer visible since we're outside of `outer_mod`
198 // Error! `outer_mod_visible_fn` is private
199 //outer_mod::inner_mod::outer_mod_visible_fn();
200
201 outer_mod::foo();
202}
203
204fn main() { bar() }
205```
206
8bb4bdeb
XL
207## Re-exporting and Visibility
208
209Rust allows publicly re-exporting items through a `pub use` directive. Because
210this is a public directive, this allows the item to be used in the current
211module through the rules above. It essentially allows public access into the
212re-exported item. For example, this program is valid:
213
cc61c64b 214```rust
8bb4bdeb
XL
215pub use self::implementation::api;
216
217mod implementation {
218 pub mod api {
219 pub fn f() {}
220 }
221}
222
223# fn main() {}
224```
225
226This means that any external crate referencing `implementation::api::f` would
227receive a privacy violation, while the path `api::f` would be allowed.
228
229When re-exporting a private item, it can be thought of as allowing the "privacy
230chain" being short-circuited through the reexport instead of passing through
231the namespace hierarchy as it normally would.