rustdoc Overview
Purpose and Scope
rustdoc is the Rust distribution tool that turns Rust crate roots or Markdown inputs into browsable documentation. For most users, it appears indirectly through Cargo documentation builds, but it can also be invoked directly when a project, test, or release process needs precise control over input, output location, crate naming, doctests, or generated formats. In the Rust repository, rustdoc is not treated as a separate external project: it lives beside the compiler, standard library, and documentation as part of the main source tree. That placement matters because rustdoc shares compiler infrastructure rather than reimplementing parsing, name resolution, diagnostics, editions, target handling, and crate metadata from scratch.
Sources: README.md, src/librustdoc/lib.rs, src/librustdoc/config.rs
The repository README frames this tree as the main source repository for Rust and says it contains the compiler, standard library, and documentation. It also presents documentation and tooling as part of Rust productivity, alongside Cargo, rustfmt, Clippy, and rust-analyzer. rustdoc fits directly into that story: it is both a user-facing tool and an internal consumer of compiler libraries. When readers see generated standard library documentation or project documentation produced by Cargo, they are seeing output from a tool whose implementation is maintained in this same repository and built against the same compiler internals.
Sources: README.md, src/librustdoc/lib.rs
The official rustdoc book describes the essential task in practical terms: pass rustdoc a crate root or a Markdown file, and it produces a web site made of HTML, CSS, and JavaScript. A beginner can create a library package, run rustdoc over the generated crate root, and inspect a documentation page under a documentation output directory. The same docs explain two immediately visible behaviors: rustdoc infers a crate name from the input file unless it is overridden, and it documents public items by default. Those surface behaviors map to configuration fields and compiler-facing options in the repository implementation.
Sources: src/librustdoc/config.rs
Relevant Source Files
- README.md - Establishes this repository as the main Rust source tree and identifies documentation and advanced tooling as first-party parts of the Rust project.
- src/librustdoc/lib.rs - Contains the main library entry point for rustdoc, imports compiler crates from the sysroot, installs the rustdoc internal compiler error hook, declares the major rustdoc modules, and exposes public internal pieces needed by related generators.
- src/librustdoc/config.rs - Defines rustdoc configuration concepts such as output format, input mode, doctest merging mode, and the large options structure that carries user-facing flags and compiler options through the tool.
System-to-Code Mapping
At the top level, rustdoc is best understood as a compiler-adjacent documentation pipeline. The entry point in the rustdoc library initializes early diagnostics, installs an issue-reporting hook that labels internal compiler errors for the rustdoc team, and then delegates to modules that clean compiler data, build documentation models, render formats, run doctests, handle external files, lint documentation, process Markdown, and support HTML or JSON output. This is a strong signal that rustdoc is not merely a Markdown renderer. It needs a real Rust understanding of crates, items, visibility, attributes, links, type information, and compiler diagnostics.
Sources: src/librustdoc/lib.rs
The module list in the main rustdoc library gives a useful map for contributors. The cleaning layer converts compiler-facing representations into documentation-facing data. The configuration layer translates command line and compiler options into a single tool configuration. The core layer coordinates compiler interaction and diagnostic context. Rendering-related modules handle display, document file system interactions, external resources, Markdown, themes, HTML, and JSON. Doctesting is a separate concern because examples in documentation are executable Rust fragments, not just visual content. Visitors, folds, and passes support traversal and transformation of the documentation model before final output is emitted.
Sources: src/librustdoc/lib.rs
The configuration file shows how rustdoc bridges user intent and compiler machinery. Its imports include compiler session configuration, crate type parsing, extern parsing, target triple parsing, lint option extraction, search paths, editions, remapped path information, and target tuples. That means common rustdoc flags are not isolated settings; many become options that must be understood consistently with rustc. For example, library search paths, extern crate declarations, conditional configuration flags, code generation options, unstable options, target selection, error output formatting, and edition choice all need to be carried through a documentation run in a form the compiler interfaces can consume.
Sources: src/librustdoc/config.rs
Execution Flow
A typical direct invocation starts with an input file and a desired documentation output. The official workflow demonstrates running rustdoc on a library crate root, then opening the generated crate documentation in a browser. If no crate name is specified, rustdoc follows the compiler-like convention of deriving a name from the crate root file. If the documented function is private, the generated page may appear sparse because public API documentation is the default. Those behaviors are not incidental user-interface details; they reflect rustdoc’s mission to document crate APIs using Rust visibility and crate metadata rather than only comments found in source text.
Sources: src/librustdoc/config.rs
The repository implementation supports more execution modes than the simplest tutorial command suggests. The configuration defines an output format enum with HTML as the default, plus JSON and doctest variants. This allows rustdoc to serve multiple consumers: human-readable web documentation, structured documentation data for tools, and execution of documentation examples as tests. The input mode also distinguishes ordinary crate or Markdown input from the final step of a merge workflow that does not need a fresh input crate. Those enum definitions give maintainers a compact vocabulary for reasoning about which major path a rustdoc invocation is taking.
Sources: src/librustdoc/config.rs
Doctests deserve special attention because they make documentation part of the test surface. The configuration includes a merge mode that can be never, always, or automatic, describing whether multiple doctests should be run in the same binary. This is a performance and behavior control rather than a formatting option. A documentation command can therefore move from parsing comments and Markdown to compiling and executing Rust examples under compiler configuration. When a doctest fails, rustdoc must report diagnostics with enough context for a developer to fix the documented example, while still behaving like a documentation tool rather than a normal crate build.
Sources: src/librustdoc/config.rs
API Components and Configuration Reference
The most important public implementation entry point visible in the requested source is the rustdoc main function, which returns a process exit code. It sets up early diagnostics and an internal compiler error hook before the rest of the invocation proceeds. Around it, the library declares internal modules for cleaning, configuration, core orchestration, document file output, doctesting, error handling, external files, folding, formats, HTML, JSON, linting, Markdown, passes, example scraping, theming, visiting, AST visiting, and library visiting. The HTML module is public because another generator uses it, while most other modules remain internal to rustdoc’s implementation boundary.
Sources: src/librustdoc/lib.rs
Compact reference:
| Component | Source-level contract | Reader-facing meaning |
|---|---|---|
| main function | Entry point returning a process exit code | Starts a rustdoc process and reports success or failure to the shell |
| output format enum | JSON, HTML, or doctest | Selects structured output, web output, or documentation-test execution |
| input mode enum | No-input merge finalization or file-backed input | Distinguishes ordinary documentation input from a merge-finalize phase |
| doctest merge enum | Never, always, or automatic | Controls whether multiple documentation tests share a binary |
| options structure | Crate name, crate kind flags, diagnostics, library paths, externs, cfgs, compiler options, target, edition, and more | Carries user flags and compiler-compatible settings through the rustdoc run |
The configuration options structure is the central object to understand when tracing a command-line flag. It includes a crate name override, booleans for binary and procedural macro crates, error formatting and diagnostic width, library search paths, external crates, conditional compilation flags, checked configuration flags, code generation options, unstable compiler options, target information, and edition selection. This mirrors the practical rustdoc book examples. A crate-name flag changes where generated documentation is organized and what the page calls the crate; visibility controls affect what items appear; output arguments affect the destination; and compiler-style options affect how the crate is interpreted before documentation is produced.
Sources: src/librustdoc/config.rs
Implementation Details
rustdoc relies on many rustc crates through explicit external crate declarations in the library source. The comments explain that these need explicit declarations even in the modern edition because they are loaded implicitly from the sysroot, and rustdoc artifacts are not stored in the compiler cargo target directory. That implementation detail protects the build from spurious rebuilds when rustc crates would otherwise appear as normal Cargo dependencies. It also shows why rustdoc development often feels close to compiler development: changing compiler internals can affect rustdoc behavior, build mechanics, and documentation output.
Sources: src/librustdoc/lib.rs
The crate-level attributes in the rustdoc library also communicate project constraints. The source sets a nightly documentation root and a playground URL for generated documentation, enables several unstable language and library features, raises the recursion limit, and turns on internal lints. Those choices are normal for a tool built inside the Rust compiler repository: it can use compiler-private crates and unstable implementation facilities that ordinary stable Rust crates cannot. For contributors, this means rustdoc code should be read as part of the Rust toolchain implementation, not as a reusable library with the same constraints as an ecosystem crate published for stable users.
Sources: src/librustdoc/lib.rs
The configuration module imports static files, themes, external HTML handling, Markdown identifier maps, documentation passes, scraped example options, and compiler configuration helpers. This combination explains why rustdoc configuration is wider than just parsing flags. A generated documentation site needs static assets and themes, but the documented crate must also be parsed and checked under the correct target, edition, extern crate graph, lint configuration, and conditional compilation environment. The same invocation can therefore influence visible pages, generated links, example extraction, diagnostics, and the compiler session used to understand the source crate.
Sources: src/librustdoc/config.rs
User Workflow and Next Steps
For a new user, the simplest path is to treat rustdoc as the engine behind project documentation. Create or open a library crate, write public items with documentation comments, and run documentation generation through Cargo or direct rustdoc invocation when you need finer control. If the output crate name looks wrong, pass an explicit crate name. If an item does not appear, check whether it is public or whether you intentionally need private item documentation. If output appears in an unexpected location, set the output directory. These tasks align with the rustdoc book’s basic usage and with the configuration fields present in the implementation.
Sources: src/librustdoc/config.rs
For contributors, the next step is to decide which layer you are changing. Command-line behavior and option translation usually start in the configuration layer. Failures that involve compiler diagnostics, target handling, editions, search paths, externs, or conditional compilation require following the bridge between rustdoc options and rustc session configuration. Rendering issues usually lead toward the format, HTML, JSON, Markdown, theme, or static-file modules. Doctest behavior should be traced through the doctest mode and merge settings before investigating compiler execution. Keeping that map in mind prevents treating rustdoc as a single monolithic renderer and makes source navigation much faster.
Sources: src/librustdoc/lib.rs, src/librustdoc/config.rs
Related pages: rustdoc-command-line, cargo-getting-started, standard-library-overview, compiler-architecture