rust-comentarios-documentacion

Comments and Documentation in Rust Using cargo doc

  • 5 min

Comments and documentation are text written alongside code to explain intent, usage, and context.

In many languages, documentation is an external tool (Doxygen, Javadoc, Sphinx…). In Rust, documentation is part of the core language.

The compiler and Cargo come ready out of the box to convert your comments into a browsable web page with search functionality and runnable examples.

Today, we’ll look at the two types of comments in Rust and how to generate that professional documentation with a single command.

Simple comments (//)

These are the standard comments everyone uses. The compiler completely ignores them. They serve to explain complex parts of the internal logic to someone reading the source code.

fn main() {
    // This is a single-line comment
    let x = 5;

    /*
     This is a block comment.
     It's less common in Rust; people usually prefer
     multiple lines of //
    */
    let y = 10;
}
Copied!

Best practice: Don’t comment the “what” (the code already says what it does), comment the “why”.

  • let x = x + 1; // Adds 1 to x (Obvious, noise).
  • let x = x + 1; // Needed to compensate for the sensor offset (Useful).

Documentation comments (///)

If you use three slashes /// instead of two, you are creating a documentation comment. These comments are processed by Rust’s tools.

They support Markdown formatting (bold, lists, links, code blocks) and are used to generate the HTML documentation of your API.

They are placed just before the element they document (a function, a struct, an enum…).

/// Adds one to the given number.
///
/// # Examples
///
/// ```
/// let arg = 5;
/// let answer = hola_mundo::add_one(arg);
///
/// assert_eq!(6, answer);
/// ```
pub fn add_one(x: i32) -> i32 {
    x + 1
}
Copied!

Common sections

Although you can write whatever you want, the Rust community follows standard conventions using Markdown headers (#):

  1. # Examples: Shows how to use the function.
  2. # Panics: Explains when this function might cause the program to abort (e.g., if you pass an out-of-bounds index).
  3. # Errors: If the function returns a Result, explains what conditions cause an error.
  4. # Safety: If the function is unsafe, explains what precautions the developer should take.

Module-level comments (//!)

Sometimes you want to document the entire file or module, not a specific element. For that, we use //! (with an exclamation mark).

These comments document the element that contains them (usually the crate file or mod), rather than the element that follows them. They are usually placed at the beginning of the main.rs or lib.rs file.

//! # My Math Library
//!
//! `mi_libreria` is a collection of utilities for performing
//! complex calculations in a highly inefficient manner.

/// Adds two numbers...
fn suma(...)
Copied!

Generating the documentation: cargo doc

Now that we’ve decorated our code with /// and Markdown, how do we view it? Open your terminal and run:

cargo doc --open
Copied!

This command:

Analyzes your code and extracts the /// and //! comments.

Generates a static website (HTML, CSS, JS) in the target/doc folder.

The --open flag automatically opens your default browser displaying the website.

You’ll see a webpage with a search bar, sidebar navigation, and all the visual styling of the official Rust documentation. And you haven’t had to configure anything!

cargo doc doesn’t only document YOUR code. It also generates the documentation for all the dependencies (libraries) your project uses. This is incredibly useful for checking how an external library works without having to search on Google; you get the documentation for the exact version you are using, offline and locally.

Documentation tests (doc tests)

Has it ever happened to you that you copy an example from a library’s documentation, paste it into your code, and it doesn’t work because the documentation was outdated?

In Rust, Rust code blocks inside /// comments can be run as tests.

When you run cargo test, Rust doesn’t just run your unit tests; it also extracts the code blocks from your documentation and runs them. If your example doesn’t compile or fails, cargo test will fail.

/// Divides two numbers.
///
/// # Examples
///
/// ```
/// let resultado = hola_mundo::dividir(10, 2);
/// assert_eq!(resultado, 5);
/// ```
///
/// ```should_panic
/// // This example documents that dividing by zero causes a panic
/// hola_mundo::dividir(10, 0);
/// ```
pub fn dividir(a: i32, b: i32) -> i32 {
    if b == 0 { panic!("Cannot divide by zero"); }
    a / b
}
Copied!

This helps ensure that the examples remain up-to-date. If you change the function but forget to adapt the example, the documentation tests will alert you.