---
title: Documentation
source: 'https://academia.sh/en/courses/rust-advanced/documentation'
course: 'The Rust Ecosystem and Advanced Topics'
language: en
updated: '2026-09-15T04:58:43+00:00'
license: 'CC BY-SA 4.0'
objectives:
    - "Shows that a documentation sentence contradicts a function's real behavior and proves this claim is checked by no tool"
    - 'Tests the runnable examples inside the documentation by invoking the documentation tool from within a program, and prints the number of passing tests'
    - 'Explains, naming both guarantee classes, that the same function can carry both an unchecked explanation and a checked example'
---

# Documentation

Measuring how two guarantee classes can stand side by side in the same source, by showing that a documentation sentence contradicts a function's real behavior without being checked by any tool, while that same function's runnable example inside the documentation is genuinely tested by invoking the documentation tool from within a program.

The previous three lessons measured three separate places that sit in the source but that
the compiler never looks at: a closed flag's body, a property tested by running, two
implementations' operation count. In all three, what was measured was a part of the source
that was *code* — a function, a block, a loop. This is the fourth and final lesson of this
topic, Project Lifecycle, and it asks the same question of the part of the source most often
overlooked: the explanation written next to a function. A documentation sentence is also
part of the source, but it is not syntax the compiler checks, it is prose a human reads;
this lesson asks who (or whether no one) checks this prose's correctness — and shows that
two different answers can stand side by side in the same source.

This question's answer cannot be given in a single sentence, because a documentation
comment has two different sections: the prose read above, and a small code example, usually
placed below it, showing how to call the function. These two sections sit together inside
the same comment, but their fates are not the same — that is exactly what this lesson
measures. This topic's other three lessons each built their own measurement; this lesson
returns to the course's twelve-observation guarantee core and uses its
documentation-accuracy observation directly.

## The Documentation Itself, and the Contradiction in the Source

In Rust, writing lines starting with three slashes (`///`) above a function forms that
function's documentation comment. This comment differs from an ordinary explanation:
subheadings like `# Examples` and code fragments wrapped in backticks can be placed inside
it. All three functions below carry this same layout — an explanatory sentence, and an
example below it. The first function is the guarantee core's (`guarantee.rs`)
documentation-accuracy section: the documentation line says the function returns the
**largest** value, while the function actually returns the **smallest**. The other two
functions — one returning the smaller value, one summing a slice — have correctly written
documentation, and were added here for comparison.

```rust
// doc_body.rs — guarantee.rs's documentation-accuracy section + two more tested examples
/// This documentation line says the function returns the **largest** value.
/// The function returns the smallest. No tool checks this contradiction.
///
/// # Examples
///
/// ```
/// assert_eq!(doc_body::wrong_doc(3, 9), 3);
/// ```
pub fn wrong_doc(a: i32, b: i32) -> i32 {
    if a < b {
        a
    } else {
        b
    }
}

/// Returns the smaller of two values.
///
/// # Examples
///
/// ```
/// assert_eq!(doc_body::smaller_of(3, 9), 3);
/// ```
pub fn smaller_of(a: i32, b: i32) -> i32 {
    if a < b {
        a
    } else {
        b
    }
}

/// Returns the sum of a slice.
///
/// # Examples
///
/// ```
/// assert_eq!(doc_body::sum_slice(&[1, 2, 3]), 6);
/// ```
pub fn sum_slice(slice: &[i32]) -> i32 {
    slice.iter().sum()
}
```

**PL13.** This file carries no `fn main` at all; it stands as a source section. All three
functions compile correctly — even though `wrong_doc`'s prose is wrong, its body is
type-consistent, and the compiler never reads the prose at all. The body below calls these
three functions.

```rust
// doc_body_main.rs — the documentation contradiction stays in the source, the program still compiles
mod doc_body;
use doc_body::{wrong_doc, smaller_of, sum_slice};

fn main() {
    println!("doc says 'largest', real result: {}", wrong_doc(3, 9));
    println!("smaller_of(3, 9) = {}", smaller_of(3, 9));
    println!("sum_slice(&[1, 2, 3]) = {}", sum_slice(&[1, 2, 3]));
}
```

```
doc says 'largest', real result: 3
smaller_of(3, 9) = 3
sum_slice(&[1, 2, 3]) = 6
```

Compilation printed no warning at all. The `wrong_doc(3, 9)` call returned `3` — the smaller
value, not the larger one the documentation sentence claims. This is expected behavior in an
ordinary compilation process: `rustc` does not parse a documentation comment starting with
three slashes (`///`) as Markdown, does not read the sentences inside it, does not compile
the code example embedded within it. The entire documentation comment — both the wrong prose
and the correctly working example — is **invisible text** in an ordinary compilation; the
compiler neither confirms nor rejects it, because it never looks at it at all.

