Skip to content

Commit cdd5545

Browse files
Add chapter for re-exports in the rustdoc book
1 parent 64a4959 commit cdd5545

File tree

2 files changed

+129
-0
lines changed

2 files changed

+129
-0
lines changed

src/doc/rustdoc/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
- [How to write documentation](how-to-write-documentation.md)
88
- [What to include (and exclude)](write-documentation/what-to-include.md)
99
- [The `#[doc]` attribute](write-documentation/the-doc-attribute.md)
10+
- [Re-exports](write-documentation/re-exports.md)
1011
- [Linking to items by name](write-documentation/linking-to-items-by-name.md)
1112
- [Documentation tests](write-documentation/documentation-tests.md)
1213
- [Rustdoc-specific lints](lints.md)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Re-exports
2+
3+
Let's start by explaining what are re-exports. To do so, we will use an example where we are
4+
writing a library (named `lib`) with some types dispatched in sub-modules:
5+
6+
```rust
7+
pub mod sub_module1 {
8+
pub struct Foo;
9+
}
10+
pub mod sub_module2 {
11+
pub struct AnotherFoo;
12+
}
13+
```
14+
15+
Users can import them like this:
16+
17+
```rust,ignore (inline)
18+
use lib::sub_module1::Foo;
19+
use lib::sub_module2::AnotherFoo;
20+
```
21+
22+
But what if you want the types to be available directly at the crate root or if we don't want the
23+
modules to be visible for users? That's where re-exports come in:
24+
25+
```rust,ignore (inline)
26+
// `sub_module1` and `sub_module2` are not visible outside.
27+
mod sub_module1 {
28+
pub struct Foo;
29+
}
30+
mod sub_module2 {
31+
pub struct AnotherFoo;
32+
}
33+
34+
// We re-export both types:
35+
pub use crate::sub_module1::Foo;
36+
pub use crate::sub_module2::AnotherFoo;
37+
```
38+
39+
And now users will be able to do:
40+
41+
```rust,ignore (inline)
42+
use lib::{Foo, AnotherFoo};
43+
```
44+
45+
And since both `sub_module1` and `sub_module2` are private, users won't be able to import them.
46+
47+
Now what's interesting is that the generated documentation for this crate will show both `Foo` and
48+
`AnotherFoo` directly at the crate root, meaning they have been inlined. There are a few rules to
49+
know whether or not a re-exported item will be inlined.
50+
51+
## Inlining rules
52+
53+
If a public item comes from a private module, it will be inlined:
54+
55+
```rust,ignore (inline)
56+
mod private_module {
57+
pub struct Public;
58+
}
59+
60+
pub mod public_mod {
61+
// `Public` will inlined here since `private_module` is private.
62+
pub use super::private_module::Public;
63+
}
64+
65+
// `Public` will not be inlined here since `public_mod` is public.
66+
pub use self::public_mod::Public;
67+
```
68+
69+
Likewise, if an item has `#[doc(hidden)]` or inherits it (from any of its parents), it
70+
will be inlined:
71+
72+
```rust,ignore (inline)
73+
#[doc(hidden)]
74+
pub mod public_mod {
75+
pub struct Public;
76+
}
77+
78+
#[doc(hidden)]
79+
pub struct Hidden;
80+
81+
// `Public` be inlined since its parent (`public_mod`) has `#[doc(hidden)]`.
82+
pub use self::public_mod::Public;
83+
// `Hidden` be inlined since it has `#[doc(hidden)]`.
84+
pub use self::Hidden;
85+
```
86+
87+
The inlining rules are a bit different for glob re-exports (`pub use x::*`) for `#[doc(hidden)]`
88+
types. If we take the previous example and then re-export like this:
89+
90+
```rust,ignore (inline)
91+
pub use self::*; // It will not inline the `Hidden` struct.
92+
pub use self::public_mod::*; // It will inline the `Public` struct.
93+
```
94+
95+
It only impacts elements that have the `#[doc(hidden)]` attributes. If it only inherits it, then it
96+
is inlined.
97+
98+
## Inlining with `#[doc(inline)]`
99+
100+
You can use the `#[doc(inline)]` attribute if you want to force an item to be inlined:
101+
102+
```rust,ignore (inline)
103+
pub mod public_mod {
104+
pub struct Public;
105+
}
106+
107+
#[doc(inline)]
108+
pub use self::public_mod::Public;
109+
```
110+
111+
With this code, even though `public_mod::Public` is public and present in the documentation, the
112+
`Public` type will be present both at the crate root and in the `public_mod` module.
113+
114+
## Attributes
115+
116+
When an item is inlined, its doc comments and most of its attributes will be inlined along with it:
117+
118+
| Attribute | Inlined? | Notes
119+
|--|--|--
120+
| `#[doc=""]` | Yes | Intra-doc links are resolved relative to where the doc comment is defined (`///` is syntax sugar for doc string attributes).
121+
| `#[doc(cfg(..))]` | Yes |
122+
| `#[deprecated]` | Yes | Intra-doc links are resolved relative to where the description is defined.
123+
| `#[doc(alias="")]` | No |
124+
| `#[doc(inline)]` | No |
125+
| `#[doc(no_inline)]` | No |
126+
| `#[doc(hidden)]` | Glob imports | For name-based imports (such as `use module::Item as ModuleItem`), hiding an item acts the same as making it private. Glob-based imports (such as `use module::*`), hidden items are not inlined.
127+
128+
All other attributes are inherited when inlined, so that the documentation matches the behavior if the inlined item was directly defined at the spot where it's shown.

0 commit comments

Comments
 (0)