Skip to content

Add guidelines about writing documentation #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
- [Documentation](./documentation/summary.md)
- [doc alias policy](./documentation/doc-alias-policy.md)
- [safety comments policy](./documentation/safety-comments.md)
- [how to write documentation](./how-to-write-documentation.md)
- [reviewing doc changes](./reviewing-doc-changes.md)

---

Expand Down
149 changes: 149 additions & 0 deletions src/documentation/how-to-write-documentation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
# How to write documentation

This document explains how to write documentation for the std/core public APIs.

Let's start with some general information:

### Contractions

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"
Comment on lines +9 to +18
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why? We currently have over 600 of such contractions in doc comments in library/*.

I think it's definitely good to have guidelines, but we should probably start with writing down the existing practices rather than making new rules that we currently don't follow.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the explanations I provided below provide explanations for it. Making documentation easier to read by reducing congestion like trying to figure out if 'd is "had" or "should/would" doesn't seem like a bad idea. Until now we didn't have a guideline so it was to be expected. I don't see why it'd be an issue when writing new documentation though. Nothing prevents us to slowly update the existing documentation.

But maybe you had some other reasons?

Copy link
Member

@Manishearth Manishearth Jun 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll point out: while there is no such thing as "standardized" english, only some of these contractions are found in formal usage (don't, can't, it'll, it's, you're, they're are found, whereas 'd for should/would/had is not as much), and I cannot think of a single English contraction that is ambiguous in formal usage (e.g. your example about 'd doesn't apply at all). Folks are more loose in chats/etc, but most modern English style guides allow contractions, and if anything it reads weirdly if you omit them. Discouraging contractions seems rather weird.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I followed what the rustc errors do (which disallow contractions). Maybe I'm once again imagining things...

* 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.

### When to use inline code blocks

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:


```text
This a `Vec` and it has a method `push` which you can call by doing `Vec::push`.
```

### When to use intra-doc links

Intra-doc links (you can see the full explanations for the feature
[here](https://doc.rust-lang.org/rustdoc/write-documentation/linking-to-items-by-name.html))
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.
Comment on lines +42 to +44
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph seems to be missing a few words.

Suggested change
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.
Little note: when you are documenting an item, there is no need to link to it.
So, if you write documentation for the `String::push_str` method, there is
no need to link to the `push_str` method or 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:

```text
This is a [`Vec`]`<`[`String`]`>`.
```
Comment on lines +46 to +51
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something we currently rarely do, and I'm not sure we should do that everywhere, as it's quite tedious with not a lot of benefit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes the reading better. As such, I think it's a good enough reason.

(It's also something we enforced when the documentation team still existed too)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It makes the reading better.

It don't think it does. It just adds more noise with the changes in color/formatting.

If both A and B are very relevant, then it might make sense to link them separately in A<B>. But quite often B isn't very relevant, and it's fine and less noisy to just link all of A<B> to A.

Regardless, this is guideline is not uncontroversial. It's fine to document and merge guidelines in to std-dev-guide that we already follow, by documenting existing practice. But new rules that we don't currently follow should first have some discussion and a decision.

Right now, we have exactly one doc comment that uses the syntax [..]`<`[..]`>`.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're absolutely right. I remembered that we had a lot more around. I guess my memory about it is completely outdated...

I still appreciate to be able to click on each type separately but maybe it's only me...


Extra explanations: since both `Vec` and `String` are in codeblocks, `<` and `>`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"explanation" is usually used a an uncountable noun, with no separate plural form:

Suggested change
Extra explanations: since both `Vec` and `String` are in codeblocks, `<` and `>`
Extra explanation: since both `Vec` and `String` are in codeblocks, `<` and `>`

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TIL, thanks!

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wikipedia seems to say it's countable: https://simple.wiktionary.org/wiki/explanation whereas oxford dictionary says it's both: https://www.oxfordlearnersdictionaries.com/definition/english/explanation 😆

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be countable, however that usually applies to when, e.g. you're doing multiple explanations to different people or at different times. If it's being explained in one place, that's a single explanation even if it has multiple parts.

(this is similar to how "fish" is uncountable except when talking about different kinds of fish)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tricky language. Thanks for the explanation!

should as well, otherwise it would render badly.

### Code blocks

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](https://doc.rust-lang.org/rustdoc/write-documentation/documentation-tests.html).

## How to write documentation for a module

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](https://doc.rust-lang.org/nightly/std/f32/index.html) or at the
[fmt module](https://doc.rust-lang.org/nightly/std/fmt/index.html) to see
good examples.

## How to write documentation for functions/methods

The basic format of each documented methods/functions should roughly look like this:

```text
[explanations]

[example(s)]
```

### Explanations

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:

```rust
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:

```text
Returns a new [`String`] which contains `&self` content with `s` added at the end.
```

### Panic?

If the function/method can panic in certain circumstances, it must to be
mentioned! This explanation needs to be prepended by a `Panics` title:

```text
# Panics

`concat_str` panics if `s` is empty.
```

### Examples

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.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many cases we just have # Example (singular) instead of # Examples when there's only one example.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember the debate behind this (I think @Manishearth was involved in this debate? Please correct me if I'm wrong!) but it's what we already recommend in the rustdoc book. I'm fine with updating both though if needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't remember being involved in this debate at all. I think both are fine.

I recall making sure the clippy lint for this can detect both (or at least talking about that).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then it was maybe at the time when the documentation team still existed I guess... Like said above, I'm fine with both.


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());
```

## How to write documentation for other items

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.
24 changes: 24 additions & 0 deletions src/documentation/reviewing-doc-changes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Reviewing doc changes

Most of the time, it is mostly reviewing that the documentation isn't wrong
in any way and that it follows the
[how to write documentation](./how-to-write-documentation.md) guideline.

There is however something where we need to be extra careful: stability
guarantees.

## Stability guarantees

First, short explanation about what a stability guarantee is: a statement in
the document which explains what the item is doing in a precise case. For
example:

* Showing precisely how a function on floats handles `NaN`.
* Saying that a sort method has a particular running-time bound.

So if a doc change updates/adds/removes a stability guarantee, it has to be
**very** carefully handled and needs to go through the
[libs API team FCP](https://rustc-dev-guide.rust-lang.org/stabilization_guide.html?highlight=fcp#fcp).

It can be circumvented by adding a `# Current Implementation` section
[like done here](https://github.com/rust-lang/rust/blob/4a8d2e3856c0c75c71998b6c85937203839b946d/library/alloc/src/slice.rs#L250).
2 changes: 2 additions & 0 deletions src/documentation/summary.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
- [doc alias policy](./doc-alias-policy.md)
- [safety comments policy](./safety-comments.md)
- [how to write documentation](./how-to-write-documentation.md)
- [reviewing doc changes](./reviewing-doc-changes.md)