Documentation with rustdoc

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production.

The reference material consulted while preparing these pages is listed in the section bibliography.

This page is written against Rust 1.99.0 and the 2024 edition, checked on 2026-10-06. rustdoc generates HTML documentation from doc comments in your source, the same tool that produces the standard library documentation and every page on docs.rs. Its examples double as tests, so documented code stays correct. Good API documentation is also one of the Rust API Guidelines' checklist items.

Doc comments

  • /// documents the item that follows (an outer doc comment);

  • //! documents the item that contains it — the crate in lib.rs, or a module at the top of its file (an inner doc comment).

Both are Markdown, and both are sugar for the #[doc = "..."] attribute. The first paragraph is the item’s summary, shown in module listings and search results, so keep it to one sentence.

//! # shelf-core
//!
//! Domain types for the *shelf* library catalogue: books, ISBNs, loans, and the
//! [`Catalog`] trait with an in-memory implementation.
//!
//! ```
//! use shelf_core::{Catalog, InMemoryCatalog};
//! let catalog = InMemoryCatalog::new();
//! assert!(catalog.is_empty());
//! ```

/// A validated ISBN-13, stored without hyphens.
///
/// Construct one with [`Isbn::parse`]; the type guarantees that every value has
/// 13 digits and a correct check digit.
///
/// # Examples
///
/// ```
/// use shelf_core::Isbn;
///
/// let isbn = Isbn::parse("978-0-441-01359-3")?;
/// assert_eq!(isbn.as_str(), "9780441013593");
/// # Ok::<(), shelf_core::IsbnError>(())
/// ```
pub struct Isbn(String);

Conventional sections

The API Guidelines and the standard library use a small set of # headings consistently:

Section What it documents

# Examples

at least one runnable example — the most valuable part of the docs

# Errors

for functions returning Result: which errors, and when

# Panics

the conditions under which the function panics

# Safety

for unsafe fn and unsafe traits: the invariants the caller must uphold (required by the missing_safety_doc lint)

/// Lends the book with `isbn` to `member`.
///
/// # Errors
///
/// Returns [`CatalogError::NotFound`] if the ISBN is unknown and
/// [`CatalogError::AlreadyLent`] if another member has the book.
///
/// # Panics
///
/// Panics if `member` is empty.
pub fn lend(isbn: &str, member: &str) -> Result<(), CatalogError> {
    assert!(!member.is_empty(), "member must not be empty");
    if isbn.is_empty() {
        return Err(CatalogError::NotFound);
    }
    Ok(())
}

/// Errors returned by [`lend`].
#[derive(Debug, PartialEq)]
pub enum CatalogError {
    /// No book with that ISBN.
    NotFound,
    /// The book is already on loan.
    AlreadyLent,
}

/// Reads `len` bytes starting at `ptr`.
///
/// # Safety
///
/// `ptr` must be valid for reads of `len` bytes and properly aligned, and the memory
/// must not be mutated for the lifetime of the returned slice.
pub unsafe fn bytes_at<'a>(ptr: *const u8, len: usize) -> &'a [u8] {
    // SAFETY: the caller guarantees the conditions documented above.
    unsafe { std::slice::from_raw_parts(ptr, len) }
}

fn main() {
    assert_eq!(lend("", "alice"), Err(CatalogError::NotFound));
    let data = [1u8, 2, 3];
    // SAFETY: `data` is a live array of 3 bytes.
    println!("{:?}", unsafe { bytes_at(data.as_ptr(), 3) });
}

Link to other items by their Rust path in square brackets: [Isbn], [`Isbn::parse`] (backticks inside the brackets render the link as code), [crate::catalog], [Vec::push], [std::io::Error]. rustdoc resolves them like use paths from the current scope and turns them into URLs, so links survive moves and re-exports. Disambiguate items that share a name with a prefix ([struct@Loan], [fn@loan], [macro@shelf]), and add custom text with [the catalogue trait](Catalog). Broken links are reported by the rustdoc::broken_intra_doc_links lint, which warns by default.

The doc attribute

Attribute Effect

#[doc(hidden)]

omit an item from the docs (it stays public: for macro internals, deprecated shims)

#[doc(alias = "isbn13")]

extra search terms

#[doc(inline)] / #[doc(no_inline)]

show a re-exported item’s full docs at the re-export site, or just a link

