Skip to content

Commit

Permalink
Revamp rustdoc docs about documentation using cfg
Browse files Browse the repository at this point in the history
- Move `cfg(doc)` out of `unstable-features`. It's not unstable.
- Remove outdated reference to `everybody_loops`.
- Improve wording in various places
- Give an example of code this allows (and does not allow)
- Link to `cfg(doc)` in `doc(cfg)` documentation. Since one is stable
and the other is not, don't combine them.
- Cleanup wording for `doc(cfg)`
- Incorporate changes from rust-lang#76849
- Mention that `doc(cfg)` is also for features
  • Loading branch information
jyn514 committed Oct 5, 2020
1 parent 7820135 commit dc5a000
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 21 deletions.
38 changes: 36 additions & 2 deletions src/doc/rustdoc/src/advanced-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The features listed on this page fall outside the rest of the main categories.

## `#[cfg(doc)]`: Documenting platform-/feature-specific information
## `#[cfg(doc)]`: Documenting platform-specific or feature-specific information

For conditional compilation, Rustdoc treats your crate the same way the compiler does. Only things
from the host target are available (or from the given `--target` if present), and everything else is
Expand All @@ -17,7 +17,7 @@ with other `#[cfg]` filters on it, you can write something like `#[cfg(any(windo
This will preserve the item either when built normally on Windows, or when being documented
anywhere.

Please note that this feature is not passed to doctests.
Please note that this `cfg` is not passed to doctests.

Example:

Expand All @@ -33,6 +33,40 @@ pub struct UnixToken;
Here, the respective tokens can only be used by dependent crates on their respective platforms, but
they will both appear in documentation.

### Interactions between platform-specific docs

Rustdoc does not have a magic way to compile documentation 'as-if' you'd run it once for each
platform (such a magic wand has been called the ['holy grail of rustdoc'][#1998]). Instead,
it sees *all* of your code at once, the same way the Rust compiler would if you passed it
`--cfg doc`. However, Rustdoc has a trick up its sleeve to handle platform-specific code if it
*does* receive it.

To document your crate, Rustdoc only needs to know the public signature of your functions.
In particular, it doesn't have to know how any of your functions are implemented, so it ignores
all type errors and name resolution errors with function bodies. Note that this does *not*
work for anything outside a function body: since Rustdoc documents your types, it has to
know what those types are! For example, this code will work regardless of the platform:

<!-- `ignore` because doc-tests are run with `rustc`, not `rustdoc` -->
```ignore
pub fn f() {
use std::os::windows::ffi::OsStrExt;
}
```

but this will not, because the unknown type is part of the function signature:

```ignore
pub fn f() -> std::os::windows::ffi::EncodeWide<'static> {
unimplemented!()
}
```

For a more realistic example of code this allows, see [the rustdoc test suite][realistic-async].

[#1998]: https://github.com/rust-lang/rust/issues/1998
[realistic-async]: https://github.com/rust-lang/rust/blob/b146000e910ccd60bdcde89363cb6aa14ecc0d95/src/test/rustdoc-ui/error-in-impl-trait/realistic-async.rs

## Add aliases for an item in documentation search

This feature allows you to add alias(es) to an item when using the `rustdoc` search through the
Expand Down
33 changes: 14 additions & 19 deletions src/doc/rustdoc/src/unstable-features.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,28 +43,16 @@ plain text.
These features operate by extending the `#[doc]` attribute, and thus can be caught by the compiler
and enabled with a `#![feature(...)]` attribute in your crate.

### Documenting platform-/feature-specific information
### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present

Because of the way Rustdoc documents a crate, the documentation it creates is specific to the target
rustc compiles for. Anything that's specific to any other target is dropped via `#[cfg]` attribute
processing early in the compilation process. However, Rustdoc has a trick up its sleeve to handle
platform-specific code if it *does* receive it.
You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on.
This has two effects:

Because Rustdoc doesn't need to fully compile a crate to binary, it replaces function bodies with
`loop {}` to prevent having to process more than necessary. This means that any code within a
function that requires platform-specific pieces is ignored. Combined with a special attribute,
`#[doc(cfg(...))]`, you can tell Rustdoc exactly which platform something is supposed to run on,
ensuring that doctests are only run on the appropriate platforms.

The `#[doc(cfg(...))]` attribute has another effect: When Rustdoc renders documentation for that
item, it will be accompanied by a banner explaining that the item is only available on certain
platforms.

For Rustdoc to document an item, it needs to see it, regardless of what platform it's currently
running on. To aid this, Rustdoc sets the flag `#[cfg(doc)]` when running on your crate.
Combining this with the target platform of a given item allows it to appear when building your crate
normally on that platform, as well as when building documentation anywhere.
1. doctests will only run on the appropriate platforms, and
2. When Rustdoc renders documentation for that item, it will be accompanied by a banner explaining
that the item is only available on certain platforms.

`#[doc(cfg)]` is intended to be used alongside [`#[cfg(doc)]`][cfg-doc].
For example, `#[cfg(any(windows, doc))]` will preserve the item either on Windows or during the
documentation process. Then, adding a new attribute `#[doc(cfg(windows))]` will tell Rustdoc that
the item is supposed to be used on Windows. For example:
Expand All @@ -81,6 +69,12 @@ pub struct WindowsToken;
#[cfg(any(unix, doc))]
#[doc(cfg(unix))]
pub struct UnixToken;

/// Token struct that is only available with the `serde` feature
#[cfg(feature = "serde")]
#[doc(cfg(feature = "serde"))]
#[derive(serde::Deserialize)]
pub struct SerdeToken;
```

In this sample, the tokens will only appear on their respective platforms, but they will both appear
Expand All @@ -90,6 +84,7 @@ in documentation.
`#![feature(doc_cfg)]` feature gate. For more information, see [its chapter in the Unstable
Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg].

[cfg-doc]: ./advanced-features.md
[unstable-doc-cfg]: ../unstable-book/language-features/doc-cfg.html
[issue-doc-cfg]: https://github.com/rust-lang/rust/issues/43781

Expand Down

0 comments on commit dc5a000

Please sign in to comment.