Hello World and Program Structure

Documentation Comments

Documentation comments (or doc comments) are special comments written in Markdown that describe public and private API items—such as functions, structs, enums, traits, modules, and crates. Unlike regular // comments, which the compiler discards, doc comments are parsed by the compiler into #[doc = "..."] attributes and used by rustdoc (cargo doc) to generate searchable HTML documentation and executable documentation tests (doctests).

Outer vs Inner Documentation Comments

Rust provides two kinds of doc comments, distinguished by whether they document the item following the comment or the item enclosing the comment:

Syntax Style Name What It Documents Typical Placement
/// ... Line Outer doc comment The item immediately following the comment Directly above a fn, struct, enum, field, trait, or mod
/** ... */ Block Outer block doc comment The item immediately following the comment Directly above an item (less common than ///)
//! ... Line Inner doc comment The crate, module, or block containing the comment At the very top of src/lib.rs, src/main.rs, or inside mod name { //! ... }
/*! ... */ Block Inner block doc comment The crate, module, or block containing the comment At the top of a crate or module
+-------------------------------------------------------------------+
| // src/lib.rs                                                     |
| //! Inner doc comment (`//!`):                                    |
| //! Documents the enclosing crate or module as a whole.           |
|                                                                   |
| /// Outer doc comment (`///`):                                    |
| /// Documents the `Rectangle` struct immediately below it.        |
| pub struct Rectangle {                                            |
|     /// Outer doc comment on the `width` field.                   |
|     pub width: u32,                                               |
|     /// Outer doc comment on the `height` field.                  |
|     pub height: u32,                                              |
| }                                                                 |
+-------------------------------------------------------------------+
//! Utilities for basic temperature conversions.

/// Converts a temperature from Celsius to Fahrenheit.
///
/// Formula: `F = C * 9 / 5 + 32`
pub fn celsius_to_fahrenheit(celsius: f64) -> f64 {
    celsius * 9.0 / 5.0 + 32.0
}

fn main() {
    println!("0°C = {}°F", celsius_to_fahrenheit(0.0));
    println!("100°C = {}°F", celsius_to_fahrenheit(100.0));
}
0°C = 32°F
100°C = 212°F

How the Compiler Desugars Doc Comments

To rustc, a doc comment is syntactic sugar for the #[doc = "..."] attribute. The following two definitions are identical to the compiler:

/// Returns the square of `x`.
///
/// Works for any `i32` that does not overflow.
pub fn square_comment(x: i32) -> i32 {
    x * x
}

#[doc = " Returns the square of `x`."]
#[doc = ""]
#[doc = " Works for any `i32` that does not overflow."]
pub fn square_attribute(x: i32) -> i32 {
    x * x
}

fn main() {
    println!("{} and {}", square_comment(5), square_attribute(5));
}
25 and 25

Standard Markdown Structure and Sections

Doc comments support CommonMark Markdown—including bold/italic text, code spans, tables, lists, blockquotes, and intra-doc links ([Option]). By convention across the Rust standard library and ecosystem, item documentation follows a consistent layout:

  1. First line (Summary line): A single short sentence summarizing what the item does, written in third-person declarative style ("Returns...", "Creates...", "Parses..."). rustdoc displays this first paragraph in module summary listings.
  2. Detailed explanation: Additional paragraphs explaining behavior, algorithmic complexity, or corner cases.
  3. Standard # headings:
Heading When to Include It
# Examples Shows one or more runnable code blocks demonstrating how to call or construct the item
# Panics Documents the exact conditions under which the function will call panic! (such as out-of-bounds indices or division by zero)
# Errors If the function returns Result<T, E>, explains the conditions that cause an Err(E) to be returned
# Safety If the function is pub unsafe fn, specifies the invariants the caller must uphold to avoid undefined behavior
/// Divides `dividend` by `divisor`, returning the integer quotient.
///
/// # Panics
///
/// Panics if `divisor` is `0`.
///
/// # Examples
///
/// ```
/// let q = divide_exact(20, 4);
/// assert_eq!(q, 5);
/// ```
pub fn divide_exact(dividend: i32, divisor: i32) -> i32 {
    assert!(divisor != 0, "divisor must not be zero");
    dividend / divisor
}

fn main() {
    println!("20 / 4 = {}", divide_exact(20, 4));
}
20 / 4 = 5

Executable Documentation Tests (Doctests)

When you run cargo test in a library crate (src/lib.rs), rustdoc extracts every Rust code block inside your doc comments, wraps it in a fn main() if none is present, compiles it against your crate, and executes it as an automated test. This guarantees that documentation examples never fall out of sync with the actual code.

Hiding Setup Lines in Doctests with #

Sometimes an example needs boilerplate setup lines (such as imports or helper definitions) to compile, but showing those lines would clutter the rendered documentation. Any line inside a doc-comment code block that starts with # (a hash followed by a space) is hidden in the generated HTML documentation while still compiled and run during cargo test:

/// Parses a positive port number from a string.
///
/// # Examples
///
/// ```
/// # fn main() -> Result<(), std::num::ParseIntError> {
/// let port: u16 = "8080".parse()?;
/// assert_eq!(port, 8080);
/// # Ok(())
/// # }
/// ```
pub fn is_privileged_port(port: u16) -> bool {
    port < 1024
}

fn main() {
    println!("80 is privileged: {}", is_privileged_port(80));
}
80 is privileged: true

In the rendered webpage produced by cargo doc, readers see only the two middle lines (let port: u16 = "8080".parse()?; and assert_eq!(port, 8080);), while cargo test compiles the full Result-returning main wrapper so the ? operator works.

Code Block Annotations for Doctests

Code Fence Tag cargo test Behavior
``` or ```rust Compiles and runs the code block; test passes if it exits without panicking
```should_panic Compiles and runs the code block; test passes only if execution panics
```compile_fail Compiles the code block; test passes only if compilation fails
```no_run Compiles the code block to verify syntax and types, but does not execute it (useful for network or file I/O examples)
```ignore Completely skips compiling and running the block
```text / ```bash Treated as non-Rust text; not compiled as a doctest

Generating HTML Documentation

To build HTML documentation for your project and open it in your default browser:

cargo doc --open

To build documentation for your crate only (skipping dependencies) and include private items:

cargo doc --no-deps --document-private-items

Common Errors

Placing an Outer Doc Comment (///) with No Following Item

Because /// attaches a #[doc = "..."] attribute to whatever item follows it, leaving a /// comment at the very end of a block or file with no item after it fails to compile:

// ❌ does not compile
fn main() {
    let x = 5;
    println!("{x}");
    /// Trailing outer doc comment with no item below it
}
error: expected item after doc comment
 --> src/main.rs:4:5
  |
4 |     /// Trailing outer doc comment with no item below it
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this doc comment doesn't document anything

error: aborting due to 1 previous error

Placing an Inner Doc Comment (//!) After an Item

Inner doc comments (//!) that document a module or file must appear at the top of the module or file, before any items (fn, struct, use). Placing //! after an item inside a module is a syntax error unless you meant ///:

// ❌ does not compile
fn helper() {}

//! Misplaced inner doc comment after an item
fn main() {
    helper();
}
error[E0753]: expected outer doc comment
 --> src/main.rs:4:1
  |
4 | //! Misplaced inner doc comment after an item
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: inner doc comments like this (starting with `//!` or `/*!`) can only appear before items
help: you might have meant to write a regular comment
  |
4 - //! Misplaced inner doc comment after an item
4 + // Misplaced inner doc comment after an item
  |
help: or an outer doc comment, if this was meant to document the following item
  |
4 - //! Misplaced inner doc comment after an item
4 + /// Misplaced inner doc comment after an item
  |

error: aborting due to 1 previous error