1#![doc(
3 html_root_url = "https://doc.rust-lang.org/nightly/",
4 html_playground_url = "https://play.rust-lang.org/"
5)]
6#![feature(ascii_char)]
7#![feature(ascii_char_variants)]
8#![feature(assert_matches)]
9#![feature(box_patterns)]
10#![feature(debug_closure_helpers)]
11#![feature(file_buffered)]
12#![feature(format_args_nl)]
13#![feature(if_let_guard)]
14#![feature(iter_intersperse)]
15#![feature(round_char_boundary)]
16#![feature(rustc_private)]
17#![feature(test)]
18#![warn(rustc::internal)]
19extern crate thin_vec;
22
23extern crate pulldown_cmark;
32extern crate rustc_abi;
33extern crate rustc_ast;
34extern crate rustc_ast_pretty;
35extern crate rustc_attr_data_structures;
36extern crate rustc_attr_parsing;
37extern crate rustc_data_structures;
38extern crate rustc_driver;
39extern crate rustc_errors;
40extern crate rustc_expand;
41extern crate rustc_feature;
42extern crate rustc_hir;
43extern crate rustc_hir_analysis;
44extern crate rustc_hir_pretty;
45extern crate rustc_index;
46extern crate rustc_infer;
47extern crate rustc_interface;
48extern crate rustc_lexer;
49extern crate rustc_lint;
50extern crate rustc_lint_defs;
51extern crate rustc_log;
52extern crate rustc_macros;
53extern crate rustc_metadata;
54extern crate rustc_middle;
55extern crate rustc_parse;
56extern crate rustc_passes;
57extern crate rustc_resolve;
58extern crate rustc_serialize;
59extern crate rustc_session;
60extern crate rustc_span;
61extern crate rustc_target;
62extern crate rustc_trait_selection;
63extern crate test;
64
65#[cfg(feature = "jemalloc")]
68extern crate tikv_jemalloc_sys as jemalloc_sys;
69
70use std::env::{self, VarError};
71use std::io::{self, IsTerminal};
72use std::path::Path;
73use std::process;
74
75use rustc_errors::DiagCtxtHandle;
76use rustc_hir::def_id::LOCAL_CRATE;
77use rustc_interface::interface;
78use rustc_middle::ty::TyCtxt;
79use rustc_session::config::{ErrorOutputType, RustcOptGroup, make_crate_type_option};
80use rustc_session::{EarlyDiagCtxt, getopts};
81use tracing::info;
82
83use crate::clean::utils::DOC_RUST_LANG_ORG_VERSION;
84
85macro_rules! map {
96 ($( $key: expr => $val: expr ),* $(,)*) => {{
97 let mut map = ::rustc_data_structures::fx::FxIndexMap::default();
98 $( map.insert($key, $val); )*
99 map
100 }}
101}
102
103mod clean;
104mod config;
105mod core;
106mod display;
107mod docfs;
108mod doctest;
109mod error;
110mod externalfiles;
111mod fold;
112mod formats;
113pub mod html;
115mod json;
116pub(crate) mod lint;
117mod markdown;
118mod passes;
119mod scrape_examples;
120mod theme;
121mod visit;
122mod visit_ast;
123mod visit_lib;
124
125pub fn main() {
126 #[cfg(feature = "jemalloc")]
129 {
130 use std::os::raw::{c_int, c_void};
131
132 #[used]
133 static _F1: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::calloc;
134 #[used]
135 static _F2: unsafe extern "C" fn(*mut *mut c_void, usize, usize) -> c_int =
136 jemalloc_sys::posix_memalign;
137 #[used]
138 static _F3: unsafe extern "C" fn(usize, usize) -> *mut c_void = jemalloc_sys::aligned_alloc;
139 #[used]
140 static _F4: unsafe extern "C" fn(usize) -> *mut c_void = jemalloc_sys::malloc;
141 #[used]
142 static _F5: unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void = jemalloc_sys::realloc;
143 #[used]
144 static _F6: unsafe extern "C" fn(*mut c_void) = jemalloc_sys::free;
145
146 #[cfg(target_os = "macos")]
147 {
148 unsafe extern "C" {
149 fn _rjem_je_zone_register();
150 }
151
152 #[used]
153 static _F7: unsafe extern "C" fn() = _rjem_je_zone_register;
154 }
155 }
156
157 let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default());
158
159 rustc_driver::install_ice_hook(
160 "https://github.com/rust-lang/rust/issues/new\
161 ?labels=C-bug%2C+I-ICE%2C+T-rustdoc&template=ice.md",
162 |_| (),
163 );
164
165 crate::init_logging(&early_dcx);
173 match rustc_log::init_logger(rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")) {
174 Ok(()) => {}
175 Err(rustc_log::Error::AlreadyInit(_)) => {}
191 Err(error) => early_dcx.early_fatal(error.to_string()),
192 }
193
194 let exit_code = rustc_driver::catch_with_exit_code(|| {
195 let at_args = rustc_driver::args::raw_args(&early_dcx);
196 main_args(&mut early_dcx, &at_args);
197 });
198 process::exit(exit_code);
199}
200
201fn init_logging(early_dcx: &EarlyDiagCtxt) {
202 let color_logs = match env::var("RUSTDOC_LOG_COLOR").as_deref() {
203 Ok("always") => true,
204 Ok("never") => false,
205 Ok("auto") | Err(VarError::NotPresent) => io::stdout().is_terminal(),
206 Ok(value) => early_dcx.early_fatal(format!(
207 "invalid log color value '{value}': expected one of always, never, or auto",
208 )),
209 Err(VarError::NotUnicode(value)) => early_dcx.early_fatal(format!(
210 "invalid log color value '{}': expected one of always, never, or auto",
211 value.to_string_lossy()
212 )),
213 };
214 let filter = tracing_subscriber::EnvFilter::from_env("RUSTDOC_LOG");
215 let layer = tracing_tree::HierarchicalLayer::default()
216 .with_writer(io::stderr)
217 .with_ansi(color_logs)
218 .with_targets(true)
219 .with_wraparound(10)
220 .with_verbose_exit(true)
221 .with_verbose_entry(true)
222 .with_indent_amount(2);
223 #[cfg(debug_assertions)]
224 let layer = layer.with_thread_ids(true).with_thread_names(true);
225
226 use tracing_subscriber::layer::SubscriberExt;
227 let subscriber = tracing_subscriber::Registry::default().with(filter).with(layer);
228 tracing::subscriber::set_global_default(subscriber).unwrap();
229}
230
231fn opts() -> Vec<RustcOptGroup> {
232 use rustc_session::config::OptionKind::{Flag, FlagMulti, Multi, Opt};
233 use rustc_session::config::OptionStability::{Stable, Unstable};
234 use rustc_session::config::make_opt as opt;
235
236 vec![
237 opt(Stable, FlagMulti, "h", "help", "show this help message", ""),
238 opt(Stable, FlagMulti, "V", "version", "print rustdoc's version", ""),
239 opt(Stable, FlagMulti, "v", "verbose", "use verbose output", ""),
240 opt(Stable, Opt, "w", "output-format", "the output type to write", "[html]"),
241 opt(
242 Stable,
243 Opt,
244 "",
245 "output",
246 "Which directory to place the output. This option is deprecated, use --out-dir instead.",
247 "PATH",
248 ),
249 opt(Stable, Opt, "o", "out-dir", "which directory to place the output", "PATH"),
250 opt(Stable, Opt, "", "crate-name", "specify the name of this crate", "NAME"),
251 make_crate_type_option(),
252 opt(Stable, Multi, "L", "library-path", "directory to add to crate search path", "DIR"),
253 opt(Stable, Multi, "", "cfg", "pass a --cfg to rustc", ""),
254 opt(Stable, Multi, "", "check-cfg", "pass a --check-cfg to rustc", ""),
255 opt(Stable, Multi, "", "extern", "pass an --extern to rustc", "NAME[=PATH]"),
256 opt(
257 Unstable,
258 Multi,
259 "",
260 "extern-html-root-url",
261 "base URL to use for dependencies; for example, \
262 \"std=/doc\" links std::vec::Vec to /doc/std/vec/struct.Vec.html",
263 "NAME=URL",
264 ),
265 opt(
266 Unstable,
267 FlagMulti,
268 "",
269 "extern-html-root-takes-precedence",
270 "give precedence to `--extern-html-root-url`, not `html_root_url`",
271 "",
272 ),
273 opt(Stable, Multi, "C", "codegen", "pass a codegen option to rustc", "OPT[=VALUE]"),
274 opt(Stable, FlagMulti, "", "document-private-items", "document private items", ""),
275 opt(
276 Unstable,
277 FlagMulti,
278 "",
279 "document-hidden-items",
280 "document items that have doc(hidden)",
281 "",
282 ),
283 opt(Stable, FlagMulti, "", "test", "run code examples as tests", ""),
284 opt(Stable, Multi, "", "test-args", "arguments to pass to the test runner", "ARGS"),
285 opt(
286 Stable,
287 Opt,
288 "",
289 "test-run-directory",
290 "The working directory in which to run tests",
291 "PATH",
292 ),
293 opt(Stable, Opt, "", "target", "target triple to document", "TRIPLE"),
294 opt(
295 Stable,
296 Multi,
297 "",
298 "markdown-css",
299 "CSS files to include via <link> in a rendered Markdown file",
300 "FILES",
301 ),
302 opt(
303 Stable,
304 Multi,
305 "",
306 "html-in-header",
307 "files to include inline in the <head> section of a rendered Markdown file \
308 or generated documentation",
309 "FILES",
310 ),
311 opt(
312 Stable,
313 Multi,
314 "",
315 "html-before-content",
316 "files to include inline between <body> and the content of a rendered \
317 Markdown file or generated documentation",
318 "FILES",
319 ),
320 opt(
321 Stable,
322 Multi,
323 "",
324 "html-after-content",
325 "files to include inline between the content and </body> of a rendered \
326 Markdown file or generated documentation",
327 "FILES",
328 ),
329 opt(
330 Unstable,
331 Multi,
332 "",
333 "markdown-before-content",
334 "files to include inline between <body> and the content of a rendered \
335 Markdown file or generated documentation",
336 "FILES",
337 ),
338 opt(
339 Unstable,
340 Multi,
341 "",
342 "markdown-after-content",
343 "files to include inline between the content and </body> of a rendered \
344 Markdown file or generated documentation",
345 "FILES",
346 ),
347 opt(Stable, Opt, "", "markdown-playground-url", "URL to send code snippets to", "URL"),
348 opt(Stable, FlagMulti, "", "markdown-no-toc", "don't include table of contents", ""),
349 opt(
350 Stable,
351 Opt,
352 "e",
353 "extend-css",
354 "To add some CSS rules with a given file to generate doc with your own theme. \
355 However, your theme might break if the rustdoc's generated HTML changes, so be careful!",
356 "PATH",
357 ),
358 opt(
359 Unstable,
360 Multi,
361 "Z",
362 "",
363 "unstable / perma-unstable options (only on nightly build)",
364 "FLAG",
365 ),
366 opt(Stable, Opt, "", "sysroot", "Override the system root", "PATH"),
367 opt(
368 Unstable,
369 Opt,
370 "",
371 "playground-url",
372 "URL to send code snippets to, may be reset by --markdown-playground-url \
373 or `#![doc(html_playground_url=...)]`",
374 "URL",
375 ),
376 opt(
377 Unstable,
378 FlagMulti,
379 "",
380 "display-doctest-warnings",
381 "show warnings that originate in doctests",
382 "",
383 ),
384 opt(
385 Stable,
386 Opt,
387 "",
388 "crate-version",
389 "crate version to print into documentation",
390 "VERSION",
391 ),
392 opt(
393 Unstable,
394 FlagMulti,
395 "",
396 "sort-modules-by-appearance",
397 "sort modules by where they appear in the program, rather than alphabetically",
398 "",
399 ),
400 opt(
401 Stable,
402 Opt,
403 "",
404 "default-theme",
405 "Set the default theme. THEME should be the theme name, generally lowercase. \
406 If an unknown default theme is specified, the builtin default is used. \
407 The set of themes, and the rustdoc built-in default, are not stable.",
408 "THEME",
409 ),
410 opt(
411 Unstable,
412 Multi,
413 "",
414 "default-setting",
415 "Default value for a rustdoc setting (used when \"rustdoc-SETTING\" is absent \
416 from web browser Local Storage). If VALUE is not supplied, \"true\" is used. \
417 Supported SETTINGs and VALUEs are not documented and not stable.",
418 "SETTING[=VALUE]",
419 ),
420 opt(
421 Stable,
422 Multi,
423 "",
424 "theme",
425 "additional themes which will be added to the generated docs",
426 "FILES",
427 ),
428 opt(Stable, Multi, "", "check-theme", "check if given theme is valid", "FILES"),
429 opt(
430 Unstable,
431 Opt,
432 "",
433 "resource-suffix",
434 "suffix to add to CSS and JavaScript files, \
435 e.g., \"search-index.js\" will become \"search-index-suffix.js\"",
436 "PATH",
437 ),
438 opt(
439 Stable,
440 Opt,
441 "",
442 "edition",
443 "edition to use when compiling rust code (default: 2015)",
444 "EDITION",
445 ),
446 opt(
447 Stable,
448 Opt,
449 "",
450 "color",
451 "Configure coloring of output:
452 auto = colorize, if output goes to a tty (default);
453 always = always colorize output;
454 never = never colorize output",
455 "auto|always|never",
456 ),
457 opt(
458 Stable,
459 Opt,
460 "",
461 "error-format",
462 "How errors and other messages are produced",
463 "human|json|short",
464 ),
465 opt(
466 Stable,
467 Opt,
468 "",
469 "diagnostic-width",
470 "Provide width of the output for truncated error messages",
471 "WIDTH",
472 ),
473 opt(Stable, Opt, "", "json", "Configure the structure of JSON diagnostics", "CONFIG"),
474 opt(Stable, Multi, "A", "allow", "Set lint allowed", "LINT"),
475 opt(Stable, Multi, "W", "warn", "Set lint warnings", "LINT"),
476 opt(Stable, Multi, "", "force-warn", "Set lint force-warn", "LINT"),
477 opt(Stable, Multi, "D", "deny", "Set lint denied", "LINT"),
478 opt(Stable, Multi, "F", "forbid", "Set lint forbidden", "LINT"),
479 opt(
480 Stable,
481 Multi,
482 "",
483 "cap-lints",
484 "Set the most restrictive lint level. \
485 More restrictive lints are capped at this level. \
486 By default, it is at `forbid` level.",
487 "LEVEL",
488 ),
489 opt(Unstable, Opt, "", "index-page", "Markdown file to be used as index page", "PATH"),
490 opt(
491 Unstable,
492 FlagMulti,
493 "",
494 "enable-index-page",
495 "To enable generation of the index page",
496 "",
497 ),
498 opt(
499 Unstable,
500 Opt,
501 "",
502 "static-root-path",
503 "Path string to force loading static files from in output pages. \
504 If not set, uses combinations of '../' to reach the documentation root.",
505 "PATH",
506 ),
507 opt(
508 Unstable,
509 Opt,
510 "",
511 "persist-doctests",
512 "Directory to persist doctest executables into",
513 "PATH",
514 ),
515 opt(
516 Unstable,
517 FlagMulti,
518 "",
519 "show-coverage",
520 "calculate percentage of public items with documentation",
521 "",
522 ),
523 opt(
524 Stable,
525 Opt,
526 "",
527 "test-runtool",
528 "",
529 "The tool to run tests with when building for a different target than host",
530 ),
531 opt(
532 Stable,
533 Multi,
534 "",
535 "test-runtool-arg",
536 "",
537 "One argument (of possibly many) to pass to the runtool",
538 ),
539 opt(
540 Unstable,
541 Opt,
542 "",
543 "test-builder",
544 "The rustc-like binary to use as the test builder",
545 "PATH",
546 ),
547 opt(
548 Unstable,
549 Multi,
550 "",
551 "test-builder-wrapper",
552 "Wrapper program to pass test-builder and arguments",
553 "PATH",
554 ),
555 opt(Unstable, FlagMulti, "", "check", "Run rustdoc checks", ""),
556 opt(
557 Unstable,
558 FlagMulti,
559 "",
560 "generate-redirect-map",
561 "Generate JSON file at the top level instead of generating HTML redirection files",
562 "",
563 ),
564 opt(
565 Unstable,
566 Multi,
567 "",
568 "emit",
569 "Comma separated list of types of output for rustdoc to emit",
570 "[unversioned-shared-resources,toolchain-shared-resources,invocation-specific,dep-info]",
571 ),
572 opt(Unstable, FlagMulti, "", "no-run", "Compile doctests without running them", ""),
573 opt(
574 Unstable,
575 Multi,
576 "",
577 "remap-path-prefix",
578 "Remap source names in compiler messages",
579 "FROM=TO",
580 ),
581 opt(
582 Unstable,
583 FlagMulti,
584 "",
585 "show-type-layout",
586 "Include the memory layout of types in the docs",
587 "",
588 ),
589 opt(Unstable, Flag, "", "nocapture", "Don't capture stdout and stderr of tests", ""),
590 opt(
591 Unstable,
592 Flag,
593 "",
594 "generate-link-to-definition",
595 "Make the identifiers in the HTML source code pages navigable",
596 "",
597 ),
598 opt(
599 Unstable,
600 Opt,
601 "",
602 "scrape-examples-output-path",
603 "",
604 "collect function call information and output at the given path",
605 ),
606 opt(
607 Unstable,
608 Multi,
609 "",
610 "scrape-examples-target-crate",
611 "",
612 "collect function call information for functions from the target crate",
613 ),
614 opt(Unstable, Flag, "", "scrape-tests", "Include test code when scraping examples", ""),
615 opt(
616 Unstable,
617 Multi,
618 "",
619 "with-examples",
620 "",
621 "path to function call information (for displaying examples in the documentation)",
622 ),
623 opt(
624 Unstable,
625 Opt,
626 "",
627 "merge",
628 "Controls how rustdoc handles files from previously documented crates in the doc root\n\
629 none = Do not write cross-crate information to the --out-dir\n\
630 shared = Append current crate's info to files found in the --out-dir\n\
631 finalize = Write current crate's info and --include-parts-dir info to the --out-dir, overwriting conflicting files",
632 "none|shared|finalize",
633 ),
634 opt(
635 Unstable,
636 Opt,
637 "",
638 "parts-out-dir",
639 "Writes trait implementations and other info for the current crate to provided path. Only use with --merge=none",
640 "path/to/doc.parts/<crate-name>",
641 ),
642 opt(
643 Unstable,
644 Multi,
645 "",
646 "include-parts-dir",
647 "Includes trait implementations and other crate info from provided path. Only use with --merge=finalize",
648 "path/to/doc.parts/<crate-name>",
649 ),
650 opt(Unstable, Flag, "", "html-no-source", "Disable HTML source code pages generation", ""),
651 opt(
652 Unstable,
653 Multi,
654 "",
655 "doctest-build-arg",
656 "One argument (of possibly many) to be used when compiling doctests",
657 "ARG",
658 ),
659 opt(
660 Unstable,
661 FlagMulti,
662 "",
663 "disable-minification",
664 "disable the minification of CSS/JS files (perma-unstable, do not use with cached files)",
665 "",
666 ),
667 opt(
669 Stable,
670 Multi,
671 "",
672 "plugin-path",
673 "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information",
674 "DIR",
675 ),
676 opt(
677 Stable,
678 Multi,
679 "",
680 "passes",
681 "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information",
682 "PASSES",
683 ),
684 opt(
685 Stable,
686 Multi,
687 "",
688 "plugins",
689 "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information",
690 "PLUGINS",
691 ),
692 opt(
693 Stable,
694 FlagMulti,
695 "",
696 "no-defaults",
697 "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information",
698 "",
699 ),
700 opt(
701 Stable,
702 Opt,
703 "r",
704 "input-format",
705 "removed, see issue #44136 <https://github.com/rust-lang/rust/issues/44136> for more information",
706 "[rust]",
707 ),
708 ]
709}
710
711fn usage(argv0: &str) {
712 let mut options = getopts::Options::new();
713 for option in opts() {
714 option.apply(&mut options);
715 }
716 println!("{}", options.usage(&format!("{argv0} [options] <input>")));
717 println!(" @path Read newline separated options from `path`\n");
718 println!(
719 "More information available at {DOC_RUST_LANG_ORG_VERSION}/rustdoc/what-is-rustdoc.html",
720 );
721}
722
723pub(crate) fn wrap_return(dcx: DiagCtxtHandle<'_>, res: Result<(), String>) {
724 match res {
725 Ok(()) => dcx.abort_if_errors(),
726 Err(err) => dcx.fatal(err),
727 }
728}
729
730fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
731 krate: clean::Crate,
732 renderopts: config::RenderOptions,
733 cache: formats::cache::Cache,
734 tcx: TyCtxt<'tcx>,
735) {
736 match formats::run_format::<T>(krate, renderopts, cache, tcx) {
737 Ok(_) => tcx.dcx().abort_if_errors(),
738 Err(e) => {
739 let mut msg =
740 tcx.dcx().struct_fatal(format!("couldn't generate documentation: {}", e.error));
741 let file = e.file.display().to_string();
742 if !file.is_empty() {
743 msg.note(format!("failed to create or modify \"{file}\""));
744 }
745 msg.emit();
746 }
747 }
748}
749
750fn run_merge_finalize(opt: config::RenderOptions) -> Result<(), error::Error> {
754 assert!(
755 opt.should_merge.write_rendered_cci,
756 "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize"
757 );
758 assert!(
759 !opt.should_merge.read_rendered_cci,
760 "config.rs only allows us to return InputMode::NoInputMergeFinalize if --merge=finalize"
761 );
762 let crates = html::render::CrateInfo::read_many(&opt.include_parts_dir)?;
763 let include_sources = !opt.html_no_source;
764 html::render::write_not_crate_specific(
765 &crates,
766 &opt.output,
767 &opt,
768 &opt.themes,
769 opt.extension_css.as_deref(),
770 &opt.resource_suffix,
771 include_sources,
772 )?;
773 Ok(())
774}
775
776fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) {
777 let at_args = at_args.get(1..).unwrap_or_default();
786
787 let args = rustc_driver::args::arg_expand_all(early_dcx, at_args);
788
789 let mut options = getopts::Options::new();
790 for option in opts() {
791 option.apply(&mut options);
792 }
793 let matches = match options.parse(&args) {
794 Ok(m) => m,
795 Err(err) => {
796 early_dcx.early_fatal(err.to_string());
797 }
798 };
799
800 let (input, options, render_options) =
803 match config::Options::from_matches(early_dcx, &matches, args) {
804 Some(opts) => opts,
805 None => return,
806 };
807
808 let dcx =
809 core::new_dcx(options.error_format, None, options.diagnostic_width, &options.unstable_opts);
810 let dcx = dcx.handle();
811
812 let input = match input {
813 config::InputMode::HasFile(input) => input,
814 config::InputMode::NoInputMergeFinalize => {
815 return wrap_return(
816 dcx,
817 run_merge_finalize(render_options)
818 .map_err(|e| format!("could not write merged cross-crate info: {e}")),
819 );
820 }
821 };
822
823 let output_format = options.output_format;
824
825 match (
826 options.should_test || output_format == config::OutputFormat::Doctest,
827 config::markdown_input(&input),
828 ) {
829 (true, Some(_)) => return wrap_return(dcx, doctest::test_markdown(&input, options)),
830 (true, None) => return doctest::run(dcx, input, options),
831 (false, Some(md_input)) => {
832 let md_input = md_input.to_owned();
833 let edition = options.edition;
834 let config = core::create_config(input, options, &render_options);
835
836 return wrap_return(
840 dcx,
841 interface::run_compiler(config, |_compiler| {
842 markdown::render_and_write(&md_input, render_options, edition)
843 }),
844 );
845 }
846 (false, None) => {}
847 }
848
849 let show_coverage = options.show_coverage;
852 let run_check = options.run_check;
853
854 info!("starting to run rustc");
856
857 let crate_version = options.crate_version.clone();
862
863 let scrape_examples_options = options.scrape_examples_options.clone();
864 let bin_crate = options.bin_crate;
865
866 let config = core::create_config(input, options, &render_options);
867
868 let registered_lints = config.register_lints.is_some();
869
870 interface::run_compiler(config, |compiler| {
871 let sess = &compiler.sess;
872
873 if sess.opts.describe_lints {
874 rustc_driver::describe_lints(sess, registered_lints);
875 return;
876 }
877
878 let krate = rustc_interface::passes::parse(sess);
879 rustc_interface::create_and_enter_global_ctxt(compiler, krate, |tcx| {
880 if sess.dcx().has_errors().is_some() {
881 sess.dcx().fatal("Compilation failed, aborting rustdoc");
882 }
883
884 let (krate, render_opts, mut cache) = sess.time("run_global_ctxt", || {
885 core::run_global_ctxt(tcx, show_coverage, render_options, output_format)
886 });
887 info!("finished with rustc");
888
889 if let Some(options) = scrape_examples_options {
890 return scrape_examples::run(krate, render_opts, cache, tcx, options, bin_crate);
891 }
892
893 cache.crate_version = crate_version;
894
895 if show_coverage {
896 return;
899 }
900
901 if render_opts.dep_info().is_some() {
902 rustc_interface::passes::write_dep_info(tcx);
903 }
904
905 if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir {
906 dump_feature_usage_metrics(tcx, metrics_dir);
907 }
908
909 if run_check {
910 return;
912 }
913
914 info!("going to format");
915 match output_format {
916 config::OutputFormat::Html => sess.time("render_html", || {
917 run_renderer::<html::render::Context<'_>>(krate, render_opts, cache, tcx)
918 }),
919 config::OutputFormat::Json => sess.time("render_json", || {
920 run_renderer::<json::JsonRenderer<'_>>(krate, render_opts, cache, tcx)
921 }),
922 config::OutputFormat::Doctest => unreachable!(),
924 }
925 })
926 })
927}
928
929fn dump_feature_usage_metrics(tcxt: TyCtxt<'_>, metrics_dir: &Path) {
930 let hash = tcxt.crate_hash(LOCAL_CRATE);
931 let crate_name = tcxt.crate_name(LOCAL_CRATE);
932 let metrics_file_name = format!("unstable_feature_usage_metrics-{crate_name}-{hash}.json");
933 let metrics_path = metrics_dir.join(metrics_file_name);
934 if let Err(error) = tcxt.features().dump_feature_usage_metrics(metrics_path) {
935 tcxt.dcx().err(format!("cannot emit feature usage metrics: {error}"));
939 }
940}