Skip to content

Commit 4a05a52

Browse files
Add documentation for doc cfg
1 parent 7c0a65e commit 4a05a52

File tree

2 files changed

+198
-82
lines changed

2 files changed

+198
-82
lines changed

src/doc/rustdoc/src/advanced-features.md

+198
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,204 @@ pub struct UnixToken;
3333
Here, the respective tokens can only be used by dependent crates on their respective platforms, but
3434
they will both appear in documentation.
3535

36+
## Recording what platforms or features are required for code to be present
37+
38+
By default, rustdoc will pick the `cfg` attributes present on each item and render them in the
39+
generated documentation. However, if you want to tweak or completely overload this behaviour, it's
40+
possible with the `#[doc(auto_cfg)]` and `#[doc(cfg(...)]` attributes.
41+
42+
### `#[doc(auto_cfg)]`
43+
44+
This attribute can have the following forms:
45+
46+
* `#[doc(auto_cfg)]`
47+
* `#[doc(auto_cfg = ...)]`
48+
* `#[doc(auto_cfg(show(...)))]`
49+
* `#[doc(auto_cfg(hide(...)))]`
50+
51+
`#[doc(auto_cfg)]` enables the feature and is the shorter form of `#[doc(auto_cfg = true)]`.
52+
Enabling the feature means that the `cfg` attributes will be picked automatically by rustdoc. To be
53+
noted: using any form of `#[doc(auto_cfg)]` will (re-)enable the feature.
54+
55+
If you want to disable it, you can use `#[doc(auto_cfg = false)]`.
56+
57+
The state of the feature (whether it's enabled or disabled) is inherited by the item's children. So
58+
if you disable the feature on module, non of the module items will get their `cfg` picked
59+
automatically, unless you re-enable the feature on the items.
60+
61+
Now about `#[doc(auto_cfg(show(...)))]` and `#[doc(auto_cfg(hide(...)))]`, they allow you to
62+
show/hide `cfg`s you don't want to appear in the documentation. By default, rustdoc hides the
63+
following `cfg` attributes: `test`, `doc` and `doctest`.
64+
65+
You can use it as follows:
66+
67+
```rust
68+
#[doc(auto_cfg(hide(unix)))]
69+
#[cfg(any(unix, feature = "futures-io"))]
70+
pub mod futures {
71+
// `futures` and all its descendants won't display "unix" in their cfgs.
72+
}
73+
```
74+
75+
And if you want to revert the hidden attributes, you can use `doc(auto_cfg(show(...)))`:
76+
77+
```rust
78+
#[doc(auto_cfg(hide(unix)))]
79+
#[cfg(any(unix, feature = "futures-io"))]
80+
pub mod futures {
81+
// `futures` and all its descendants won't display "unix" in their cfgs.
82+
#[doc(auto_cfg(show(unix)))]
83+
#[cfg(unix)] // It will be displayed for `bar`.
84+
pub fn bar() {}
85+
86+
#[cfg(unix)] // It will not be displayed for `bar`.
87+
pub fn foo() {}
88+
}
89+
```
90+
91+
The attribute accepts only a list of identifiers or key/value items. So you can write:
92+
93+
```rust
94+
#[doc(auto_cfg(hide(unix, doctest, feature = "something")))]
95+
#[doc(auto_cfg(hide()))]
96+
```
97+
98+
But you cannot write:
99+
100+
```rust
101+
#[doc(auto_cfg(hide(not(unix))))]
102+
```
103+
104+
So if we use `doc(auto_cfg(hide(unix)))`, it means it will hide all mentions of `unix`:
105+
106+
```rust
107+
#[cfg(unix)] // nothing displayed
108+
#[cfg(any(unix))] // nothing displayed
109+
#[cfg(any(unix, windows))] // only `windows` displayed
110+
```
111+
112+
However, it only impacts the `unix` cfg, not the feature:
113+
114+
```rust
115+
#[cfg(feature = "unix")] // `feature = "unix"` is displayed
116+
```
117+
118+
If `cfg_auto(show(...))` and `cfg_auto(hide(...))` are used to show/hide a same cfg on a same item,
119+
it'll emit an error. Example:
120+
121+
```rust
122+
#[doc(auto_cfg(hide(unix)))]
123+
#[doc(auto_cfg(show(unix)))] // Error!
124+
pub fn foo() {}
125+
```
126+
127+
### `#[doc(cfg(...))]`
128+
129+
This attribute provides a standardized format to override `#[cfg()]` attributes to document
130+
conditionally available items. Example:
131+
132+
```rust
133+
// the "real" cfg condition
134+
#[cfg(feature = "futures-io")]
135+
// the `doc(cfg())` so it's displayed to the readers
136+
#[doc(cfg(feature = "futures-io"))]
137+
pub mod futures {}
138+
```
139+
140+
It will display in the documentation for this module:
141+
142+
```text
143+
This is supported on feature="futures-io" only.
144+
```
145+
146+
You can use it to display information in generated documentation, whether or not there is a
147+
`#[cfg()]` attribute:
148+
149+
```rust
150+
#[doc(cfg(feature = "futures-io"))]
151+
pub mod futures {}
152+
```
153+
154+
It will be displayed exactly the same as the previous code.
155+
156+
This attribute has the same syntax as conditional compilation, but it only causes documentation to
157+
be added. This means `#[doc(cfg(not(windows)))]` will not cause your docs to be hidden on
158+
non-windows targets, even though `#[cfg(not(windows))]` does do that.
159+
160+
If `doc(auto_cfg)` is enabled on the item, `doc(cfg)` will override it anyway so in the two previous
161+
examples, even if the `doc(auto_cfg)` feature was enabled, it would still display the same thing.
162+
163+
### (doc) cfg inheritance
164+
165+
Rustdoc merges `cfg` attributes from parent modules to its children. For example, in this case, the
166+
module `non_unix` will describe the entire compatibility matrix for the module, and not just its
167+
directly attached information:
168+
169+
```rust
170+
#[doc(cfg(any(windows, unix)))]
171+
pub mod desktop {
172+
#[doc(cfg(not(unix)))]
173+
pub mod non_unix {
174+
//
175+
}
176+
}
177+
```
178+
179+
will display:
180+
181+
```
182+
Available on (Windows or Unix) and non-Unix only.
183+
```
184+
185+
### Re-exports and inlining
186+
187+
`cfg` attributes of a re-export are never merged with the re-exported item(s) attributes except if
188+
the re-export has the `#[doc(inline)]` attribute. In this case, the `cfg` of the re-exported item
189+
will be merged with the re-export's.
190+
191+
When talking about "attributes merge", we mean that if the re-export has `#[cfg(unix)]` and the
192+
re-exported item has `#[cfg(feature = "foo")]`, you will only see `cfg(unix)` on the re-export and
193+
only `cfg(feature = "foo")` on the re-exported item, unless the re-export has `#[doc(inline)]`, then
194+
you will only see the re-exported item with both `cfg(unix)` and `cfg(feature = "foo")`.
195+
196+
Example:
197+
198+
```rust
199+
#[doc(cfg(any(windows, unix)))]
200+
pub mod desktop {
201+
#[doc(cfg(not(unix)))]
202+
pub mod non_unix {
203+
// code
204+
}
205+
}
206+
207+
#[doc(cfg(target_os = "freebsd"))]
208+
pub use desktop::non_unix as non_unix_desktop;
209+
#[doc(cfg(target_os = "macos"))]
210+
#[doc(inline)]
211+
pub use desktop::non_unix as inlined_non_unix_desktop;
212+
```
213+
214+
In this example, `non_unix_desktop` will only display `cfg(target_os = "freeebsd")` and not display
215+
any `cfg` from `desktop::non_unix`.
216+
217+
On the contrary, `inlined_non_unix_desktop` will have cfgs from both the re-export and the
218+
re-exported item.
219+
220+
So that also means that if a crate re-exports a foreign item, unless it has `#[doc(inline)]`, the
221+
`cfg` and `doc(cfg)` attributes will not be visible:
222+
223+
```rust
224+
// dep:
225+
#[cfg(feature = "a")]
226+
pub struct S;
227+
228+
// crate using dep:
229+
230+
// There will be no mention of `feature = "a"` in the documentation.
231+
pub use dep::S as Y;
232+
```
233+
36234
### Interactions between platform-specific docs
37235

38236
Rustdoc does not have a magic way to compile documentation 'as-if' you'd run it once for each

src/doc/rustdoc/src/unstable-features.md

-82
Original file line numberDiff line numberDiff line change
@@ -56,88 +56,6 @@ It is also not emitted for foreign items, aliases, extern crates and imports.
5656
These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler
5757
and enabled with a `#![feature(...)]` attribute in your crate.
5858

59-
### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present
60-
61-
* Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781)
62-
63-
You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on.
64-
This has two effects:
65-
66-
1. doctests will only run on the appropriate platforms, and
67-
2. When Rustdoc renders documentation for that item, it will be accompanied by a banner explaining
68-
that the item is only available on certain platforms.
69-
70-
`#[doc(cfg)]` is intended to be used alongside [`#[cfg(doc)]`][cfg-doc].
71-
For example, `#[cfg(any(windows, doc))]` will preserve the item either on Windows or during the
72-
documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that
73-
the item is supposed to be used on Windows. For example:
74-
75-
```rust
76-
#![feature(doc_cfg)]
77-
78-
/// Token struct that can only be used on Windows.
79-
#[cfg(any(windows, doc))]
80-
#[doc(cfg(windows))]
81-
pub struct WindowsToken;
82-
83-
/// Token struct that can only be used on Unix.
84-
#[cfg(any(unix, doc))]
85-
#[doc(cfg(unix))]
86-
pub struct UnixToken;
87-
88-
/// Token struct that is only available with the `serde` feature
89-
#[cfg(feature = "serde")]
90-
#[doc(cfg(feature = "serde"))]
91-
#[derive(serde::Deserialize)]
92-
pub struct SerdeToken;
93-
```
94-
95-
In this sample, the tokens will only appear on their respective platforms, but they will both appear
96-
in documentation.
97-
98-
`#[doc(cfg(...))]` was introduced to be used by the standard library and currently requires the
99-
`#![feature(doc_cfg)]` feature gate. For more information, see [its chapter in the Unstable
100-
Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].
101-
102-
### `doc_auto_cfg`: Automatically generate `#[doc(cfg)]`
103-
104-
* Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781)
105-
106-
`doc_auto_cfg` is an extension to the `#[doc(cfg)]` feature. With it, you don't need to add
107-
`#[doc(cfg(...)]` anymore unless you want to override the default behaviour. So if we take the
108-
previous source code:
109-
110-
```rust
111-
#![feature(doc_auto_cfg)]
112-
113-
/// Token struct that can only be used on Windows.
114-
#[cfg(any(windows, doc))]
115-
pub struct WindowsToken;
116-
117-
/// Token struct that can only be used on Unix.
118-
#[cfg(any(unix, doc))]
119-
pub struct UnixToken;
120-
121-
/// Token struct that is only available with the `serde` feature
122-
#[cfg(feature = "serde")]
123-
#[derive(serde::Deserialize)]
124-
pub struct SerdeToken;
125-
```
126-
127-
It'll render almost the same, the difference being that `doc` will also be displayed. To fix this,
128-
you can use `doc_cfg_hide`:
129-
130-
```rust
131-
#![feature(doc_cfg_hide)]
132-
#![doc(cfg_hide(doc))]
133-
```
134-
135-
And `doc` won't show up anymore!
136-
137-
[cfg-doc]: ./advanced-features.md
138-
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
139-
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781
140-
14159
### Adding your trait to the "Notable traits" dialog
14260

14361
* Tracking issue: [#45040](https://github.com/rust-lang/rust/issues/45040)

0 commit comments

Comments
 (0)