This document explains how to write documentation for the std/core public APIs.
Let's start with some general information:
It is common in English to have contractions such as "don't" or "can't". Do not use these in documentation. Always write their "full form":
- "do not" instead of "don't"
- "cannot" instead of "can't"
- "it would" instead of "it'd"
- "it will" instead of "it'll"
- "it is"/"it has" instead of "it's"
- "you are" instead of "you're"
- "they are" instead of "they're"
- etc
The only exception to this rule is "let's" as it is specific/known/common enough.
The reason is simply to make the reading simpler for as many people as possible.
Whenever you are talking about a type or anything code related, it should be in a inline code block. As a reminder, a inline code block is created with backticks (`). For example:
This a `Vec` and it has a method `push` which you can call by doing `Vec::push`.
Intra-doc links (you can see the full explanations for the feature here) should be used as much as possible whenever a type is mentioned.
Little note: when you are documenting an item, no need to link to it. So if you
write documentation for String::push_str
method, no need to link to the method
push_str
or to the String
type.
If you have cases like Vec<String>
, you need to use intra-doc links on both
Vec
and String
as well. It would look like this:
This is a [`Vec`]`<`[`String`]`>`.
Extra explanations: since both Vec
and String
are in codeblocks, <
and >
should as well, otherwise it would render badly.
With rustdoc, code blocks are tested (because they are treated as Rust code
blocks by default). It allows us to know if the documentation is up to date. As
such, please avoid using ignore
as much as possible on code blocks! If you
want as a language other than Rust, simply set it in the code block tags:
```text
This is not rust code!
```
Some special cases:
- If the code example cannot be run (when documenting a I/O item for example),
use
no_run
. - If it is expected to fail, use
should_panic
. - If it is expected to fail compilation (which be quite rare!), use
compile_fail
.
You can find more information about code blocks here.
A module is supposed to contain "similar" items. As such, its documentation is supposed to give an overview and eventually a base to understand what the items it contains are doing.
You can take a look at the f32 module or at the fmt module to see good examples.
The basic format of each documented methods/functions should roughly look like this:
[explanations]
[example(s)]
By explanations
we mean that the text should explain what the method and what
each of its arguments are for. Let's take this method for example:
pub fn concat_str(&self, s: &str) -> String {
if s.is_empty() {
panic!("empty concat string");
}
format!("{}{}", self.string, s)
}
The explanation should look like this:
Returns a new [`String`] which contains `&self` content with `s` added at the end.
If the function/method can panic in certain circumstances, it must to be
mentioned! This explanation needs to be prepended by a Panics
title:
# Panics
`concat_str` panics if `s` is empty.
As for the examples, they have to show the usage of the function/method. Just
like the panic
section, they need to be prepended by a Examples
title.
It is better if you use assert*!
macros at the end to ensure that the example
is working as expected. It also allows the readers to understand more easily
what the function is doing (or returning).
# Examples
```
let s = MyType::new("hello ");
assert_eq!("hello Georges", s.concat_str("Georges").as_str());
```
It is mostly the same as for methods and functions except that the examples are (strongly) recommended and not mandatory.
A good example often shows how to create the item.