Rust: Documentation

Home · Blog

29 March 2023

Rust and Cargo have excellent support for interface documentation.

For simple comments in the code, you can use the // and /* … */ syntax you may know from C, Java, and other languages:

// this is a comment
/* another comment with a /* nested comment */ inside */

Unlike in C and Go, you can have a /* … */ comment inside another one.

For interface documentation, put a comment starting with /// just before the item you want to document, or a comment starting with //! inside the item. Usually //! is used to document modules, putting the comment at the top of the file, and /// for everything else:

//! Comment describing the crate.

/// Documentation for foo.
pub fn foo() -> bool { true }

// Documentation for Bar.
pub struct Bar {
    /// Documentation for a.
    pub a: i32,

    /// Documentation for b.
    pub b: f64,
}

The cargo doc command uses these to build nicely formatted HTML documentation. If you run

cargo doc --open

it’ll build the documentation and open it in your default browser. This doesn’t start a server -- it just builds the documentation in the target directory, so you’ll have to run cargo doc again after you make changes.

Documentation is written in Markdown so you can use headings, lists, etc. Markdown code blocks are meant to have executable code samples:

/// Returns `x` added to itself.
///
/// ```
/// let y = mycrate::double(2);
/// assert_eq!(y, 4);
/// ```
pub fn double(x: i32) -> i32 {
    x + x
}

The code will be shown, with syntax highlighting, in the generated documentation, but it’s also a type of test (see Rust: Testing) which you can run with

cargo test --doc

One final detail: when you re-export definitions with pub use, by default the re-exported items will be documented in-line with the rest of the module. You can turn that off with an annotation:

#[doc(no_inline)]
pub use nested::{x, y};

With no_inline, the documentation for this module won’t include the documentation for x and y but it will have a section titled “Re-exports” that lists the items that are re-exported. If you don’t want any mention of the re-exported items, use hidden:

#[doc(hidden)]
pub use nested::{x, y};