11# 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
88## 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,15 @@ 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-
63+ converts the ` HIR ` items to the cleaned [ ` AST ` ] [ ast ] .
64+ This is also the step where cross-
6165crate inlining is performed, which requires converting ` rustc_middle ` data
6266structures into the cleaned [ ` AST ` ] [ ast ] .
6367
6468The other major thing that happens in ` clean/mod.rs ` is the collection of doc
6569comments 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.
70+ ` struct ` , present on anything that gets hand-written documentation.
71+ This makes it easier to collect this documentation later in the process.
6872
6973The primary output of this process is a [ ` clean::types::Crate ` ] with a tree of [ ` Item ` ] s
7074which describe the publicly-documentable items in the target crate.
@@ -90,13 +94,14 @@ which describe the publicly-documentable items in the target crate.
9094### Passes Anything But a Gas Station (or: [ Hot Potato] ( https://www.youtube.com/watch?v=WNFBIt5HxdY ) )
9195
9296Before 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.
97+ the cleaned [ ` AST ` ] [ ast ] .
98+ Several of these passes are ` lint ` s and reports, but some of them mutate or generate new items.
9599
96100These are all implemented in the [ ` librustdoc/passes ` ] directory, one file per pass.
97101By default, all of these passes are run on a crate, but the ones
98102regarding dropping private/hidden items can be bypassed by passing
99- ` --document-private-items ` to ` rustdoc ` . Note that unlike the previous set of [ ` AST ` ] [ ast ]
103+ ` --document-private-items ` to ` rustdoc ` .
104+ Note that unlike the previous set of [ ` AST ` ] [ ast ]
100105transformations, the passes are run on the _ cleaned_ crate.
101106
102107Here is the list of passes as of <!-- date-check --> March 2023:
@@ -105,8 +110,7 @@ Here is the list of passes as of <!-- date-check --> March 2023:
105110 flag.
106111
107112- ` 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 ` .
113+ runs before ` strip-private ` , which is why it needs to be separate from ` run-lints ` .
110114
111115- ` collect-intra-doc-links ` resolves [ intra-doc links] ( https://doc.rust-lang.org/nightly/rustdoc/write-documentation/linking-to-items-by-name.html ) .
112116
@@ -121,8 +125,8 @@ Here is the list of passes as of <!-- date-check --> March 2023:
121125
122126 - ` bare_urls ` detects links that are not linkified, e.g., in Markdown such as
123127 ` 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 ` .
128+ ` Go to <https://example.com/>. ` to linkify it.
129+ This is the code behind the <!-- date-check: may 2022 --> ` rustdoc::bare_urls ` ` lint ` .
126130
127131 - ` check_code_block_syntax ` validates syntax inside Rust code blocks
128132 (<code >```rust</code >)
@@ -131,33 +135,37 @@ Here is the list of passes as of <!-- date-check --> March 2023:
131135 in doc comments.
132136
133137- ` 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.
138+ from the output.
139+ ` strip-private ` implies ` strip-priv-imports ` .
140+ Basically, the goal is to remove items that are not relevant for public documentation.
141+ This pass is skipped when ` --document-hidden-items ` is passed.
137142
138143- ` strip-priv-imports ` strips all private import statements (` use ` , `extern
139- crate` ) from a crate. This is necessary because ` rustdoc` will handle * public*
144+ crate`) from a crate.
145+ This is necessary because ` rustdoc ` will handle * public*
140146 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 `
147+ a "Reexports" section with the import in it.
148+ The pass ensures that all of these imports are actually relevant to documentation.
149+ It is technically only run when ` --document-private-items ` is passed, but ` strip-private `
144150 accomplishes the same thing.
145151
146152- ` 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.
153+ externally.
154+ This pass is skipped when ` --document-private-items ` is passed.
148155
149156There 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.
157+ collection of utility functions for the ` strip-* ` passes and is not a pass itself.
152158
153159[ `librustdoc/passes` ] : https://github.com/rust-lang/rust/tree/HEAD/src/librustdoc/passes
154160[ `stripper` ] : https://doc.rust-lang.org/nightly/nightly-rustc/rustdoc/passes/stripper/index.html
155161
156162## From clean to HTML
157163
158- This is where the "second phase" in ` rustdoc ` begins. This phase primarily lives
164+ This is where the "second phase" in ` rustdoc ` begins.
165+ This phase primarily lives
159166in 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
167+ [ ` formats::renderer::run_format ` ] .
168+ This code is responsible for setting up a type that
161169` impl FormatRenderer ` , which for ` HTML ` is [ ` Context ` ] .
162170
163171This structure contains methods that get called by ` run_format ` to drive the
@@ -168,8 +176,8 @@ doc rendering, which includes:
168176* ` after_krate ` generates other global resources like ` all.html `
169177
170178In ` 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 `
179+ and manual ` write!() ` calls, starting in [ ` html/layout.rs ` ] .
180+ The parts that have not been converted to templates occur within a series of ` std::fmt::Display `
173181implementations and functions that pass around a ` &mut std::fmt::Formatter ` .
174182
175183The parts that actually generate ` HTML ` from the items and documentation start
@@ -183,11 +191,13 @@ pieces like "how should I print a where clause as part of some other item".
183191
184192Whenever ` rustdoc ` comes across an item that should print hand-written
185193documentation 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
194+ with the Markdown parser.
195+ This is exposed as a series of types that wrap a
196+ string of Markdown, and implement ` fmt::Display ` to emit ` HTML ` text.
197+ It takes special care to enable certain features like footnotes and tables and add
189198syntax highlighting to Rust code blocks (via ` html/highlight.rs ` ) before
190- running the Markdown parser. There's also a function [ ` find_codes ` ] which is
199+ running the Markdown parser.
200+ There's also a function [ ` find_codes ` ] which is
191201called by ` find_testable_codes ` that specifically scans for Rust code blocks so
192202the test-runner code can find all the ` doctest ` s in the crate.
193203
@@ -208,11 +218,11 @@ the test-runner code can find all the `doctest`s in the crate.
208218[ video ] : https://www.youtube.com/watch?v=hOLAGYmUQV0
209219
210220It'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
221+ directly, even during ` HTML ` generation.
222+ This [ didn't used to be the case] , and
212223a lot of ` rustdoc ` 's architecture was designed around not doing that, but a
213224` 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.
225+ run generation for both ` HTML ` and the (unstable as of <!-- date-check --> March 2023) JSON format.
216226
217227This change has allowed other changes to remove data from the "clean" [ ` AST ` ] [ ast ]
218228that can be easily derived from ` TyCtxt ` queries, and we'll usually accept
@@ -222,18 +232,17 @@ is complicated from two other constraints that `rustdoc` runs under:
222232* Docs can be generated for crates that don't actually pass type checking.
223233 This is used for generating docs that cover mutually-exclusive platform
224234 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 ` .
235+ cover all supported operating systems.
236+ This means ` rustdoc ` has to be able to generate docs from ` HIR ` .
227237* Docs can inline across crates. Since crate metadata doesn't contain ` HIR ` ,
228238 it must be possible to generate inlined docs from the ` rustc_middle ` data.
229239
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.
240+ The "clean" [ ` AST ` ] [ ast ] acts as a common output format for both input formats.
241+ There is also some data in clean that doesn't correspond directly to ` HIR ` , such as
242+ synthetic ` impl ` s for auto traits and blanket ` impl ` s generated by the ` collect-trait-impls ` pass.
234243
235- Some additional data is stored in
236- ` html::render::context::{Context, SharedContext} ` . These two types serve as
244+ Some additional data is stored in ` html::render::context::{Context, SharedContext} ` .
245+ These two types serve as
237246ways to segregate ` rustdoc ` 's data for an eventual future with multithreaded doc
238247generation, as well as just keeping things organized:
239248
@@ -250,19 +259,20 @@ generation, as well as just keeping things organized:
250259## Other tricks up its sleeve
251260
252261All 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
262+ crate, but there are couple other major modes that ` rustdoc ` runs in.
263+ It can also be run on a standalone Markdown file, or it can run ` doctest ` s on Rust code or
264+ standalone Markdown files.
265+ For the former, it shortcuts straight to
256266` html/markdown.rs ` , optionally including a mode which inserts a Table of
257267Contents to the output ` HTML ` .
258268
259269For the latter, ` rustdoc ` runs a similar partial-compilation to get relevant
260270documentation 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
271+ render process, it runs a much simpler crate walk to grab * just* the hand-written documentation.
272+ Combined with the aforementioned
263273"` 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
274+ tests to run before handing them off to the test runner.
275+ One notable location in ` test.rs ` is the function ` make_test ` , which is where hand-written
266276` doctest ` s get transformed into something that can be executed.
267277
268278Some extra reading about ` make_test ` can be found
@@ -271,18 +281,17 @@ Some extra reading about `make_test` can be found
271281## Testing locally
272282
273283Some 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:
284+ storage to be used across pages, which doesn't work well without an ` HTTP ` server.
285+ To test these features locally, you can run a local ` HTTP ` server, like this:
277286
278287``` bash
279288$ ./x doc library
280289# The documentation has been generated into `build/[YOUR ARCH]/doc`.
281290$ python3 -m http.server -d build/[YOUR ARCH]/doc
282291```
283292
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/ ` .
293+ Now you can browse your documentation just like you would if it was hosted on the internet.
294+ For example, the url for ` std ` will be ` rust/std/ ` .
286295
287296## See also
288297
0 commit comments