This is exactly the class the guarantee core measures: **nobody checks it**. The compiler
checked the function's *body* (checked its type, resolved its names) but never saw the
function's *documentation* at all. Even though a documentation sentence is part of the
source, it sits entirely outside the compiler's sphere of interest — just like the closed
flag's body in the Dependencies and Feature Flags lesson, but for a different reason: there,
the body never entered compilation at all; here, it is not that it fails to enter, but that
the compiler sees it as **belonging to another category entirely** — not code, prose.

It matters to keep these two situations apart. A closed flag's body is a piece of code that
could enter compilation once the flag is turned on — it is potentially checkable, merely
unchecked today. A documentation sentence's prose part, on the other hand, never enters
compilation under any condition; it was never code, and never will be. The compiler
separates a `///` documentation comment from the rest of the source and stores it as
information attached to the function — so it is not entirely ignored, it sits somewhere a
documentation tool can read it. But an ordinary compilation's type-checking and
name-resolution stages never look at this information's content at all: they do not verify
the sentence inside it, they do not compile the code example inside it. What is checked and
what is merely stored are different things.

This comes from the same root as the rot measured in the Dependencies and Feature Flags
lesson. There, a closed flag's body could lose sync as the rest of the source changed,
because nobody checked it. Here, the same thing happens between a function's body and its
documentation: the body can change over time — a bug gets fixed, a behavior gets reversed —
but the documentation sentence above it does not update itself. `wrong_doc` was probably
written correctly at some point (perhaps the function really did return the largest value),
and the documentation sentence was forgotten when the body changed; there is no way to prove
this, but the fact that both sides can live independently explains why such drift is
possible at all. What the two share is that no checking mechanism keeps the two sides tied
to each other.

## The Example Inside the Documentation: Testing from Within a Program

Each function's documentation above has a `# Examples` section, containing a code example
wrapped in three backticks. Even though these examples are invisible in ordinary
compilation, the language's own documentation tool handles them specially: it scans the
source and compiles and runs each example as a separate test. This is the second form of
measurement built from within a program in this curriculum — in the Procedural Macros
lesson, the compiler itself was invoked from within a program; here, what is invoked is not
the compiler, but one of the compiler's side tools. The program below invokes this tool from
within itself, using `std::process::Command`, and prints only how many examples passed — no
path, duration, or machine name is printed.

```rust
// doc_test.rs — invokes the documentation tool from within the program and prints the passing test count
use std::process::Command;

fn main() {
    let build = Command::new("rustc")
        .args([
            "--edition", "2021", "--crate-type", "lib",
            "-o", "libdoc_body.rlib", "doc_body.rs",
        ])
        .output()
        .expect("could not start the compiler");
    if !build.status.success() {
        println!("passing tests: 0");
        return;
    }

    let test_run = Command::new("rustdoc")
        .args(["--edition", "2021", "--test", "-L", ".", "doc_body.rs"])
        .output()
        .expect("could not start the documentation tool");

    let output = String::from_utf8_lossy(&test_run.stdout);
    let count = output
        .lines()
        .find(|s| s.starts_with("test result:"))
        .and_then(|line| line.split("passed").next())
        .and_then(|part| part.trim().rsplit(' ').next())
        .and_then(|s| s.parse::<u32>().ok())
        .unwrap_or(0);

    println!("passing tests: {}", count);
}
```

```
passing tests: 3
```

**PL14.** All three examples passed — `wrong_doc`'s, `smaller_of`'s, and `sum_slice`'s. This
program runs in two steps. In the first step, it compiles the source as a library; this step
is necessary because every example calls the real functions in the source by their full
names, like `doc_body::wrong_doc`, and the documentation tool needs to find the pre-compiled
library to resolve these names. In the second step, the documentation tool is invoked in
test mode; the `-L .` option tells the tool to look for the pre-compiled library in the
working directory. The tool's own output contains, line by line, a path, a duration, and a
detailed breakdown; this program extracts only the single number from the "passed" line out
of that output and never prints the rest — no field dependent on the environment leaks into
this program's own output.

This run reverses the previous section's observation. In ordinary compilation, the
documentation was completely invisible; here, the documentation tool reads the same source
**with a different eye** — it treats the code fragment inside each `# Examples` block as a
separate source file and genuinely compiles and runs it. `wrong_doc`'s example tests real
behavior (the result `3`) with the equality-checking call inside it, and **passes** —
because the example code itself is written correctly, only the prose sentence above it is
wrong. The class measured in this lesson changes here: **still holds**. The documentation
tool is part of the language's own distribution, and, just like `rustc` checks a body, it
checks the example by compiling and running it.

