From 4e067e80ebb60022d6446335b0721feed73483b9 Mon Sep 17 00:00:00 2001 From: Loïc BRANSTETT Date: Tue, 8 Mar 2022 23:11:37 +0100 Subject: Improve rustdoc book --- src/doc/rustdoc/book.toml | 4 + src/doc/rustdoc/src/SUMMARY.md | 15 +- src/doc/rustdoc/src/advanced-features.md | 22 + src/doc/rustdoc/src/command-line-arguments.md | 30 +- src/doc/rustdoc/src/deprecated-features.md | 13 + src/doc/rustdoc/src/documentation-tests.md | 445 --------------------- src/doc/rustdoc/src/how-to-read-rustdoc.md | 4 +- src/doc/rustdoc/src/linking-to-items-by-name.md | 143 ------- src/doc/rustdoc/src/lints.md | 24 +- src/doc/rustdoc/src/passes.md | 11 - src/doc/rustdoc/src/the-doc-attribute.md | 276 ------------- src/doc/rustdoc/src/unstable-features.md | 51 ++- src/doc/rustdoc/src/website-features.md | 25 -- src/doc/rustdoc/src/what-to-include.md | 125 ------ .../src/write-documentation/documentation-tests.md | 445 +++++++++++++++++++++ .../linking-to-items-by-name.md | 143 +++++++ .../src/write-documentation/the-doc-attribute.md | 276 +++++++++++++ .../src/write-documentation/what-to-include.md | 125 ++++++ 18 files changed, 1100 insertions(+), 1077 deletions(-) create mode 100644 src/doc/rustdoc/src/deprecated-features.md delete mode 100644 src/doc/rustdoc/src/documentation-tests.md delete mode 100644 src/doc/rustdoc/src/linking-to-items-by-name.md delete mode 100644 src/doc/rustdoc/src/passes.md delete mode 100644 src/doc/rustdoc/src/the-doc-attribute.md delete mode 100644 src/doc/rustdoc/src/website-features.md delete mode 100644 src/doc/rustdoc/src/what-to-include.md create mode 100644 src/doc/rustdoc/src/write-documentation/documentation-tests.md create mode 100644 src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md create mode 100644 src/doc/rustdoc/src/write-documentation/the-doc-attribute.md create mode 100644 src/doc/rustdoc/src/write-documentation/what-to-include.md (limited to 'src') diff --git a/src/doc/rustdoc/book.toml b/src/doc/rustdoc/book.toml index 97e08416d76..45405a11765 100644 --- a/src/doc/rustdoc/book.toml +++ b/src/doc/rustdoc/book.toml @@ -4,3 +4,7 @@ title = "The rustdoc book" [output.html] git-repository-url = "https://github.com/rust-lang/rust/tree/master/src/doc/rustdoc" + +[output.html.redirect] +"/the-doc-attribute.html" = "write-documentation/the-doc-attribute.html" +"/documentation-tests.html" = "write-documentation/documentation-tests.html" diff --git a/src/doc/rustdoc/src/SUMMARY.md b/src/doc/rustdoc/src/SUMMARY.md index eb181859453..d627f5b0389 100644 --- a/src/doc/rustdoc/src/SUMMARY.md +++ b/src/doc/rustdoc/src/SUMMARY.md @@ -1,16 +1,15 @@ # The Rustdoc Book - [What is rustdoc?](what-is-rustdoc.md) +- [Command-line arguments](command-line-arguments.md) - [How to read rustdoc output](how-to-read-rustdoc.md) - [How to write documentation](how-to-write-documentation.md) -- [What to include (and exclude)](what-to-include.md) -- [Command-line arguments](command-line-arguments.md) -- [The `#[doc]` attribute](the-doc-attribute.md) -- [Documentation tests](documentation-tests.md) -- [Linking to items by name](linking-to-items-by-name.md) -- [Lints](lints.md) + - [What to include (and exclude)](write-documentation/what-to-include.md) + - [The `#[doc]` attribute](write-documentation/the-doc-attribute.md) + - [Linking to items by name](write-documentation/linking-to-items-by-name.md) + - [Documentation tests](write-documentation/documentation-tests.md) +- [Rustdoc-specific lints](lints.md) - [Advanced features](advanced-features.md) - [Unstable features](unstable-features.md) -- [Website features](website-features.md) -- [Passes](passes.md) +- [Deprecated features](deprecated-features.md) - [References](references.md) diff --git a/src/doc/rustdoc/src/advanced-features.md b/src/doc/rustdoc/src/advanced-features.md index 6147bd0a97a..dbf0baec04c 100644 --- a/src/doc/rustdoc/src/advanced-features.md +++ b/src/doc/rustdoc/src/advanced-features.md @@ -88,3 +88,25 @@ You can add multiple aliases at the same time by using a list: #[doc(alias("x", "big"))] pub struct BigX; ``` + +## Custom search engines + +If you find yourself often referencing online Rust docs you might enjoy using a custom search +engine. This allows you to use the navigation bar directly to search a `rustdoc` website. +Most browsers support this feature by letting you define a URL template containing `%s` +which will be substituted for the search term. As an example, for the standard library you could use +this template: + +```text +https://doc.rust-lang.org/stable/std/?search=%s +``` + +Note that this will take you to a results page listing all matches. If you want to navigate to the first +result right away (which is often the best match) use the following instead: + +```text +https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true +``` + +This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL +to automatically go to the first result. diff --git a/src/doc/rustdoc/src/command-line-arguments.md b/src/doc/rustdoc/src/command-line-arguments.md index 3ce57f88938..2a2e51b2f63 100644 --- a/src/doc/rustdoc/src/command-line-arguments.md +++ b/src/doc/rustdoc/src/command-line-arguments.md @@ -177,7 +177,7 @@ $ rustdoc src/lib.rs --test ``` This flag will run your code examples as tests. For more, see [the chapter -on documentation tests](documentation-tests.md). +on documentation tests](write-documentation/documentation-tests.md). See also `--test-args`. @@ -190,7 +190,7 @@ $ rustdoc src/lib.rs --test --test-args ignored ``` This flag will pass options to the test runner when running documentation tests. -For more, see [the chapter on documentation tests](documentation-tests.md). +For more, see [the chapter on documentation tests](write-documentation/documentation-tests.md). See also `--test`. @@ -336,7 +336,7 @@ $ rustdoc src/lib.rs --sysroot /path/to/sysroot Similar to `rustc --sysroot`, this lets you change the sysroot `rustdoc` uses when compiling your code. -### `--edition`: control the edition of docs and doctests +## `--edition`: control the edition of docs and doctests Using this flag looks like this: @@ -403,12 +403,12 @@ encoded as UTF-8. ## `--passes`: add more rustdoc passes This flag is **deprecated**. -For more details on passes, see [the chapter on them](passes.md). +For more details on passes, see [the chapter on them](deprecated-features.md#passes). ## `--no-defaults`: don't run default passes This flag is **deprecated**. -For more details on passes, see [the chapter on them](passes.md). +For more details on passes, see [the chapter on them](deprecated-features.md#passes). ## `-r`/`--input-format`: input format @@ -417,23 +417,3 @@ This flag is **deprecated** and **has no effect**. Rustdoc only supports Rust source code and Markdown input formats. If the file ends in `.md` or `.markdown`, `rustdoc` treats it as a Markdown file. Otherwise, it assumes that the input file is Rust. - -# Unstable command line arguments - -## `--nocapture` - -When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be -captured by rustdoc. Instead, the output will be directed to your terminal, -as if you had run the test executable manually. This is especially useful -for debugging your tests! - -## `--check` - -When this flag is supplied, rustdoc will type check and lint your code, but will not generate any -documentation or run your doctests. - -Using this flag looks like: - -```bash -rustdoc -Z unstable-options --check src/lib.rs -``` diff --git a/src/doc/rustdoc/src/deprecated-features.md b/src/doc/rustdoc/src/deprecated-features.md new file mode 100644 index 00000000000..2bc6e8fc8ae --- /dev/null +++ b/src/doc/rustdoc/src/deprecated-features.md @@ -0,0 +1,13 @@ +# Deprecated features + +## Passes + +Rustdoc has a concept called "passes". These are transformations that +`rustdoc` runs on your documentation before producing its final output. + +Customizing passes is **deprecated**. The available passes are not considered stable and may +change in any release. + +In the past the most common use case for customizing passes was to omit the `strip-private` pass. +You can do this more easily, and without risk of the pass being changed, by passing +[`--document-private-items`](./unstable-features.md#--document-private-items). diff --git a/src/doc/rustdoc/src/documentation-tests.md b/src/doc/rustdoc/src/documentation-tests.md deleted file mode 100644 index 534fd19b52e..00000000000 --- a/src/doc/rustdoc/src/documentation-tests.md +++ /dev/null @@ -1,445 +0,0 @@ -# Documentation tests - -`rustdoc` supports executing your documentation examples as tests. This makes sure -that examples within your documentation are up to date and working. - -The basic idea is this: - -```rust,no_run -/// # Examples -/// -/// ``` -/// let x = 5; -/// ``` -# fn f() {} -``` - -The triple backticks start and end code blocks. If this were in a file named `foo.rs`, -running `rustdoc --test foo.rs` will extract this example, and then run it as a test. - -Please note that by default, if no language is set for the block code, rustdoc -assumes it is Rust code. So the following: - -``````markdown -```rust -let x = 5; -``` -`````` - -is strictly equivalent to: - -``````markdown -``` -let x = 5; -``` -`````` - -There's some subtlety though! Read on for more details. - -## Passing or failing a doctest - -Like regular unit tests, regular doctests are considered to "pass" -if they compile and run without panicking. -So if you want to demonstrate that some computation gives a certain result, -the `assert!` family of macros works the same as other Rust code: - -```rust -let foo = "foo"; -assert_eq!(foo, "foo"); -``` - -This way, if the computation ever returns something different, -the code panics and the doctest fails. - -## Pre-processing examples - -In the example above, you'll note something strange: there's no `main` -function! Forcing you to write `main` for every example, no matter how small, -adds friction and clutters the output. So `rustdoc` processes your examples -slightly before running them. Here's the full algorithm `rustdoc` uses to -preprocess examples: - -1. Some common `allow` attributes are inserted, including - `unused_variables`, `unused_assignments`, `unused_mut`, - `unused_attributes`, and `dead_code`. Small examples often trigger - these lints. -2. Any attributes specified with `#![doc(test(attr(...)))]` are added. -3. Any leading `#![foo]` attributes are left intact as crate attributes. -4. If the example does not contain `extern crate`, and - `#![doc(test(no_crate_inject))]` was not specified, then `extern crate - ;` is inserted (note the lack of `#[macro_use]`). -5. Finally, if the example does not contain `fn main`, the remainder of the - text is wrapped in `fn main() { your_code }`. - -For more about that caveat in rule 4, see "Documenting Macros" below. - -## Hiding portions of the example - -Sometimes, you need some setup code, or other things that would distract -from your example, but are important to make the tests work. Consider -an example block that looks like this: - -```rust,no_run -/// ``` -/// /// Some documentation. -/// # fn foo() {} // this function will be hidden -/// println!("Hello, World!"); -/// ``` -# fn f() {} -``` - -It will render like this: - -```rust -/// Some documentation. -# fn foo() {} -println!("Hello, World!"); -``` - -Yes, that's right: you can add lines that start with `# `, and they will -be hidden from the output, but will be used when compiling your code. You -can use this to your advantage. In this case, documentation comments need -to apply to some kind of function, so if I want to show you just a -documentation comment, I need to add a little function definition below -it. At the same time, it's only there to satisfy the compiler, so hiding -it makes the example more clear. You can use this technique to explain -longer examples in detail, while still preserving the testability of your -documentation. - -For example, imagine that we wanted to document this code: - -```rust -let x = 5; -let y = 6; -println!("{}", x + y); -``` - -We might want the documentation to end up looking like this: - -> First, we set `x` to five: -> -> ```rust -> let x = 5; -> # let y = 6; -> # println!("{}", x + y); -> ``` -> -> Next, we set `y` to six: -> -> ```rust -> # let x = 5; -> let y = 6; -> # println!("{}", x + y); -> ``` -> -> Finally, we print the sum of `x` and `y`: -> -> ```rust -> # let x = 5; -> # let y = 6; -> println!("{}", x + y); -> ``` - -To keep each code block testable, we want the whole program in each block, but -we don't want the reader to see every line every time. Here's what we put in -our source code: - -``````markdown -First, we set `x` to five: - -``` -let x = 5; -# let y = 6; -# println!("{}", x + y); -``` - -Next, we set `y` to six: - -``` -# let x = 5; -let y = 6; -# println!("{}", x + y); -``` - -Finally, we print the sum of `x` and `y`: - -``` -# let x = 5; -# let y = 6; -println!("{}", x + y); -``` -`````` - -By repeating all parts of the example, you can ensure that your example still -compiles, while only showing the parts that are relevant to that part of your -explanation. - -The `#`-hiding of lines can be prevented by using two consecutive hashes -`##`. This only needs to be done with the first `#` which would've -otherwise caused hiding. If we have a string literal like the following, -which has a line that starts with a `#`: - -```rust -let s = "foo -## bar # baz"; -``` - -We can document it by escaping the initial `#`: - -```text -/// let s = "foo -/// ## bar # baz"; -``` - - -## Using `?` in doc tests - -When writing an example, it is rarely useful to include a complete error -handling, as it would add significant amounts of boilerplate code. Instead, you -may want the following: - -```rust,no_run -/// ``` -/// use std::io; -/// let mut input = String::new(); -/// io::stdin().read_line(&mut input)?; -/// ``` -# fn f() {} -``` - -The problem is that `?` returns a `Result` and test functions don't -return anything, so this will give a mismatched types error. - -You can get around this limitation by manually adding a `main` that returns -`Result`, because `Result` implements the `Termination` trait: - -```rust,no_run -/// A doc test using ? -/// -/// ``` -/// use std::io; -/// -/// fn main() -> io::Result<()> { -/// let mut input = String::new(); -/// io::stdin().read_line(&mut input)?; -/// Ok(()) -/// } -/// ``` -# fn f() {} -``` - -Together with the `# ` from the section above, you arrive at a solution that -appears to the reader as the initial idea but works with doc tests: - -```rust,no_run -/// ``` -/// use std::io; -/// # fn main() -> io::Result<()> { -/// let mut input = String::new(); -/// io::stdin().read_line(&mut input)?; -/// # Ok(()) -/// # } -/// ``` -# fn f() {} -``` - -As of version 1.34.0, one can also omit the `fn main()`, but you will have to -disambiguate the error type: - -```rust,no_run -/// ``` -/// use std::io; -/// let mut input = String::new(); -/// io::stdin().read_line(&mut input)?; -/// # Ok::<(), io::Error>(()) -/// ``` -# fn f() {} -``` - -This is an unfortunate consequence of the `?` operator adding an implicit -conversion, so type inference fails because the type is not unique. Please note -that you must write the `(())` in one sequence without intermediate whitespace -so that `rustdoc` understands you want an implicit `Result`-returning function. - -## Showing warnings in doctests - -You can show warnings in doctests by running `rustdoc --test --test-args=--show-output` -(or, if you're using cargo, `cargo test --doc -- --show-output`). -By default, this will still hide `unused` warnings, since so many examples use private functions; -you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings. -You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally. - -[test-attr]: ./the-doc-attribute.md#testattr - -## Documenting macros - -Here’s an example of documenting a macro: - -```rust -/// Panic with a given message unless an expression evaluates to true. -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate foo; -/// # fn main() { -/// panic_unless!(1 + 1 == 2, “Math is broken.”); -/// # } -/// ``` -/// -/// ```should_panic -/// # #[macro_use] extern crate foo; -/// # fn main() { -/// panic_unless!(true == false, “I’m broken.”); -/// # } -/// ``` -#[macro_export] -macro_rules! panic_unless { - ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); -} -# fn main() {} -``` - -You’ll note three things: we need to add our own `extern crate` line, so that -we can add the `#[macro_use]` attribute. Second, we’ll need to add our own -`main()` as well (for reasons discussed above). Finally, a judicious use of -`#` to comment out those two things, so they don’t show up in the output. - -## Attributes - -Code blocks can be annotated with attributes that help `rustdoc` do the right -thing when testing your code: - -The `ignore` attribute tells Rust to ignore your code. This is almost never -what you want as it's the most generic. Instead, consider annotating it -with `text` if it's not code or using `#`s to get a working example that -only shows the part you care about. - -```rust -/// ```ignore -/// fn foo() { -/// ``` -# fn foo() {} -``` - -`should_panic` tells `rustdoc` that the code should compile correctly but -panic during execution. If the code doesn't panic, the test will fail. - -```rust -/// ```should_panic -/// assert!(false); -/// ``` -# fn foo() {} -``` - -The `no_run` attribute will compile your code but not run it. This is -important for examples such as "Here's how to retrieve a web page," -which you would want to ensure compiles, but might be run in a test -environment that has no network access. This attribute can also be -used to demonstrate code snippets that can cause Undefined Behavior. - -```rust -/// ```no_run -/// loop { -/// println!("Hello, world"); -/// } -/// ``` -# fn foo() {} -``` - -`compile_fail` tells `rustdoc` that the compilation should fail. If it -compiles, then the test will fail. However, please note that code failing -with the current Rust release may work in a future release, as new features -are added. - -```rust -/// ```compile_fail -/// let x = 5; -/// x += 2; // shouldn't compile! -/// ``` -# fn foo() {} -``` - -`edition2015`, `edition2018` and `edition2021` tell `rustdoc` -that the code sample should be compiled using the respective edition of Rust. - -```rust -/// Only runs on the 2018 edition. -/// -/// ```edition2018 -/// let result: Result = try { -/// "1".parse::()? -/// + "2".parse::()? -/// + "3".parse::()? -/// }; -/// ``` -# fn foo() {} -``` - -## Syntax reference - -The *exact* syntax for code blocks, including the edge cases, can be found -in the [Fenced Code Blocks](https://spec.commonmark.org/0.29/#fenced-code-blocks) -section of the CommonMark specification. - -Rustdoc also accepts *indented* code blocks as an alternative to fenced -code blocks: instead of surrounding your code with three backticks, you -can indent each line by four or more spaces. - -``````markdown - let foo = "foo"; - assert_eq!(foo, "foo"); -`````` - -These, too, are documented in the CommonMark specification, in the -[Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks) -section. - -However, it's preferable to use fenced code blocks over indented code blocks. -Not only are fenced code blocks considered more idiomatic for Rust code, -but there is no way to use attributes such as `ignore` or `should_panic` with -indented code blocks. - -### Include items only when collecting doctests - -Rustdoc's documentation tests can do some things that regular unit tests can't, so it can -sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in -documentation. To this end, Rustdoc allows you to have certain items only appear when it's -collecting doctests, so you can utilize doctest functionality without forcing the test to appear in -docs, or to find an arbitrary private item to include it on. - -When compiling a crate for use in doctests (with `--test` option), `rustdoc` will set `#[cfg(doctest)]`. -Note that they will still link against only the public items of your crate; if you need to test -private items, you need to write a unit test. - -In this example, we're adding doctests that we know won't compile, to verify that our struct can -only take in valid data: - -```rust -/// We have a struct here. Remember it doesn't accept negative numbers! -pub struct MyStruct(pub usize); - -/// ```compile_fail -/// let x = my_crate::MyStruct(-5); -/// ``` -#[cfg(doctest)] -pub struct MyStructOnlyTakesUsize; -``` - -Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate -API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while `rustdoc` is -collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc, -but is hidden from the public documentation. - -Another possible use of `#[cfg(doctest)]` is to test doctests that are included in your README file -without including it in your main documentation. For example, you could write this into your -`lib.rs` to test your README as part of your doctests: - -```rust,no_run -#[doc = include_str!("../README.md")] -#[cfg(doctest)] -pub struct ReadmeDoctests; -``` - -This will include your README as documentation on the hidden struct `ReadmeDoctests`, which will -then be tested alongside the rest of your doctests. diff --git a/src/doc/rustdoc/src/how-to-read-rustdoc.md b/src/doc/rustdoc/src/how-to-read-rustdoc.md index 99724d859ee..098bc1879b5 100644 --- a/src/doc/rustdoc/src/how-to-read-rustdoc.md +++ b/src/doc/rustdoc/src/how-to-read-rustdoc.md @@ -26,7 +26,7 @@ At the top is some at-a-glance info and controls: - a button to collapse or expand the top-level documentation for that item (`[+]` or `[-]`), - a link to the source code (`[src]`), - if [configured](the-doc-attribute.html#html_no_source), + if [configured](write-documentation/the-doc-attribute.html#html_no_source), and present (the source may not be available if the documentation was created with `cargo doc --no-deps`), - and the version in which the item became stable, @@ -52,7 +52,7 @@ For example, when looking at documentation for the crate root, it shows all the crates documented in the documentation bundle, and quick links to the modules, structs, traits, functions, and macros available from the current crate. -At the top, it displays a [configurable logo](the-doc-attribute.html#html_logo_url) +At the top, it displays a [configurable logo](write-documentation/the-doc-attribute.html#html_logo_url) alongside the current crate's name and version, or the current item whose documentation is being displayed. diff --git a/src/doc/rustdoc/src/linking-to-items-by-name.md b/src/doc/rustdoc/src/linking-to-items-by-name.md deleted file mode 100644 index 6ca1d1153b4..00000000000 --- a/src/doc/rustdoc/src/linking-to-items-by-name.md +++ /dev/null @@ -1,143 +0,0 @@ -# Linking to items by name - -Rustdoc is capable of directly linking to other rustdoc pages using the path of -the item as a link. This is referred to as an 'intra-doc link'. - -For example, in the following code all of the links will link to the rustdoc page for `Bar`: - -```rust -/// This struct is not [Bar] -pub struct Foo1; - -/// This struct is also not [bar](Bar) -pub struct Foo2; - -/// This struct is also not [bar][b] -/// -/// [b]: Bar -pub struct Foo3; - -/// This struct is also not [`Bar`] -pub struct Foo4; - -/// This struct *is* [`Bar`]! -pub struct Bar; -``` - -Unlike normal Markdown, `[bar][Bar]` syntax is also supported without needing a -`[Bar]: ...` reference link. - -Backticks around the link will be stripped, so ``[`Option`]`` will correctly -link to `Option`. - -## Valid links - -You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and -`crate`. Associated items (functions, types, and constants) are supported, but [not for blanket -trait implementations][#79682]. Rustdoc also supports linking to all primitives listed in -[the standard library documentation](../std/index.html#primitives). - -[#79682]: https://github.com/rust-lang/rust/pull/79682 - -You can also refer to items with generic parameters like `Vec`. The link will -resolve as if you had written ``[`Vec`](Vec)``. Fully-qualified syntax (for example, -`::into_iter()`) is [not yet supported][fqs-issue], however. - -[fqs-issue]: https://github.com/rust-lang/rust/issues/74563 - -```rust,edition2018 -use std::sync::mpsc::Receiver; - -/// This is a version of [`Receiver`] with support for [`std::future`]. -/// -/// You can obtain a [`std::future::Future`] by calling [`Self::recv()`]. -pub struct AsyncReceiver { - sender: Receiver -} - -impl AsyncReceiver { - pub async fn recv() -> T { - unimplemented!() - } -} -``` - -Rustdoc allows using URL fragment specifiers, just like a normal link: - -```rust -/// This is a special implementation of [positional parameters]. -/// -/// [positional parameters]: std::fmt#formatting-parameters -struct MySpecialFormatter; -``` - -## Namespaces and Disambiguators - -Paths in Rust have three namespaces: type, value, and macro. Item names must be unique within -their namespace, but can overlap with items in other namespaces. In case of ambiguity, -rustdoc will warn about the ambiguity and suggest a disambiguator. - -```rust -/// See also: [`Foo`](struct@Foo) -struct Bar; - -/// This is different from [`Foo`](fn@Foo) -struct Foo {} - -fn Foo() {} -``` - -These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be -rendered as `Foo`. - -You can also disambiguate for functions by adding `()` after the function name, -or for macros by adding `!` after the macro name: - -```rust -/// This is different from [`foo!`] -fn foo() {} - -/// This is different from [`foo()`] -macro_rules! foo { - () => {} -} -``` - -## Warnings, re-exports, and scoping - -Links are resolved in the scope of the module where the item is defined, even -when the item is re-exported. If a link from another crate fails to resolve, no -warning is given. - -```rust,edition2018 -mod inner { - /// Link to [f()] - pub struct S; - pub fn f() {} -} -pub use inner::S; // the link to `f` will still resolve correctly -``` - -When re-exporting an item, rustdoc allows adding additional documentation to it. -That additional documentation will be resolved in the scope of the re-export, not -the original, allowing you to link to items in the new crate. The new links -will still give a warning if they fail to resolve. - -```rust -/// See also [foo()] -pub use std::process::Command; - -pub fn foo() {} -``` - -This is especially useful for proc-macros, which must always be defined in their own dedicated crate. - -Note: Because of how `macro_rules!` macros are scoped in Rust, the intra-doc links of a -`macro_rules!` macro will be resolved [relative to the crate root][#72243], as opposed to the -module it is defined in. - -If links do not look 'sufficiently like' an intra-doc link, they will be ignored and no warning -will be given, even if the link fails to resolve. For example, any link containing `/` or `[]` -characters will be ignored. - -[#72243]: https://github.com/rust-lang/rust/issues/72243 diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md index 1773c15464a..bff01d7cb7c 100644 --- a/src/doc/rustdoc/src/lints.md +++ b/src/doc/rustdoc/src/lints.md @@ -13,11 +13,11 @@ Note that, except for `missing_docs`, these lints are only available when runnin Here is the list of the lints provided by `rustdoc`: -## broken_intra_doc_links +## `broken_intra_doc_links` This lint **warns by default**. This lint detects when an [intra-doc link] fails to be resolved. For example: -[intra-doc link]: linking-to-items-by-name.md +[intra-doc link]: write-documentation/linking-to-items-by-name.md ```rust /// I want to link to [`Nonexistent`] but it doesn't exist! @@ -64,7 +64,7 @@ help: to link to the function, add parentheses ``` -## private_intra_doc_links +## `private_intra_doc_links` This lint **warns by default**. This lint detects when [intra-doc links] from public to private items. For example: @@ -104,9 +104,9 @@ warning: public documentation for `public` links to private item `private` = note: this link resolves only because you passed `--document-private-items`, but will break without ``` -[intra-doc links]: linking-to-items-by-name.html +[intra-doc links]: write-documentation/linking-to-items-by-name.md -## missing_docs +## `missing_docs` This lint is **allowed by default**. It detects items missing documentation. For example: @@ -130,7 +130,7 @@ warning: missing documentation for a function Note that unlike other rustdoc lints, this lint is also available from `rustc` directly. -## missing_crate_level_docs +## `missing_crate_level_docs` This lint is **allowed by default**. It detects if there is no documentation at the crate root. For example: @@ -154,7 +154,7 @@ warning in the future. This is intended as a means to introduce new users on get started, without providing overwhelming warnings like `missing_docs` might. -## missing_doc_code_examples +## `missing_doc_code_examples` This lint is **allowed by default** and is **nightly-only**. It detects when a documentation block is missing a code example. For example: @@ -190,7 +190,7 @@ To fix the lint, you need to add a code example into the documentation block: pub fn no_code_example() {} ``` -## private_doc_tests +## `private_doc_tests` This lint is **allowed by default**. It detects documentation tests when they are on a private item. For example: @@ -223,7 +223,7 @@ warning: Documentation test in private item | |___________^ ``` -## invalid_codeblock_attributes +## `invalid_codeblock_attributes` This lint **warns by default**. It detects code block attributes in documentation examples that have potentially mis-typed values. For example: @@ -259,7 +259,7 @@ warning: unknown attribute `should-panic`. Did you mean `should_panic`? In the example above, the correct form is `should_panic`. This helps detect typo mistakes for some common attributes. -## invalid_html_tags +## `invalid_html_tags` This lint is **allowed by default** and is **nightly-only**. It detects unclosed or invalid HTML tags. For example: @@ -298,7 +298,7 @@ warning: unclosed HTML tag `h1` warning: 2 warnings emitted ``` -## invalid_rust_codeblocks +## `invalid_rust_codeblocks` This lint **warns by default**. It detects Rust code blocks in documentation examples that are invalid (e.g. empty, not parsable as Rust). For example: @@ -342,7 +342,7 @@ warning: could not parse code block as Rust code = note: error from rustc: unterminated character literal ``` -## bare_urls +## `bare_urls` This lint is **warn-by-default**. It detects URLs which are not links. For example: diff --git a/src/doc/rustdoc/src/passes.md b/src/doc/rustdoc/src/passes.md deleted file mode 100644 index c3c3fd3068e..00000000000 --- a/src/doc/rustdoc/src/passes.md +++ /dev/null @@ -1,11 +0,0 @@ -# Passes - -Rustdoc has a concept called "passes". These are transformations that -`rustdoc` runs on your documentation before producing its final output. - -Customizing passes is **deprecated**. The available passes are not considered stable and may -change in any release. - -In the past the most common use case for customizing passes was to omit the `strip-private` pass. -You can do this more easily, and without risk of the pass being changed, by passing -[`--document-private-items`](./unstable-features.md#--document-private-items). diff --git a/src/doc/rustdoc/src/the-doc-attribute.md b/src/doc/rustdoc/src/the-doc-attribute.md deleted file mode 100644 index c5cc84022e3..00000000000 --- a/src/doc/rustdoc/src/the-doc-attribute.md +++ /dev/null @@ -1,276 +0,0 @@ -# The `#[doc]` attribute - -The `#[doc]` attribute lets you control various aspects of how `rustdoc` does -its job. - -The most basic function of `#[doc]` is to handle the actual documentation -text. That is, `///` is syntax sugar for `#[doc]`. This means that these two -are the same: - -```rust,no_run -/// This is a doc comment. -#[doc = " This is a doc comment."] -# fn f() {} -``` - -(Note the leading space in the attribute version.) - -In most cases, `///` is easier to use than `#[doc]`. One case where the latter is easier is -when generating documentation in macros; the `collapse-docs` pass will combine multiple -`#[doc]` attributes into a single doc comment, letting you generate code like this: - -```rust,no_run -#[doc = "This is"] -#[doc = " a "] -#[doc = "doc comment"] -# fn f() {} -``` - -Which can feel more flexible. Note that this would generate this: - -```rust,no_run -#[doc = "This is\n a \ndoc comment"] -# fn f() {} -``` - -but given that docs are rendered via Markdown, it will remove these newlines. - -Another use case is for including external files as documentation: - -```rust,no_run -#[doc = include_str!("../README.md")] -# fn f() {} -``` - -The `doc` attribute has more options though! These don't involve the text of -the output, but instead, various aspects of the presentation of the output. -We've split them into two kinds below: attributes that are useful at the -crate level, and ones that are useful at the item level. - -## At the crate level - -These options control how the docs look at a crate level. - -### `html_favicon_url` - -This form of the `doc` attribute lets you control the favicon of your docs. - -```rust,no_run -#![doc(html_favicon_url = "https://example.com/favicon.ico")] -``` - -This will put `` into your docs, where -the string for the attribute goes into the `{}`. - -If you don't use this attribute, there will be no favicon. - -### `html_logo_url` - -This form of the `doc` attribute lets you control the logo in the upper -left hand side of the docs. - -```rust,no_run -#![doc(html_logo_url = "https://example.com/logo.jpg")] -``` - -This will put `logo` into -your docs, where the string for the attribute goes into the `{}`. - -If you don't use this attribute, there will be no logo. - -### `html_playground_url` - -This form of the `doc` attribute lets you control where the "run" buttons -on your documentation examples make requests to. - -```rust,no_run -#![doc(html_playground_url = "https://playground.example.com/")] -``` - -Now, when you press "run", the button will make a request to this domain. - -If you don't use this attribute, there will be no run buttons. - -### `issue_tracker_base_url` - -This form of the `doc` attribute is mostly only useful for the standard library; -When a feature is unstable, an issue number for tracking the feature must be -given. `rustdoc` uses this number, plus the base URL given here, to link to -the tracking issue. - -```rust,no_run -#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -``` - -### `html_root_url` - -The `#[doc(html_root_url = "…")]` attribute value indicates the URL for -generating links to external crates. When rustdoc needs to generate a link to -an item in an external crate, it will first check if the extern crate has been -documented locally on-disk, and if so link directly to it. Failing that, it -will use the URL given by the `--extern-html-root-url` command-line flag if -available. If that is not available, then it will use the `html_root_url` -value in the extern crate if it is available. If that is not available, then -the extern items will not be linked. - -```rust,no_run -#![doc(html_root_url = "https://docs.rs/serde/1.0")] -``` - -### `html_no_source` - -By default, `rustdoc` will include the source code of your program, with links -to it in the docs. But if you include this: - -```rust,no_run -#![doc(html_no_source)] -``` - -it will not. - -### `test(no_crate_inject)` - -By default, `rustdoc` will automatically add a line with `extern crate my_crate;` into each doctest. -But if you include this: - -```rust,no_run -#![doc(test(no_crate_inject))] -``` - -it will not. - -### `test(attr(...))` - -This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For -example, if you want your doctests to fail if they produce any warnings, you could add this: - -```rust,no_run -#![doc(test(attr(deny(warnings))))] -``` - -## At the item level - -These forms of the `#[doc]` attribute are used on individual items, to control how -they are documented. - -### `inline` and `no_inline` - - - -These attributes are used on `use` statements, and control where the documentation shows -up. For example, consider this Rust code: - -```rust,no_run -pub use bar::Bar; - -/// bar docs -pub mod bar { - /// the docs for Bar - pub struct Bar; -} -# fn main() {} -``` - -The documentation will generate a "Re-exports" section, and say `pub use bar::Bar;`, where -`Bar` is a link to its page. - -If we change the `use` line like this: - -```rust,no_run -#[doc(inline)] -pub use bar::Bar; -# pub mod bar { pub struct Bar; } -# fn main() {} -``` - -Instead, `Bar` will appear in a `Structs` section, just like `Bar` was defined at the -top level, rather than `pub use`'d. - -Let's change our original example, by making `bar` private: - -```rust,no_run -pub use bar::Bar; - -/// bar docs -mod bar { - /// the docs for Bar - pub struct Bar; -} -# fn main() {} -``` - -Here, because `bar` is not public, `Bar` wouldn't have its own page, so there's nowhere -to link to. `rustdoc` will inline these definitions, and so we end up in the same case -as the `#[doc(inline)]` above; `Bar` is in a `Structs` section, as if it were defined at -the top level. If we add the `no_inline` form of the attribute: - -```rust,no_run -#[doc(no_inline)] -pub use bar::Bar; - -/// bar docs -mod bar { - /// the docs for Bar - pub struct Bar; -} -# fn main() {} -``` - -Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere. - -One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will -not eagerly inline it as a module unless you add `#[doc(inline)]`. - -### `hidden` - - - -Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless -the `strip-hidden` pass is removed. - -### `alias` - -This attribute adds an alias in the search index. - -Let's take an example: - -```rust,no_run -#[doc(alias = "TheAlias")] -pub struct SomeType; -``` - -So now, if you enter "TheAlias" in the search, it'll display `SomeType`. -Of course, if you enter `SomeType` it'll return `SomeType` as expected! - -#### FFI example - -This doc attribute is especially useful when writing bindings for a C library. -For example, let's say we have a C function that looks like this: - -```c -int lib_name_do_something(Obj *obj); -``` - -It takes a pointer to an `Obj` type and returns an integer. In Rust, it might -be written like this: - -```ignore (using non-existing ffi types) -pub struct Obj { - inner: *mut ffi::Obj, -} - -impl Obj { - pub fn do_something(&mut self) -> i32 { - unsafe { ffi::lib_name_do_something(self.inner) } - } -} -``` - -The function has been turned into a method to make it more convenient to use. -However, if you want to look for the Rust equivalent of `lib_name_do_something`, -you have no way to do so. - -To get around this limitation, we just add `#[doc(alias = "lib_name_do_something")]` -on the `do_something` method and then it's all good! -Users can now look for `lib_name_do_something` in our crate directly and find -`Obj::do_something`. diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 141d5d2d2b2..537ab48bbfc 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -22,7 +22,7 @@ As detailed in [the chapter on documentation tests][doctest-attributes], you can nightly, you can optionally add an error number to state that a doctest should emit a specific error number: -[doctest-attributes]: documentation-tests.html#attributes +[doctest-attributes]: write-documentation/documentation-tests.html#attributes ``````markdown ```compile_fail,E0044 @@ -45,6 +45,8 @@ and enabled with a `#![feature(...)]` attribute in your crate. ### `#[doc(cfg)]`: Recording what platforms or features are required for code to be present + * Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781) + You can use `#[doc(cfg(...))]` to tell Rustdoc exactly which platform items appear on. This has two effects: @@ -86,6 +88,8 @@ Book][unstable-doc-cfg] and [its tracking issue][issue-doc-cfg]. ### `doc_auto_cfg`: Automatically generate `#[doc(cfg)]` + * Tracking issue: [#43781](https://github.com/rust-lang/rust/issues/43781) + `doc_auto_cfg` is an extension to the `#[doc(cfg)]` feature. With it, you don't need to add `#[doc(cfg(...)]` anymore unless you want to override the default behaviour. So if we take the previous source code: @@ -123,6 +127,8 @@ And `doc` won't show up anymore! ### Adding your trait to the "Notable traits" dialog + * Tracking issue: [#45040](https://github.com/rust-lang/rust/issues/45040) + Rustdoc keeps a list of a few traits that are believed to be "fundamental" to types that implement them. These traits are intended to be the primary interface for their implementers, and are often most of the API available to be documented @@ -146,6 +152,8 @@ and [its tracking issue][issue-notable_trait]. ### Exclude certain dependencies from documentation + * Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027) + The standard library uses several dependencies which, in turn, use several types and traits from the standard library. In addition, there are several compiler-internal crates that are not considered to be part of the official standard library, and thus would be a distraction to include in @@ -164,8 +172,7 @@ Book][unstable-masked] and [its tracking issue][issue-masked]. [unstable-masked]: ../unstable-book/language-features/doc-masked.html [issue-masked]: https://github.com/rust-lang/rust/issues/44027 - -## Document primitives +### Document primitives This is for Rust compiler internal use only. @@ -174,7 +181,7 @@ attributes. The `#[doc(primitive)]` attribute is used by the standard library to to generate documentation for primitive types, and requires `#![feature(rustdoc_internals)]` to enable. -## Document keywords +### Document keywords This is for Rust compiler internal use only. @@ -199,6 +206,8 @@ the flag in question to Rustdoc on the command-line. To do this from Cargo, you ### `--markdown-before-content`: include rendered Markdown before the content + * Tracking issue: [#44027](https://github.com/rust-lang/rust/issues/44027) + Using this flag looks like this: ```bash @@ -241,7 +250,7 @@ attribute][doc-playground]. Please be aware that the official Rust Playground at https://play.rust-lang.org does not have every crate available, so if your examples require your crate, make sure the playground you provide has your crate available. -[doc-playground]: the-doc-attribute.html#html_playground_url +[doc-playground]: write-documentation/the-doc-attribute.html#html_playground_url If both `--playground-url` and `--markdown-playground-url` are present when rendering a standalone Markdown file, the URL given to `--markdown-playground-url` will take precedence. If both @@ -279,6 +288,8 @@ between compilations. ### `--resource-suffix`: modifying the name of CSS/JavaScript in crate docs + * Tracking issue: [#54765](https://github.com/rust-lang/rust/issues/54765) + Using this flag looks like this: ```bash @@ -331,6 +342,24 @@ Using `index-page` option enables `enable-index-page` option as well. This feature allows the generation of a default index-page which lists the generated crates. +### `--nocapture`: disable output capture for test + +When this flag is used with `--test`, the output (stdout and stderr) of your tests won't be +captured by rustdoc. Instead, the output will be directed to your terminal, +as if you had run the test executable manually. This is especially useful +for debugging your tests! + +### `--check`: only checks the documentation + +When this flag is supplied, rustdoc will type check and lint your code, but will not generate any +documentation or run your doctests. + +Using this flag looks like: + +```bash +rustdoc -Z unstable-options --check src/lib.rs +``` + ### `--static-root-path`: control how static files are loaded in HTML output Using this flag looks like this: @@ -348,6 +377,8 @@ renamed with `--resource-suffix` will load from the given path. ### `--persist-doctests`: persist doctest executables after running + * Tracking issue: [#56925](https://github.com/rust-lang/rust/issues/56925) + Using this flag looks like this: ```bash @@ -360,6 +391,8 @@ with this option, you can keep those binaries around for farther testing. ### `--show-coverage`: calculate the percentage of items with documentation + * Tracking issue: [#58154](https://github.com/rust-lang/rust/issues/58154) + Using this flag looks like this: ```bash @@ -438,6 +471,8 @@ information. ### `--enable-per-target-ignores`: allow `ignore-foo` style filters for doctests + * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) + Using this flag looks like this: ```bash @@ -471,6 +506,8 @@ override `ignore`. ### `--runtool`, `--runtool-arg`: program to run tests with; args to pass to it + * Tracking issue: [#64245](https://github.com/rust-lang/rust/issues/64245) + Using these options looks like this: ```bash @@ -488,6 +525,8 @@ Another use case would be to run a test inside an emulator, or through a Virtual ### `--with-examples`: include examples of uses of items as documentation + * Tracking issue: [#88791](https://github.com/rust-lang/rust/issues/88791) + This option, combined with `--scrape-examples-target-crate` and `--scrape-examples-output-path`, is used to implement the functionality in [RFC #3123](https://github.com/rust-lang/rfcs/pull/3123). Uses of an item (currently @@ -515,6 +554,8 @@ add the `--scrape-tests` flag. ### `--check-cfg`: check configuration flags + * Tracking issue: [#82450](https://github.com/rust-lang/rust/issues/82450) + This flag accepts the same values as `rustc --check-cfg`, and uses it to check configuration flags. Using this flag looks like this: diff --git a/src/doc/rustdoc/src/website-features.md b/src/doc/rustdoc/src/website-features.md deleted file mode 100644 index 5fade4e84a9..00000000000 --- a/src/doc/rustdoc/src/website-features.md +++ /dev/null @@ -1,25 +0,0 @@ -# Website features - -These features are about using the website generated by `rustdoc`. - -## Custom search engines - -If you find yourself often referencing online Rust docs you might enjoy using a custom search -engine. This allows you to use the navigation bar directly to search a `rustdoc` website. -Most browsers support this feature by letting you define a URL template containing `%s` -which will be substituted for the search term. As an example, for the standard library you could use -this template: - -```text -https://doc.rust-lang.org/stable/std/?search=%s -``` - -Note that this will take you to a results page listing all matches. If you want to navigate to the first -result right away (which is often the best match) use the following instead: - -```text -https://doc.rust-lang.org/stable/std/?search=%s&go_to_first=true -``` - -This URL adds the `go_to_first=true` query parameter which can be appended to any `rustdoc` search URL -to automatically go to the first result. diff --git a/src/doc/rustdoc/src/what-to-include.md b/src/doc/rustdoc/src/what-to-include.md deleted file mode 100644 index 2a6b62ebfd5..00000000000 --- a/src/doc/rustdoc/src/what-to-include.md +++ /dev/null @@ -1,125 +0,0 @@ -# What to include (and exclude) - -It is easy to say everything must be documented in a project and often times -that is correct, but how can we get there, and are there things that don't -belong? - -At the top of the `src/lib.rs` or `main.rs` file in your binary project, include -the following attribute: - -```rust -#![warn(missing_docs)] -``` - -Now run `cargo doc` and examine the output. Here's a sample: - -```text - Documenting docdemo v0.1.0 (/Users/username/docdemo) -warning: missing documentation for the crate - --> src/main.rs:1:1 - | -1 | / #![warn(missing_docs)] -2 | | -3 | | fn main() { -4 | | println!("Hello, world!"); -5 | | } - | |_^ - | -note: the lint level is defined here - --> src/main.rs:1:9 - | -1 | #![warn(missing_docs)] - | ^^^^^^^^^^^^ - -warning: 1 warning emitted - - Finished dev [unoptimized + debuginfo] target(s) in 2.96s -``` - -As a library author, adding the lint `#![deny(missing_docs)]` is a great way to -ensure the project does not drift away from being documented well, and -`#![warn(missing_docs)]` is a good way to move towards comprehensive -documentation. In addition to docs, `#![deny(missing_doc_code_examples)]` -ensures each function contains a usage example. In our example above, the -warning is resolved by adding crate level documentation. - -There are more lints in the upcoming chapter [Lints][rustdoc-lints]. - -## Examples - -Of course this is contrived to be simple, but part of the power of documentation -is showing code that is easy to follow, rather than being realistic. Docs often -take shortcuts with error handling because examples can become complicated to -follow with all the necessary set up required for a simple example. - -`Async` is a good example of this. In order to execute an `async` example, an -executor needs to be available. Examples will often shortcut this, and leave -users to figure out how to put the `async` code into their own runtime. - -It is preferred that `unwrap()` not be used inside an example, and some of the -error handling components be hidden if they make the example too difficult to -follow. - -``````text -/// Example -/// ```rust -/// let fourtytwo = "42".parse::()?; -/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10); -/// ``` -`````` - -When rustdoc wraps that in a main function, it will fail to compile because the -`ParseIntError` trait is not implemented. In order to help both your audience -and your test suite, this example needs some additional code: - -``````text -/// Example -/// ```rust -/// # main() -> Result<(), std::num::ParseIntError> { -/// let fortytwo = "42".parse::()?; -/// println!("{} + 10 = {}", fortytwo, fortytwo+10); -/// # Ok(()) -/// # } -/// ``` -`````` - -The example is the same on the doc page, but has that extra information -available to anyone trying to use your crate. More about tests in the -upcoming [Documentation tests] chapter. - -## What to Exclude - -Certain parts of your public interface may be included by default in the output -of rustdoc. The attribute `#[doc(hidden)]` can hide implementation details -to encourage idiomatic use of the crate. - -For example, an internal `macro!` that makes the crate easier to implement can -become a footgun for users when it appears in the public documentation. An -internal `Error` type may exist, and `impl` details should be hidden, as -detailed in the [API Guidelines]. - -## Customizing the output - -It is possible to pass a custom css file to `rustdoc` and style the -documentation. - -```bash -rustdoc --extend-css custom.css src/lib.rs -``` - -A good example of using this feature to create a dark theme is documented [on -this blog]. Just remember, dark theme is already included in the rustdoc output -by clicking on the paintbrush. Adding additional options to the themes are -as easy as creating a custom theme `.css` file and using the following syntax: - -```bash -rustdoc --theme awesome.css src/lib.rs -``` - -Here is an example of a new theme, [Ayu]. - -[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/css/themes/ayu.css -[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden -[Documentation tests]: documentation-tests.md -[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme -[rustdoc-lints]: lints.md diff --git a/src/doc/rustdoc/src/write-documentation/documentation-tests.md b/src/doc/rustdoc/src/write-documentation/documentation-tests.md new file mode 100644 index 00000000000..1cb5b049df4 --- /dev/null +++ b/src/doc/rustdoc/src/write-documentation/documentation-tests.md @@ -0,0 +1,445 @@ +# Documentation tests + +`rustdoc` supports executing your documentation examples as tests. This makes sure +that examples within your documentation are up to date and working. + +The basic idea is this: + +```rust,no_run +/// # Examples +/// +/// ``` +/// let x = 5; +/// ``` +# fn f() {} +``` + +The triple backticks start and end code blocks. If this were in a file named `foo.rs`, +running `rustdoc --test foo.rs` will extract this example, and then run it as a test. + +Please note that by default, if no language is set for the block code, rustdoc +assumes it is Rust code. So the following: + +``````markdown +```rust +let x = 5; +``` +`````` + +is strictly equivalent to: + +``````markdown +``` +let x = 5; +``` +`````` + +There's some subtlety though! Read on for more details. + +## Passing or failing a doctest + +Like regular unit tests, regular doctests are considered to "pass" +if they compile and run without panicking. +So if you want to demonstrate that some computation gives a certain result, +the `assert!` family of macros works the same as other Rust code: + +```rust +let foo = "foo"; +assert_eq!(foo, "foo"); +``` + +This way, if the computation ever returns something different, +the code panics and the doctest fails. + +## Pre-processing examples + +In the example above, you'll note something strange: there's no `main` +function! Forcing you to write `main` for every example, no matter how small, +adds friction and clutters the output. So `rustdoc` processes your examples +slightly before running them. Here's the full algorithm `rustdoc` uses to +preprocess examples: + +1. Some common `allow` attributes are inserted, including + `unused_variables`, `unused_assignments`, `unused_mut`, + `unused_attributes`, and `dead_code`. Small examples often trigger + these lints. +2. Any attributes specified with `#![doc(test(attr(...)))]` are added. +3. Any leading `#![foo]` attributes are left intact as crate attributes. +4. If the example does not contain `extern crate`, and + `#![doc(test(no_crate_inject))]` was not specified, then `extern crate + ;` is inserted (note the lack of `#[macro_use]`). +5. Finally, if the example does not contain `fn main`, the remainder of the + text is wrapped in `fn main() { your_code }`. + +For more about that caveat in rule 4, see "Documenting Macros" below. + +## Hiding portions of the example + +Sometimes, you need some setup code, or other things that would distract +from your example, but are important to make the tests work. Consider +an example block that looks like this: + +```rust,no_run +/// ``` +/// /// Some documentation. +/// # fn foo() {} // this function will be hidden +/// println!("Hello, World!"); +/// ``` +# fn f() {} +``` + +It will render like this: + +```rust +/// Some documentation. +# fn foo() {} +println!("Hello, World!"); +``` + +Yes, that's right: you can add lines that start with `# `, and they will +be hidden from the output, but will be used when compiling your code. You +can use this to your advantage. In this case, documentation comments need +to apply to some kind of function, so if I want to show you just a +documentation comment, I need to add a little function definition below +it. At the same time, it's only there to satisfy the compiler, so hiding +it makes the example more clear. You can use this technique to explain +longer examples in detail, while still preserving the testability of your +documentation. + +For example, imagine that we wanted to document this code: + +```rust +let x = 5; +let y = 6; +println!("{}", x + y); +``` + +We might want the documentation to end up looking like this: + +> First, we set `x` to five: +> +> ```rust +> let x = 5; +> # let y = 6; +> # println!("{}", x + y); +> ``` +> +> Next, we set `y` to six: +> +> ```rust +> # let x = 5; +> let y = 6; +> # println!("{}", x + y); +> ``` +> +> Finally, we print the sum of `x` and `y`: +> +> ```rust +> # let x = 5; +> # let y = 6; +> println!("{}", x + y); +> ``` + +To keep each code block testable, we want the whole program in each block, but +we don't want the reader to see every line every time. Here's what we put in +our source code: + +``````markdown +First, we set `x` to five: + +``` +let x = 5; +# let y = 6; +# println!("{}", x + y); +``` + +Next, we set `y` to six: + +``` +# let x = 5; +let y = 6; +# println!("{}", x + y); +``` + +Finally, we print the sum of `x` and `y`: + +``` +# let x = 5; +# let y = 6; +println!("{}", x + y); +``` +`````` + +By repeating all parts of the example, you can ensure that your example still +compiles, while only showing the parts that are relevant to that part of your +explanation. + +The `#`-hiding of lines can be prevented by using two consecutive hashes +`##`. This only needs to be done with the first `#` which would've +otherwise caused hiding. If we have a string literal like the following, +which has a line that starts with a `#`: + +```rust +let s = "foo +## bar # baz"; +``` + +We can document it by escaping the initial `#`: + +```text +/// let s = "foo +/// ## bar # baz"; +``` + + +## Using `?` in doc tests + +When writing an example, it is rarely useful to include a complete error +handling, as it would add significant amounts of boilerplate code. Instead, you +may want the following: + +```rust,no_run +/// ``` +/// use std::io; +/// let mut input = String::new(); +/// io::stdin().read_line(&mut input)?; +/// ``` +# fn f() {} +``` + +The problem is that `?` returns a `Result` and test functions don't +return anything, so this will give a mismatched types error. + +You can get around this limitation by manually adding a `main` that returns +`Result`, because `Result` implements the `Termination` trait: + +```rust,no_run +/// A doc test using ? +/// +/// ``` +/// use std::io; +/// +/// fn main() -> io::Result<()> { +/// let mut input = String::new(); +/// io::stdin().read_line(&mut input)?; +/// Ok(()) +/// } +/// ``` +# fn f() {} +``` + +Together with the `# ` from the section above, you arrive at a solution that +appears to the reader as the initial idea but works with doc tests: + +```rust,no_run +/// ``` +/// use std::io; +/// # fn main() -> io::Result<()> { +/// let mut input = String::new(); +/// io::stdin().read_line(&mut input)?; +/// # Ok(()) +/// # } +/// ``` +# fn f() {} +``` + +As of version 1.34.0, one can also omit the `fn main()`, but you will have to +disambiguate the error type: + +```rust,no_run +/// ``` +/// use std::io; +/// let mut input = String::new(); +/// io::stdin().read_line(&mut input)?; +/// # Ok::<(), io::Error>(()) +/// ``` +# fn f() {} +``` + +This is an unfortunate consequence of the `?` operator adding an implicit +conversion, so type inference fails because the type is not unique. Please note +that you must write the `(())` in one sequence without intermediate whitespace +so that `rustdoc` understands you want an implicit `Result`-returning function. + +## Showing warnings in doctests + +You can show warnings in doctests by running `rustdoc --test --test-args=--show-output` +(or, if you're using cargo, `cargo test --doc -- --show-output`). +By default, this will still hide `unused` warnings, since so many examples use private functions; +you can add `#![warn(unused)]` to the top of your example if you want to see unused variables or dead code warnings. +You can also use [`#![doc(test(attr(warn(unused))))]`][test-attr] in the crate root to enable warnings globally. + +[test-attr]: the-doc-attribute.md#testattr + +## Documenting macros + +Here’s an example of documenting a macro: + +```rust +/// Panic with a given message unless an expression evaluates to true. +/// +/// # Examples +/// +/// ``` +/// # #[macro_use] extern crate foo; +/// # fn main() { +/// panic_unless!(1 + 1 == 2, “Math is broken.”); +/// # } +/// ``` +/// +/// ```should_panic +/// # #[macro_use] extern crate foo; +/// # fn main() { +/// panic_unless!(true == false, “I’m broken.”); +/// # } +/// ``` +#[macro_export] +macro_rules! panic_unless { + ($condition:expr, $($rest:expr),+) => ({ if ! $condition { panic!($($rest),+); } }); +} +# fn main() {} +``` + +You’ll note three things: we need to add our own `extern crate` line, so that +we can add the `#[macro_use]` attribute. Second, we’ll need to add our own +`main()` as well (for reasons discussed above). Finally, a judicious use of +`#` to comment out those two things, so they don’t show up in the output. + +## Attributes + +Code blocks can be annotated with attributes that help `rustdoc` do the right +thing when testing your code: + +The `ignore` attribute tells Rust to ignore your code. This is almost never +what you want as it's the most generic. Instead, consider annotating it +with `text` if it's not code or using `#`s to get a working example that +only shows the part you care about. + +```rust +/// ```ignore +/// fn foo() { +/// ``` +# fn foo() {} +``` + +`should_panic` tells `rustdoc` that the code should compile correctly but +panic during execution. If the code doesn't panic, the test will fail. + +```rust +/// ```should_panic +/// assert!(false); +/// ``` +# fn foo() {} +``` + +The `no_run` attribute will compile your code but not run it. This is +important for examples such as "Here's how to retrieve a web page," +which you would want to ensure compiles, but might be run in a test +environment that has no network access. This attribute can also be +used to demonstrate code snippets that can cause Undefined Behavior. + +```rust +/// ```no_run +/// loop { +/// println!("Hello, world"); +/// } +/// ``` +# fn foo() {} +``` + +`compile_fail` tells `rustdoc` that the compilation should fail. If it +compiles, then the test will fail. However, please note that code failing +with the current Rust release may work in a future release, as new features +are added. + +```rust +/// ```compile_fail +/// let x = 5; +/// x += 2; // shouldn't compile! +/// ``` +# fn foo() {} +``` + +`edition2015`, `edition2018` and `edition2021` tell `rustdoc` +that the code sample should be compiled using the respective edition of Rust. + +```rust +/// Only runs on the 2018 edition. +/// +/// ```edition2018 +/// let result: Result = try { +/// "1".parse::()? +/// + "2".parse::()? +/// + "3".parse::()? +/// }; +/// ``` +# fn foo() {} +``` + +## Syntax reference + +The *exact* syntax for code blocks, including the edge cases, can be found +in the [Fenced Code Blocks](https://spec.commonmark.org/0.29/#fenced-code-blocks) +section of the CommonMark specification. + +Rustdoc also accepts *indented* code blocks as an alternative to fenced +code blocks: instead of surrounding your code with three backticks, you +can indent each line by four or more spaces. + +``````markdown + let foo = "foo"; + assert_eq!(foo, "foo"); +`````` + +These, too, are documented in the CommonMark specification, in the +[Indented Code Blocks](https://spec.commonmark.org/0.29/#indented-code-blocks) +section. + +However, it's preferable to use fenced code blocks over indented code blocks. +Not only are fenced code blocks considered more idiomatic for Rust code, +but there is no way to use attributes such as `ignore` or `should_panic` with +indented code blocks. + +### Include items only when collecting doctests + +Rustdoc's documentation tests can do some things that regular unit tests can't, so it can +sometimes be useful to extend your doctests with samples that wouldn't otherwise need to be in +documentation. To this end, Rustdoc allows you to have certain items only appear when it's +collecting doctests, so you can utilize doctest functionality without forcing the test to appear in +docs, or to find an arbitrary private item to include it on. + +When compiling a crate for use in doctests (with `--test` option), `rustdoc` will set `#[cfg(doctest)]`. +Note that they will still link against only the public items of your crate; if you need to test +private items, you need to write a unit test. + +In this example, we're adding doctests that we know won't compile, to verify that our struct can +only take in valid data: + +```rust +/// We have a struct here. Remember it doesn't accept negative numbers! +pub struct MyStruct(pub usize); + +/// ```compile_fail +/// let x = my_crate::MyStruct(-5); +/// ``` +#[cfg(doctest)] +pub struct MyStructOnlyTakesUsize; +``` + +Note that the struct `MyStructOnlyTakesUsize` here isn't actually part of your public crate +API. The use of `#[cfg(doctest)]` makes sure that this struct only exists while `rustdoc` is +collecting doctests. This means that its doctest is executed when `--test` is passed to rustdoc, +but is hidden from the public documentation. + +Another possible use of `#[cfg(doctest)]` is to test doctests that are included in your README file +without including it in your main documentation. For example, you could write this into your +`lib.rs` to test your README as part of your doctests: + +```rust,no_run +#[doc = include_str!("../README.md")] +#[cfg(doctest)] +pub struct ReadmeDoctests; +``` + +This will include your README as documentation on the hidden struct `ReadmeDoctests`, which will +then be tested alongside the rest of your doctests. diff --git a/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md new file mode 100644 index 00000000000..36bc312b9c9 --- /dev/null +++ b/src/doc/rustdoc/src/write-documentation/linking-to-items-by-name.md @@ -0,0 +1,143 @@ +# Linking to items by name + +Rustdoc is capable of directly linking to other rustdoc pages using the path of +the item as a link. This is referred to as an 'intra-doc link'. + +For example, in the following code all of the links will link to the rustdoc page for `Bar`: + +```rust +/// This struct is not [Bar] +pub struct Foo1; + +/// This struct is also not [bar](Bar) +pub struct Foo2; + +/// This struct is also not [bar][b] +/// +/// [b]: Bar +pub struct Foo3; + +/// This struct is also not [`Bar`] +pub struct Foo4; + +/// This struct *is* [`Bar`]! +pub struct Bar; +``` + +Unlike normal Markdown, `[bar][Bar]` syntax is also supported without needing a +`[Bar]: ...` reference link. + +Backticks around the link will be stripped, so ``[`Option`]`` will correctly +link to `Option`. + +## Valid links + +You can refer to anything in scope, and use paths, including `Self`, `self`, `super`, and +`crate`. Associated items (functions, types, and constants) are supported, but [not for blanket +trait implementations][#79682]. Rustdoc also supports linking to all primitives listed in +[the standard library documentation](../../std/index.html#primitives). + +[#79682]: https://github.com/rust-lang/rust/pull/79682 + +You can also refer to items with generic parameters like `Vec`. The link will +resolve as if you had written ``[`Vec`](Vec)``. Fully-qualified syntax (for example, +`::into_iter()`) is [not yet supported][fqs-issue], however. + +[fqs-issue]: https://github.com/rust-lang/rust/issues/74563 + +```rust,edition2018 +use std::sync::mpsc::Receiver; + +/// This is a version of [`Receiver`] with support for [`std::future`]. +/// +/// You can obtain a [`std::future::Future`] by calling [`Self::recv()`]. +pub struct AsyncReceiver { + sender: Receiver +} + +impl AsyncReceiver { + pub async fn recv() -> T { + unimplemented!() + } +} +``` + +Rustdoc allows using URL fragment specifiers, just like a normal link: + +```rust +/// This is a special implementation of [positional parameters]. +/// +/// [positional parameters]: std::fmt#formatting-parameters +struct MySpecialFormatter; +``` + +## Namespaces and Disambiguators + +Paths in Rust have three namespaces: type, value, and macro. Item names must be unique within +their namespace, but can overlap with items in other namespaces. In case of ambiguity, +rustdoc will warn about the ambiguity and suggest a disambiguator. + +```rust +/// See also: [`Foo`](struct@Foo) +struct Bar; + +/// This is different from [`Foo`](fn@Foo) +struct Foo {} + +fn Foo() {} +``` + +These prefixes will be stripped when displayed in the documentation, so `[struct@Foo]` will be +rendered as `Foo`. + +You can also disambiguate for functions by adding `()` after the function name, +or for macros by adding `!` after the macro name: + +```rust +/// This is different from [`foo!`] +fn foo() {} + +/// This is different from [`foo()`] +macro_rules! foo { + () => {} +} +``` + +## Warnings, re-exports, and scoping + +Links are resolved in the scope of the module where the item is defined, even +when the item is re-exported. If a link from another crate fails to resolve, no +warning is given. + +```rust,edition2018 +mod inner { + /// Link to [f()] + pub struct S; + pub fn f() {} +} +pub use inner::S; // the link to `f` will still resolve correctly +``` + +When re-exporting an item, rustdoc allows adding additional documentation to it. +That additional documentation will be resolved in the scope of the re-export, not +the original, allowing you to link to items in the new crate. The new links +will still give a warning if they fail to resolve. + +```rust +/// See also [foo()] +pub use std::process::Command; + +pub fn foo() {} +``` + +This is especially useful for proc-macros, which must always be defined in their own dedicated crate. + +Note: Because of how `macro_rules!` macros are scoped in Rust, the intra-doc links of a +`macro_rules!` macro will be resolved [relative to the crate root][#72243], as opposed to the +module it is defined in. + +If links do not look 'sufficiently like' an intra-doc link, they will be ignored and no warning +will be given, even if the link fails to resolve. For example, any link containing `/` or `[]` +characters will be ignored. + +[#72243]: https://github.com/rust-lang/rust/issues/72243 diff --git a/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md new file mode 100644 index 00000000000..25ef8b5bb91 --- /dev/null +++ b/src/doc/rustdoc/src/write-documentation/the-doc-attribute.md @@ -0,0 +1,276 @@ +# The `#[doc]` attribute + +The `#[doc]` attribute lets you control various aspects of how `rustdoc` does +its job. + +The most basic function of `#[doc]` is to handle the actual documentation +text. That is, `///` is syntax sugar for `#[doc]`. This means that these two +are the same: + +```rust,no_run +/// This is a doc comment. +#[doc = " This is a doc comment."] +# fn f() {} +``` + +(Note the leading space in the attribute version.) + +In most cases, `///` is easier to use than `#[doc]`. One case where the latter is easier is +when generating documentation in macros; the `collapse-docs` pass will combine multiple +`#[doc]` attributes into a single doc comment, letting you generate code like this: + +```rust,no_run +#[doc = "This is"] +#[doc = " a "] +#[doc = "doc comment"] +# fn f() {} +``` + +Which can feel more flexible. Note that this would generate this: + +```rust,no_run +#[doc = "This is\n a \ndoc comment"] +# fn f() {} +``` + +but given that docs are rendered via Markdown, it will remove these newlines. + +Another use case is for including external files as documentation: + +```rust,no_run +#[doc = include_str!("../../README.md")] +# fn f() {} +``` + +The `doc` attribute has more options though! These don't involve the text of +the output, but instead, various aspects of the presentation of the output. +We've split them into two kinds below: attributes that are useful at the +crate level, and ones that are useful at the item level. + +## At the crate level + +These options control how the docs look at a crate level. + +### `html_favicon_url` + +This form of the `doc` attribute lets you control the favicon of your docs. + +```rust,no_run +#![doc(html_favicon_url = "https://example.com/favicon.ico")] +``` + +This will put `` into your docs, where +the string for the attribute goes into the `{}`. + +If you don't use this attribute, there will be no favicon. + +### `html_logo_url` + +This form of the `doc` attribute lets you control the logo in the upper +left hand side of the docs. + +```rust,no_run +#![doc(html_logo_url = "https://example.com/logo.jpg")] +``` + +This will put `logo` into +your docs, where the string for the attribute goes into the `{}`. + +If you don't use this attribute, there will be no logo. + +### `html_playground_url` + +This form of the `doc` attribute lets you control where the "run" buttons +on your documentation examples make requests to. + +```rust,no_run +#![doc(html_playground_url = "https://playground.example.com/")] +``` + +Now, when you press "run", the button will make a request to this domain. + +If you don't use this attribute, there will be no run buttons. + +### `issue_tracker_base_url` + +This form of the `doc` attribute is mostly only useful for the standard library; +When a feature is unstable, an issue number for tracking the feature must be +given. `rustdoc` uses this number, plus the base URL given here, to link to +the tracking issue. + +```rust,no_run +#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] +``` + +### `html_root_url` + +The `#[doc(html_root_url = "…")]` attribute value indicates the URL for +generating links to external crates. When rustdoc needs to generate a link to +an item in an external crate, it will first check if the extern crate has been +documented locally on-disk, and if so link directly to it. Failing that, it +will use the URL given by the `--extern-html-root-url` command-line flag if +available. If that is not available, then it will use the `html_root_url` +value in the extern crate if it is available. If that is not available, then +the extern items will not be linked. + +```rust,no_run +#![doc(html_root_url = "https://docs.rs/serde/1.0")] +``` + +### `html_no_source` + +By default, `rustdoc` will include the source code of your program, with links +to it in the docs. But if you include this: + +```rust,no_run +#![doc(html_no_source)] +``` + +it will not. + +### `test(no_crate_inject)` + +By default, `rustdoc` will automatically add a line with `extern crate my_crate;` into each doctest. +But if you include this: + +```rust,no_run +#![doc(test(no_crate_inject))] +``` + +it will not. + +### `test(attr(...))` + +This form of the `doc` attribute allows you to add arbitrary attributes to all your doctests. For +example, if you want your doctests to fail if they produce any warnings, you could add this: + +```rust,no_run +#![doc(test(attr(deny(warnings))))] +``` + +## At the item level + +These forms of the `#[doc]` attribute are used on individual items, to control how +they are documented. + +### `inline` and `no_inline` + + + +These attributes are used on `use` statements, and control where the documentation shows +up. For example, consider this Rust code: + +```rust,no_run +pub use bar::Bar; + +/// bar docs +pub mod bar { + /// the docs for Bar + pub struct Bar; +} +# fn main() {} +``` + +The documentation will generate a "Re-exports" section, and say `pub use bar::Bar;`, where +`Bar` is a link to its page. + +If we change the `use` line like this: + +```rust,no_run +#[doc(inline)] +pub use bar::Bar; +# pub mod bar { pub struct Bar; } +# fn main() {} +``` + +Instead, `Bar` will appear in a `Structs` section, just like `Bar` was defined at the +top level, rather than `pub use`'d. + +Let's change our original example, by making `bar` private: + +```rust,no_run +pub use bar::Bar; + +/// bar docs +mod bar { + /// the docs for Bar + pub struct Bar; +} +# fn main() {} +``` + +Here, because `bar` is not public, `Bar` wouldn't have its own page, so there's nowhere +to link to. `rustdoc` will inline these definitions, and so we end up in the same case +as the `#[doc(inline)]` above; `Bar` is in a `Structs` section, as if it were defined at +the top level. If we add the `no_inline` form of the attribute: + +```rust,no_run +#[doc(no_inline)] +pub use bar::Bar; + +/// bar docs +mod bar { + /// the docs for Bar + pub struct Bar; +} +# fn main() {} +``` + +Now we'll have a `Re-exports` line, and `Bar` will not link to anywhere. + +One special case: In Rust 2018 and later, if you `pub use` one of your dependencies, `rustdoc` will +not eagerly inline it as a module unless you add `#[doc(inline)]`. + +### `hidden` + + + +Any item annotated with `#[doc(hidden)]` will not appear in the documentation, unless +the `strip-hidden` pass is removed. + +### `alias` + +This attribute adds an alias in the search index. + +Let's take an example: + +```rust,no_run +#[doc(alias = "TheAlias")] +pub struct SomeType; +``` + +So now, if you enter "TheAlias" in the search, it'll display `SomeType`. +Of course, if you enter `SomeType` it'll return `SomeType` as expected! + +#### FFI example + +This doc attribute is especially useful when writing bindings for a C library. +For example, let's say we have a C function that looks like this: + +```c +int lib_name_do_something(Obj *obj); +``` + +It takes a pointer to an `Obj` type and returns an integer. In Rust, it might +be written like this: + +```ignore (using non-existing ffi types) +pub struct Obj { + inner: *mut ffi::Obj, +} + +impl Obj { + pub fn do_something(&mut self) -> i32 { + unsafe { ffi::lib_name_do_something(self.inner) } + } +} +``` + +The function has been turned into a method to make it more convenient to use. +However, if you want to look for the Rust equivalent of `lib_name_do_something`, +you have no way to do so. + +To get around this limitation, we just add `#[doc(alias = "lib_name_do_something")]` +on the `do_something` method and then it's all good! +Users can now look for `lib_name_do_something` in our crate directly and find +`Obj::do_something`. diff --git a/src/doc/rustdoc/src/write-documentation/what-to-include.md b/src/doc/rustdoc/src/write-documentation/what-to-include.md new file mode 100644 index 00000000000..35e6ccbc388 --- /dev/null +++ b/src/doc/rustdoc/src/write-documentation/what-to-include.md @@ -0,0 +1,125 @@ +# What to include (and exclude) + +It is easy to say everything must be documented in a project and often times +that is correct, but how can we get there, and are there things that don't +belong? + +At the top of the `src/lib.rs` or `main.rs` file in your binary project, include +the following attribute: + +```rust +#![warn(missing_docs)] +``` + +Now run `cargo doc` and examine the output. Here's a sample: + +```text + Documenting docdemo v0.1.0 (/Users/username/docdemo) +warning: missing documentation for the crate + --> src/main.rs:1:1 + | +1 | / #![warn(missing_docs)] +2 | | +3 | | fn main() { +4 | | println!("Hello, world!"); +5 | | } + | |_^ + | +note: the lint level is defined here + --> src/main.rs:1:9 + | +1 | #![warn(missing_docs)] + | ^^^^^^^^^^^^ + +warning: 1 warning emitted + + Finished dev [unoptimized + debuginfo] target(s) in 2.96s +``` + +As a library author, adding the lint `#![deny(missing_docs)]` is a great way to +ensure the project does not drift away from being documented well, and +`#![warn(missing_docs)]` is a good way to move towards comprehensive +documentation. In addition to docs, `#![deny(missing_doc_code_examples)]` +ensures each function contains a usage example. In our example above, the +warning is resolved by adding crate level documentation. + +There are more lints in the upcoming chapter [Lints][rustdoc-lints]. + +## Examples + +Of course this is contrived to be simple, but part of the power of documentation +is showing code that is easy to follow, rather than being realistic. Docs often +take shortcuts with error handling because examples can become complicated to +follow with all the necessary set up required for a simple example. + +`Async` is a good example of this. In order to execute an `async` example, an +executor needs to be available. Examples will often shortcut this, and leave +users to figure out how to put the `async` code into their own runtime. + +It is preferred that `unwrap()` not be used inside an example, and some of the +error handling components be hidden if they make the example too difficult to +follow. + +``````text +/// Example +/// ```rust +/// let fourtytwo = "42".parse::()?; +/// println!("{} + 10 = {}", fourtytwo, fourtytwo+10); +/// ``` +`````` + +When rustdoc wraps that in a main function, it will fail to compile because the +`ParseIntError` trait is not implemented. In order to help both your audience +and your test suite, this example needs some additional code: + +``````text +/// Example +/// ```rust +/// # main() -> Result<(), std::num::ParseIntError> { +/// let fortytwo = "42".parse::()?; +/// println!("{} + 10 = {}", fortytwo, fortytwo+10); +/// # Ok(()) +/// # } +/// ``` +`````` + +The example is the same on the doc page, but has that extra information +available to anyone trying to use your crate. More about tests in the +upcoming [Documentation tests] chapter. + +## What to Exclude + +Certain parts of your public interface may be included by default in the output +of rustdoc. The attribute `#[doc(hidden)]` can hide implementation details +to encourage idiomatic use of the crate. + +For example, an internal `macro!` that makes the crate easier to implement can +become a footgun for users when it appears in the public documentation. An +internal `Error` type may exist, and `impl` details should be hidden, as +detailed in the [API Guidelines]. + +## Customizing the output + +It is possible to pass a custom css file to `rustdoc` and style the +documentation. + +```bash +rustdoc --extend-css custom.css src/lib.rs +``` + +A good example of using this feature to create a dark theme is documented [on +this blog]. Just remember, dark theme is already included in the rustdoc output +by clicking on the paintbrush. Adding additional options to the themes are +as easy as creating a custom theme `.css` file and using the following syntax: + +```bash +rustdoc --theme awesome.css src/lib.rs +``` + +Here is an example of a new theme, [Ayu]. + +[Ayu]: https://github.com/rust-lang/rust/blob/master/src/librustdoc/html/static/css/themes/ayu.css +[API Guidelines]: https://rust-lang.github.io/api-guidelines/documentation.html#rustdoc-does-not-show-unhelpful-implementation-details-c-hidden +[Documentation tests]: documentation-tests.md +[on this blog]: https://blog.guillaume-gomez.fr/articles/2016-09-16+Generating+doc+with+rustdoc+and+a+custom+theme +[rustdoc-lints]: ../lints.md -- cgit 1.4.1-3-g733a5