#[doc = include_str!("../README.md")]

use a file as documentation (common for the crate root)

#![doc(html_logo_url = "...", html_root_url = "...")]

crate-level presentation settings

#[cfg(doc)]

code compiled only when building documentation — e.g. to document platform-specific items on every platform

#[cfg_attr(docsrs, doc(cfg(feature = "json")))]

show "Available on crate feature json only" badges on docs.rs (the doc_cfg feature is nightly; docs.rs builds with nightly)

Source: The rustdoc book: The #[doc attribute]

Re-exports

rustdoc documents an item where it is publicly reachable. A pub use of an item from a private module is inlined: the item appears in the re-exporting module as if defined there. A pub use of something already public elsewhere (for example from another crate) appears as a re-export link unless you add #[doc(inline)]. This lets a crate like shelf-core keep its modules private and present a flat API (see Modules, Crates & Visibility).

Documentation tests

Every fenced code block in a doc comment is, by default, a Rust doctest: rustdoc wraps it in fn main, links it against your crate, compiles it and runs it. Lines starting with +# + are compiled but hidden from the rendered docs — useful for setup code and for the Ok::<(), E>(()) trick that lets examples use ?. Fence attributes change how a block is treated:

Fence Behaviour

```rust or ```

compiled and run; must not panic

```no_run

compiled but not run (network calls, infinite loops, side effects)

```should_panic

must panic when run

```compile_fail

must fail to compile — documents what the API prevents

```ignore

not compiled at all (avoid; prefer no_run or text)

```text, ```toml, ```bash

not Rust: not tested

```edition2021

compile with a specific edition

```standalone_crate

opt out of combined doctests (2024) for this block

/// Parses a year printed on a title page.
///
/// ```
/// # use doccheck::parse_year; // hidden line: still compiled
/// assert_eq!(parse_year("© 1965"), Some(1965));
/// ```
///
/// Years before printing are rejected:
///
/// ```should_panic
/// # use doccheck::parse_year;
/// parse_year("1066").expect("printed books only");
/// ```
///
/// A year is a number, not a string:
///
/// ```compile_fail
/// let y: u16 = doccheck::parse_year("1965"); // Option<u16> is not u16
/// ```
pub fn parse_year(text: &str) -> Option<u16> {
    let digits: String = text.chars().filter(char::is_ascii_digit).collect();
    digits.parse().ok().filter(|y| *y >= 1450)
}
cargo test --doc
#    Doc-tests doccheck
# running 3 tests
# test src/lib.rs - parse_year (line 3) ... ok
# test src/lib.rs - parse_year (line 10) - should panic ... ok
# test src/lib.rs - parse_year (line 17) - compile fail ... ok

Since the 2024 edition, doctests are merged into one binary per crate where possible (combined doctests), which makes large documentation suites much faster to run; see Testing & Benchmarking.

rustdoc lints and scraped examples

Useful lints, set in code or in the [lints.rustdoc] table of Cargo.toml:

  • missing_docs (a rustc lint) — every public item must be documented; common in libraries as warn;

  • rustdoc::broken_intra_doc_links and rustdoc::private_intra_doc_links — link problems;

  • rustdoc::missing_crate_level_docs — no //! at the crate root;

  • rustdoc::bare_urls — a URL that is not a Markdown link;

  • rustdoc::invalid_codeblock_attributes, rustdoc::unescaped_backticks;

  • clippy::missing_errors_doc, missing_panics_doc, missing_safety_doc (pedantic) — missing sections.

Scraped examples (cargo doc -Zrustdoc-scrape-examples on nightly, enabled by default on docs.rs for crates that opt in through [package.metadata.docs.rs]) take real call sites from your examples/ directory and show them under each function.

cargo doc and docs.rs

cargo doc --open                    # build docs for your crate and all dependencies, open in a browser
cargo doc --no-deps                 # only your crate(s)
cargo doc --document-private-items  # include private items (for maintainers)
RUSTDOCFLAGS="-D warnings" cargo doc --no-deps   # fail CI on broken links and other rustdoc warnings

Every crate published to crates.io is built and hosted on https://docs.rs, with all versions kept. Configure the docs.rs build (features, targets, --cfg docsrs) in [package.metadata.docs.rs]. rustup doc --std opens the standard library documentation offline.