1- # Rustdoc Internals
1+ # Rustdoc internals
22
3- This page describes [ ` rustdoc ` ] 's passes and modes. For an overview of ` rustdoc ` ,
4- see the [ "Rustdoc overview" chapter] ( ./rustdoc.md ) .
3+ This page describes [ ` rustdoc ` ] 's passes and modes.
4+ For an overview of ` rustdoc ` , see the [ "Rustdoc overview" chapter] ( ./rustdoc.md ) .
55
66[ `rustdoc` ] : https://github.com/rust-lang/rust/tree/HEAD/src/tools/rustdoc
77
8- ## From Crate to Clean
8+ ## From crate to clean
99
1010In [ ` core.rs ` ] are two central items: the [ ` rustdoc::core::DocContext ` ]
11- ` struct ` , and the [ ` rustdoc::core::run_global_ctxt ` ] function. The latter is
12- where ` rustdoc ` calls out to ` rustc ` to compile a crate to the point where
13- ` rustdoc ` can take over. The former is a state container used when crawling
14- through a crate to gather its documentation.
11+ ` struct ` , and the [ ` rustdoc::core::run_global_ctxt ` ] function.
12+ The latter is where ` rustdoc ` calls out to ` rustc ` to compile a crate to the point where
13+ ` rustdoc ` can take over.
14+ The former is a state container used when crawling through a crate to gather its documentation.
1515
1616The main process of crate crawling is done in [ ` clean/mod.rs ` ] through several
17- functions with names that start with ` clean_ ` . Each function accepts an ` hir `
18- or ` ty ` data structure, and outputs a ` clean ` structure used by ` rustdoc ` . For
19- example, [ this function for converting lifetimes] :
17+ functions with names that start with ` clean_ ` .
18+ Each function accepts an ` hir `
19+ or ` ty ` data structure, and outputs a ` clean ` structure used by ` rustdoc ` .
20+ For example, [ this function for converting lifetimes] :
2021
2122``` rust,ignore
2223fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
@@ -34,17 +35,19 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) ->
3435```
3536
3637Also, ` clean/mod.rs ` defines the types for the "cleaned" [ Abstract Syntax Tree
37- (` AST ` )] [ ast ] used later to render documentation pages. Each usually accompanies a
38+ (` AST ` )] [ ast ] used later to render documentation pages.
39+ Each usually accompanies a
3840` clean_* ` function that takes some [ ` AST ` ] [ ast ] or [ High-Level Intermediate
39- Representation (` HIR ` )] [ hir ] type from ` rustc ` and converts it into the
40- appropriate "cleaned" type. "Big" items like modules or associated items may
41+ Representation (` HIR ` )] [ hir ] type from ` rustc ` and converts it into the appropriate "cleaned" type.
42+ "Big" items like modules or associated items may
4143have some extra processing in its ` clean ` function, but for the most part these
42- ` impl ` s are straightforward conversions. The "entry point" to this module is
44+ ` impl ` s are straightforward conversions.
45+ The "entry point" to this module is
4346[ ` clean::utils::krate ` ] [ ck0 ] , which is called by [ ` run_global_ctxt ` ] .
4447
4548The first step in [ ` clean::utils::krate ` ] [ ck1 ] is to invoke
46- [ ` visit_ast::RustdocVisitor ` ] to process the module tree into an intermediate
47- [ ` visit_ast::Module ` ] . This is the step that actually crawls the
49+ [ ` visit_ast::RustdocVisitor ` ] to process the module tree into an intermediate [ ` visit_ast::Module ` ] .
50+ This is the step that actually crawls the
4851[ ` rustc_hir::Crate ` ] , normalizing various aspects of name resolution, such as:
4952
5053 * handling ` #[doc(inline)] ` and ` #[doc(no_inline)] `
@@ -57,14 +60,14 @@ The first step in [`clean::utils::krate`][ck1] is to invoke
5760 they're defined as a reexport or not
5861
5962After this step, ` clean::krate ` invokes [ ` clean_doc_module ` ] , which actually
60- converts the ` HIR ` items to the cleaned [ ` AST ` ] [ ast ] . This is also the step where cross-
61- crate inlining is performed, which requires converting ` rustc_middle ` data
62- structures into the cleaned [ ` AST ` ] [ ast ] .
63+ converts the ` HIR ` items to the cleaned [ ` AST ` ] [ ast ] .
64+ This is also the step where cross-crate inlining is performed,
65+ which requires converting ` rustc_middle ` data structures into the cleaned [ ` AST ` ] [ ast ] .
6366
6467The other major thing that happens in ` clean/mod.rs ` is the collection of doc
6568comments and ` #[doc=""] ` attributes into a separate field of the [ ` Attributes ` ]
66- ` struct ` , present on anything that gets hand-written documentation. This makes it
67- easier to collect this documentation later in the process.
69+ ` struct ` , present on anything that gets hand-written documentation.
70+ This makes it easier to collect this documentation later in the process.
6871
6972The primary output of this process is a [ ` clean::types::Crate ` ] with a tree of [ ` Item ` ] s
7073which describe the publicly-documentable items in the target crate.
@@ -90,13 +93,14 @@ which describe the publicly-documentable items in the target crate.
9093### Passes Anything But a Gas Station (or: [ Hot Potato] ( https://www.youtube.com/watch?v=WNFBIt5HxdY ) )
9194
9295Before moving on to the next major step, a few important "passes" occur over
93- the cleaned [ ` AST ` ] [ ast ] . Several of these passes are ` lint ` s and reports, but some of
94- them mutate or generate new items.
96+ the cleaned [ ` AST ` ] [ ast ] .
97+ Several of these passes are ` lint ` s and reports, but some of them mutate or generate new items.
9598
9699These are all implemented in the [ ` librustdoc/passes ` ] directory, one file per pass.
97100By default, all of these passes are run on a crate, but the ones
98101regarding dropping private/hidden items can be bypassed by passing
99- ` --document-private-items ` to ` rustdoc ` . Note that unlike the previous set of [ ` AST ` ] [ ast ]
102+ ` --document-private-items ` to ` rustdoc ` .
103+ Note that, unlike the previous set of [ ` AST ` ] [ ast ]
100104transformations, the passes are run on the _ cleaned_ crate.
101105
102106Here is the list of passes as of <!-- date-check --> March 2023:
@@ -105,8 +109,7 @@ Here is the list of passes as of <!-- date-check --> March 2023:
105109 flag.
106110
107111- ` check-doc-test-visibility ` runs ` doctest ` visibility–related ` lint ` s. This pass
108- runs before ` strip-private ` , which is why it needs to be separate from
109- ` run-lints ` .
112+ runs before ` strip-private ` , which is why it needs to be separate from ` run-lints ` .
110113
111114- ` collect-intra-doc-links ` resolves [ intra-doc links] ( https://doc.rust-lang.org/nightly/rustdoc/write-documentation/linking-to-items-by-name.html ) .
112115
@@ -121,8 +124,8 @@ Here is the list of passes as of <!-- date-check --> March 2023:
121124
122125 - ` bare_urls ` detects links that are not linkified, e.g., in Markdown such as
123126 ` Go to https://example.com/. ` It suggests wrapping the link with angle brackets:
124- ` Go to <https://example.com/>. ` to linkify it. This is the code behind the <!--
125- date-check: may 2022 --> ` rustdoc::bare_urls ` ` lint ` .
127+ ` Go to <https://example.com/>. ` to linkify it.
128+ This is the code behind the <!-- date-check: may 2022 --> ` rustdoc::bare_urls ` ` lint ` .
126129
127130 - ` check_code_block_syntax ` validates syntax inside Rust code blocks
128131 (<code >```rust</code >)
@@ -131,33 +134,37 @@ Here is the list of passes as of <!-- date-check --> March 2023:
131134 in doc comments.
132135
133136- ` strip-hidden ` and ` strip-private ` strip all ` doc(hidden) ` and private items
134- from the output. ` strip-private ` implies ` strip-priv-imports ` . Basically, the
135- goal is to remove items that are not relevant for public documentation. This
136- pass is skipped when ` --document-hidden-items ` is passed.
137+ from the output.
138+ ` strip-private ` implies ` strip-priv-imports ` .
139+ Basically, the goal is to remove items that are not relevant for public documentation.
140+ This pass is skipped when ` --document-hidden-items ` is passed.
137141
138142- ` strip-priv-imports ` strips all private import statements (` use ` , `extern
139- crate` ) from a crate. This is necessary because ` rustdoc` will handle * public*
143+ crate`) from a crate.
144+ This is necessary because ` rustdoc ` will handle * public*
140145 imports by either inlining the item's documentation to the module or creating
141- a "Reexports" section with the import in it. The pass ensures that all of
142- these imports are actually relevant to documentation. It is technically
143- only run when ` --document-private-items ` is passed, but ` strip-private `
146+ a "Reexports" section with the import in it.
147+ The pass ensures that all of these imports are actually relevant to documentation.
148+ It is technically only run when ` --document-private-items ` is passed, but ` strip-private `
144149 accomplishes the same thing.
145150
146151- ` strip-private ` strips all private items from a crate which cannot be seen
147- externally. This pass is skipped when ` --document-private-items ` is passed.
152+ externally.
153+ This pass is skipped when ` --document-private-items ` is passed.
148154
149155There is also a [ ` stripper ` ] module in ` librustdoc/passes ` , but it is a
150- collection of utility functions for the ` strip-* ` passes and is not a pass
151- itself.
156+ collection of utility functions for the ` strip-* ` passes and is not a pass itself.
152157
153158[ `librustdoc/passes` ] : https://github.com/rust-lang/rust/tree/HEAD/src/librustdoc/passes
154159[ `stripper` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/passes/stripper/index.html
155160
156- ## From Clean To HTML
161+ ## From clean to HTML
157162
158- This is where the "second phase" in ` rustdoc ` begins. This phase primarily lives
163+ This is where the "second phase" in ` rustdoc ` begins.
164+ This phase primarily lives
159165in the [ ` librustdoc/formats ` ] and [ ` librustdoc/html ` ] folders, and it all starts with
160- [ ` formats::renderer::run_format ` ] . This code is responsible for setting up a type that
166+ [ ` formats::renderer::run_format ` ] .
167+ This code is responsible for setting up a type that
161168` impl FormatRenderer ` , which for ` HTML ` is [ ` Context ` ] .
162169
163170This structure contains methods that get called by ` run_format ` to drive the
@@ -168,8 +175,8 @@ doc rendering, which includes:
168175* ` after_krate ` generates other global resources like ` all.html `
169176
170177In ` item ` , the "page rendering" occurs, via a mixture of [ Askama] templates
171- and manual ` write!() ` calls, starting in [ ` html/layout.rs ` ] . The parts that have
172- not been converted to templates occur within a series of ` std::fmt::Display `
178+ and manual ` write!() ` calls, starting in [ ` html/layout.rs ` ] .
179+ The parts that have not been converted to templates occur within a series of ` std::fmt::Display `
173180implementations and functions that pass around a ` &mut std::fmt::Formatter ` .
174181
175182The parts that actually generate ` HTML ` from the items and documentation start
@@ -183,11 +190,13 @@ pieces like "how should I print a where clause as part of some other item".
183190
184191Whenever ` rustdoc ` comes across an item that should print hand-written
185192documentation alongside, it calls out to [ ` html/markdown.rs ` ] which interfaces
186- with the Markdown parser. This is exposed as a series of types that wrap a
187- string of Markdown, and implement ` fmt::Display ` to emit ` HTML ` text. It takes
188- special care to enable certain features like footnotes and tables and add
193+ with the Markdown parser.
194+ This is exposed as a series of types that wrap a
195+ string of Markdown, and implement ` fmt::Display ` to emit ` HTML ` text.
196+ It takes special care to enable certain features like footnotes and tables and add
189197syntax highlighting to Rust code blocks (via ` html/highlight.rs ` ) before
190- running the Markdown parser. There's also a function [ ` find_codes ` ] which is
198+ running the Markdown parser.
199+ There's also a function [ ` find_codes ` ] which is
191200called by ` find_testable_codes ` that specifically scans for Rust code blocks so
192201the test-runner code can find all the ` doctest ` s in the crate.
193202
@@ -208,11 +217,11 @@ the test-runner code can find all the `doctest`s in the crate.
208217[ video ] : https://www.youtube.com/watch?v=hOLAGYmUQV0
209218
210219It's important to note that ` rustdoc ` can ask the compiler for type information
211- directly, even during ` HTML ` generation. This [ didn't used to be the case] , and
220+ directly, even during ` HTML ` generation.
221+ This [ didn't used to be the case] , and
212222a lot of ` rustdoc ` 's architecture was designed around not doing that, but a
213223` TyCtxt ` is now passed to ` formats::renderer::run_format ` , which is used to
214- run generation for both ` HTML ` and the
215- (unstable as of <!-- date-check --> March 2023) JSON format.
224+ run generation for both ` HTML ` and the (unstable as of <!-- date-check --> Nov 2025) JSON format.
216225
217226This change has allowed other changes to remove data from the "clean" [ ` AST ` ] [ ast ]
218227that can be easily derived from ` TyCtxt ` queries, and we'll usually accept
@@ -222,18 +231,17 @@ is complicated from two other constraints that `rustdoc` runs under:
222231* Docs can be generated for crates that don't actually pass type checking.
223232 This is used for generating docs that cover mutually-exclusive platform
224233 configurations, such as ` libstd ` having a single package of docs that
225- cover all supported operating systems. This means ` rustdoc ` has to be able
226- to generate docs from ` HIR ` .
234+ cover all supported operating systems.
235+ This means ` rustdoc ` has to be able to generate docs from ` HIR ` .
227236* Docs can inline across crates. Since crate metadata doesn't contain ` HIR ` ,
228237 it must be possible to generate inlined docs from the ` rustc_middle ` data.
229238
230- The "clean" [ ` AST ` ] [ ast ] acts as a common output format for both input formats. There
231- is also some data in clean that doesn't correspond directly to ` HIR ` , such as
232- synthetic ` impl ` s for auto traits and blanket ` impl ` s generated by the
233- ` collect-trait-impls ` pass.
239+ The "clean" [ ` AST ` ] [ ast ] acts as a common output format for both input formats.
240+ There is also some data in clean that doesn't correspond directly to ` HIR ` , such as
241+ synthetic ` impl ` s for auto traits and blanket ` impl ` s generated by the ` collect-trait-impls ` pass.
234242
235- Some additional data is stored in
236- ` html::render::context::{Context, SharedContext} ` . These two types serve as
243+ Some additional data is stored in ` html::render::context::{Context, SharedContext} ` .
244+ These two types serve as
237245ways to segregate ` rustdoc ` 's data for an eventual future with multithreaded doc
238246generation, as well as just keeping things organized:
239247
@@ -247,44 +255,44 @@ generation, as well as just keeping things organized:
247255[ didn't used to be the case ] : https://github.com/rust-lang/rust/pull/80090
248256[ `SharedContext` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/html/render/context/struct.SharedContext.html
249257
250- ## Other Tricks Up Its Sleeve
258+ ## Other tricks up its sleeve
251259
252260All this describes the process for generating ` HTML ` documentation from a Rust
253- crate, but there are couple other major modes that ` rustdoc ` runs in. It can also
254- be run on a standalone Markdown file, or it can run ` doctest ` s on Rust code or
255- standalone Markdown files. For the former, it shortcuts straight to
261+ crate, but there are couple other major modes that ` rustdoc ` runs in.
262+ It can also be run on a standalone Markdown file, or it can run ` doctest ` s on Rust code or
263+ standalone Markdown files.
264+ For the former, it shortcuts straight to
256265` html/markdown.rs ` , optionally including a mode which inserts a Table of
257266Contents to the output ` HTML ` .
258267
259268For the latter, ` rustdoc ` runs a similar partial-compilation to get relevant
260269documentation in ` test.rs ` , but instead of going through the full clean and
261- render process, it runs a much simpler crate walk to grab * just* the
262- hand-written documentation. Combined with the aforementioned
270+ render process, it runs a much simpler crate walk to grab * just* the hand-written documentation.
271+ Combined with the aforementioned
263272"` find_testable_code ` " in ` html/markdown.rs ` , it builds up a collection of
264- tests to run before handing them off to the test runner. One notable location
265- in ` test.rs ` is the function ` make_test ` , which is where hand-written
273+ tests to run before handing them off to the test runner.
274+ One notable location in ` test.rs ` is the function ` make_test ` , which is where hand-written
266275` doctest ` s get transformed into something that can be executed.
267276
268277Some extra reading about ` make_test ` can be found
269278[ here] ( https://quietmisdreavus.net/code/2018/02/23/how-the-doctests-get-made/ ) .
270279
271- ## Testing Locally
280+ ## Testing locally
272281
273282Some features of the generated ` HTML ` documentation might require local
274- storage to be used across pages, which doesn't work well without an ` HTTP `
275- server. To test these features locally, you can run a local ` HTTP ` server, like
276- this:
283+ storage to be used across pages, which doesn't work well without an ` HTTP ` server.
284+ To test these features locally, you can run a local ` HTTP ` server, like this:
277285
278- ``` bash
286+ ``` console
279287$ ./x doc library
280288# The documentation has been generated into ` build/[YOUR ARCH]/doc` .
281289$ python3 -m http.server -d build/[YOUR ARCH]/doc
282290```
283291
284- Now you can browse your documentation just like you would if it was hosted
285- on the internet. For example, the url for ` std ` will be ` rust/std/ ` .
292+ Now you can browse your documentation just like you would if it was hosted on the internet.
293+ For example, the url for ` std ` will be ` rust/std/ ` .
286294
287- ## See Also
295+ ## See also
288296
289297- The [ ` rustdoc ` api docs]
290298- [ An overview of ` rustdoc ` ] ( ./rustdoc.md )
0 commit comments