This provides a defense against the rot described in the previous section — but only for the
example, not for the prose. Had `smaller_of`'s signature changed (say, if it took three
arguments instead of two), the call inside its example would no longer compile, and the
documentation tool would mark it "failed"; the example is **forced** to stay in sync with
the body. Nothing, however, keeps `wrong_doc`'s prose in sync with the body — whether the
body changes or not, the sentence stays exactly as it is. The guarantee the documentation
tool gives is therefore real but narrow: only the example is forced to stay in sync with the
body, not the explanation surrounding it.

**Distinguishing this from a related idea:** the Production Go: Testing, Tooling and
Performance course's measurement axis was **who** states a piece of knowledge — the source,
a tool, or a run. A documentation sentence is exactly a piece of knowledge **the source
states**; this lesson asks whether that knowledge is verified. The answer splits in two: the
prose part is read by no tool at all (nobody checks it), while the example part is run by
the language's own documentation tool (still holds) — the same source sentence's two
different parts meet two different fates. Compared to that course's three-way distinction, a
documentation sentence's prose falls exactly into the "stated by the source" category — no
tool or run verifies it; the documentation sentence's example, however, steps outside that
three-way split, because it stops being something the source merely states and becomes
something **a run verifies**.

## A Bounding Measurement

Reading the two runs above together produces a striking result: `wrong_doc`'s example is
one of the three passing tests, and its **passing** does not change the fact that the prose
sentence above it is still wrong. The example tests `3`, and `3` is the correct result; the
prose says "largest," and that is wrong. Because the documentation tool runs the example and
gets the correct result, it marks the test as **passed** — without ever looking at what the
prose says.

**PL15.** This is this measurement's most important limit: what the documentation tool
checks is **the example, not the explanation.** An example tests the claims inside it (the
expected values written with the equality-checking call); the prose sentence above the
example neither influences nor checks what it says, in any way. A person could read
`wrong_doc`'s documentation, understand "returns the largest," see the example below the
same documentation, and even know that it passes — and still walk away from the source with
a wrong impression, because a passing example says nothing at all about the prose's
correctness.

This limit's scope is also clear-cut: the documentation tool sees only code blocks marked
with ` ``` `; every sentence outside these blocks, including the `# Examples` heading, is
ordinary text to it. An example being written correctly does not mean that example is
**consistent** with the explanation — it only means the example is correct on its own terms
(that it matches the real behavior in the source code). In this lesson, the `smaller_of`
function has exactly the same body as `wrong_doc`, but its prose is correct; both of their
examples pass the same kind of test, because the example only tests what gets called and
what gets returned at the code level, it does not compare the two functions' prose.

This limit has one more consequence: an example passing does not mean the case that example
**represents** is complete, either. `wrong_doc`'s example tests only a single call (`3` with
`9`); what the function returns when called with a different input never appears in this
example at all. While the documentation tool marks this example as passed, it says nothing
about what the function does for *every* input — exactly the same limit seen in the Testing
and Property-Based Testing lesson applies here too: exactly as much guarantee as the tested
input, no more, no less. The guarantee the documentation tool gives is therefore doubly
bounded: it tests only the example (not the prose), and it tests only the input the example
tests (not the function's entire behavior).

## Summary

- In an ordinary compilation (`rustc`), both a documentation comment's prose and the code
  example inside it are invisible; the compiler looks at neither.
- `wrong_doc`'s documentation sentence says "largest," the body returns the "smallest"; this
  contradiction passes without warning in ordinary compilation — the class is **nobody
  checks it**.
- The documentation tool was invoked from within the program, and only the passing test
  count (`3`) was printed; duration, path, and machine name were never printed.
- The documentation tool genuinely compiles and runs the code inside `# Examples`; for this
  section, the class is **still holds** — the language's own tool carries `rustc`'s checking
  one step further.
- The bounding measurement: `wrong_doc`'s example passed, but the wrong prose sentence
  above it is still wrong — the documentation tool tests the example, not the explanation.
- The same function can carry two guarantee classes at once: its documentation's prose is
  nobody-checks-it, its documentation's example is still-holds.

## Next Step

This topic's four lessons, Project Lifecycle, showed how the compiler's guarantee stops in
four separate places: in a closed flag's body (nobody checks it), in a test established by
running (handed to the writer), in a counted unit of operation (nobody checks it), and now
in a documentation sentence — where, for the first time, two classes (nobody-checks-it and
still-holds) appear together within a single lesson. All four are different views of the
same underlying fact: wherever the compiler stops, the remaining gap is either filled by
nobody, filled by the writer through running, or entered by one of the language's own tools
with a different kind of checking.

The course's final lesson — the course wrap-up — brings these four places together and turns
to look at a fifth, this one outside a source: a version string. That string, too, sits in
the source and corresponds to nothing; which version of a library preserves which signature
is the Publishing lesson's subject. This lesson leaves its mark there, too: a version
string, just like a documentation sentence, is a claim that sits in the source, that a human
reads, but that the compiler never checks.
