From 50a79693e171dbf20a979334b1d38dc1a61d1138 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Thu, 16 Jul 2020 09:02:41 -0400 Subject: [PATCH 1/9] Add some timing info to rustdoc There are various improvements, but the main one is to time each pass that rustdoc performs (`rustdoc::passes`). Before, these were the top five timings for `cargo doc` on the cargo repository: ``` +---------------------------------+-----------+-----------------+----------+------------+ | Item | Self time | % of total time | Time | Item count | +---------------------------------+-----------+-----------------+----------+------------+ | | 854.70ms | 20.888 | 2.47s | 744823 | +---------------------------------+-----------+-----------------+----------+------------+ | expand_crate | 795.29ms | 19.436 | 848.00ms | 1 | +---------------------------------+-----------+-----------------+----------+------------+ | metadata_decode_entry | 256.73ms | 6.274 | 279.49ms | 518344 | +---------------------------------+-----------+-----------------+----------+------------+ | resolve_crate | 240.56ms | 5.879 | 242.86ms | 1 | +---------------------------------+-----------+-----------------+----------+------------+ | hir_lowering | 146.79ms | 3.587 | 146.79ms | 1 | +---------------------------------+-----------+-----------------+----------+------------+ ``` Now the timings are: ``` +---------------------------------+-----------+-----------------+----------+------------+ | Item | Self time | % of total time | Time | Item count | +---------------------------------+-----------+-----------------+----------+------------+ | | 1.40s | 22.662 | 3.73s | 771430 | +---------------------------------+-----------+-----------------+----------+------------+ | collect-trait-impls | 1.34s | 21.672 | 2.87s | 1 | +---------------------------------+-----------+-----------------+----------+------------+ | expand_crate | 1.21s | 19.577 | 1.28s | 1 | +---------------------------------+-----------+-----------------+----------+------------+ | build extern trait impl | 704.66ms | 11.427 | 1.07s | 21893 | +---------------------------------+-----------+-----------------+----------+------------+ | metadata_decode_entry | 354.84ms | 5.754 | 391.81ms | 544919 | +---------------------------------+-----------+-----------------+----------+------------+ ``` --- src/librustdoc/core.rs | 12 +++++++++--- src/librustdoc/passes/collect_trait_impls.rs | 8 ++++++-- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index a2f6d33a27a0e..cb50200ae675a 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -407,7 +407,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let hir = tcx.hir(); let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(def_id))); debug!("visiting body for {:?}", def_id); + tcx.sess.time("emit ignored resolution errors", || { EmitIgnoredResolutionErrors::new(tcx).visit_body(body); + }); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; }), @@ -430,6 +432,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // intra-doc-links resolver.borrow_mut().access(|resolver| { for extern_name in &extern_names { + sess.time("load extern crate", || { resolver .resolve_str_path_error( DUMMY_SP, @@ -440,6 +443,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt .unwrap_or_else(|()| { panic!("Unable to resolve external crate {}", extern_name) }); + }); } }); @@ -480,7 +484,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt tcx.ensure().check_mod_attrs(local_def_id); } - let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); + let access_levels = tcx + .sess + .time("privacy_access_levels", || tcx.privacy_access_levels(LOCAL_CRATE)); // Convert from a HirId set to a DefId set since we don't always have easy access // to the map from defid -> hirid let access_levels = AccessLevels { @@ -519,7 +525,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }; debug!("crate: {:?}", tcx.hir().krate()); - let mut krate = clean::krate(&mut ctxt); + let mut krate = tcx.sess.time("clean crate", || clean::krate(&mut ctxt)); if let Some(ref m) = krate.module { if let None | Some("") = m.doc_value() { @@ -618,7 +624,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt }; if run { debug!("running pass {}", p.pass.name); - krate = (p.pass.run)(krate, &ctxt); + krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &ctxt)); } } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 24baff46dcfa5..b6bb96ef455ef 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -29,7 +29,9 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { for &cnum in cx.tcx.crates().iter() { for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { - inline::build_impl(cx, did, None, &mut new_items); + cx.tcx.sess.time("build extern trait impl", || { + inline::build_impl(cx, did, None, &mut new_items); + }); } } @@ -87,7 +89,9 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() { for &impl_node in cx.tcx.hir().trait_impls(trait_did) { let impl_did = cx.tcx.hir().local_def_id(impl_node); - inline::build_impl(cx, impl_did.to_def_id(), None, &mut new_items); + cx.tcx.sess.time("build local trait impl", || { + inline::build_impl(cx, impl_did.to_def_id(), None, &mut new_items); + }); } } From a0ebf1d3506222478d85c23efa8fae84eb1e591a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 16 Aug 2020 17:29:53 -0400 Subject: [PATCH 2/9] Time loading all crates, not each individual crate --- src/librustdoc/core.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index cb50200ae675a..458a71fd13c1f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -431,8 +431,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt // actually be loaded, just in case they're only referred to inside // intra-doc-links resolver.borrow_mut().access(|resolver| { + sess.time("load extern crates", || { for extern_name in &extern_names { - sess.time("load extern crate", || { resolver .resolve_str_path_error( DUMMY_SP, @@ -443,9 +443,9 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt .unwrap_or_else(|()| { panic!("Unable to resolve external crate {}", extern_name) }); - }); } }); + }); // Now we're good to clone the resolver because everything should be loaded resolver.clone() From d2527989875a7ef84de96ea61721508f5d8f7111 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 16 Aug 2020 17:30:27 -0400 Subject: [PATCH 3/9] Remove redundant timing for query --- src/librustdoc/core.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 458a71fd13c1f..dbb54fb5062c9 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -484,9 +484,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt tcx.ensure().check_mod_attrs(local_def_id); } - let access_levels = tcx - .sess - .time("privacy_access_levels", || tcx.privacy_access_levels(LOCAL_CRATE)); + let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); // Convert from a HirId set to a DefId set since we don't always have easy access // to the map from defid -> hirid let access_levels = AccessLevels { From e730947ba6db5a44031138b871c37886eab53427 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 16 Aug 2020 17:40:47 -0400 Subject: [PATCH 4/9] Separate `run_global_ctxt` into a separate function --- src/librustdoc/core.rs | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index dbb54fb5062c9..e7856bbfd34b0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -32,7 +32,7 @@ use std::rc::Rc; use crate::clean; use crate::clean::{AttributesExt, MAX_DEF_ID}; -use crate::config::RenderInfo; +use crate::config::{RenderInfo, OutputFormat}; use crate::config::{Options as RustdocOptions, RenderOptions}; use crate::passes::{self, Condition::*, ConditionalPass}; @@ -299,8 +299,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt lint_opts, describe_lints, lint_cap, - mut default_passes, - mut manual_passes, + default_passes, + manual_passes, display_warnings, render_options, output_format, @@ -457,7 +457,14 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - global_ctxt.enter(|tcx| { + global_ctxt.enter(|tcx| run_global_ctxt(tcx, resolver, default_passes, manual_passes, render_options, output_format)) + }) + }) +} + +fn run_global_ctxt(tcx: TyCtxt<'_>, resolver: Rc>, + mut default_passes: passes::DefaultPassOption, mut manual_passes: Vec, + render_options: RenderOptions, output_format: Option) -> (clean::Crate, RenderInfo, RenderOptions) { // Certain queries assume that some checks were run elsewhere // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), // so type-check everything other than function bodies in this crate before running lints. @@ -476,13 +483,15 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt } }); tcx.sess.abort_if_errors(); - sess.time("missing_docs", || { + tcx.sess.time("missing_docs", || { rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); }); + tcx.sess.time("check_mod_attrs", || { for &module in tcx.hir().krate().modules.keys() { let local_def_id = tcx.hir().local_def_id(module); tcx.ensure().check_mod_attrs(local_def_id); } + }); let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); // Convert from a HirId set to a DefId set since we don't always have easy access @@ -629,9 +638,6 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt ctxt.sess().abort_if_errors(); (krate, ctxt.renderinfo.into_inner(), ctxt.render_options) - }) - }) - }) } /// Due to https://github.com/rust-lang/rust/pull/73566, From 6782dc0fcecccc2747d39ff7496b35d11dcc556c Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 16 Aug 2020 17:41:25 -0400 Subject: [PATCH 5/9] Time running the global context --- src/librustdoc/core.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index e7856bbfd34b0..9cc6c61d049e0 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -457,7 +457,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - global_ctxt.enter(|tcx| run_global_ctxt(tcx, resolver, default_passes, manual_passes, render_options, output_format)) + sess.time("run_global_ctxt", || global_ctxt.enter(|tcx| run_global_ctxt(tcx, resolver, default_passes, manual_passes, render_options, output_format))) }) }) } From d21378488740097dd6c6759b3803c21cae733ee6 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 16 Aug 2020 17:56:02 -0400 Subject: [PATCH 6/9] xpy fmt --- src/librustdoc/core.rs | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 9cc6c61d049e0..81241e00f9119 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -32,8 +32,8 @@ use std::rc::Rc; use crate::clean; use crate::clean::{AttributesExt, MAX_DEF_ID}; -use crate::config::{RenderInfo, OutputFormat}; use crate::config::{Options as RustdocOptions, RenderOptions}; +use crate::config::{OutputFormat, RenderInfo}; use crate::passes::{self, Condition::*, ConditionalPass}; pub use rustc_session::config::{CodegenOptions, DebuggingOptions, Input, Options}; @@ -457,14 +457,30 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - sess.time("run_global_ctxt", || global_ctxt.enter(|tcx| run_global_ctxt(tcx, resolver, default_passes, manual_passes, render_options, output_format))) + sess.time("run_global_ctxt", || { + global_ctxt.enter(|tcx| { + run_global_ctxt( + tcx, + resolver, + default_passes, + manual_passes, + render_options, + output_format, + ) + }) + }) }) }) } -fn run_global_ctxt(tcx: TyCtxt<'_>, resolver: Rc>, - mut default_passes: passes::DefaultPassOption, mut manual_passes: Vec, - render_options: RenderOptions, output_format: Option) -> (clean::Crate, RenderInfo, RenderOptions) { +fn run_global_ctxt( + tcx: TyCtxt<'_>, + resolver: Rc>, + mut default_passes: passes::DefaultPassOption, + mut manual_passes: Vec, + render_options: RenderOptions, + output_format: Option, +) -> (clean::Crate, RenderInfo, RenderOptions) { // Certain queries assume that some checks were run elsewhere // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), // so type-check everything other than function bodies in this crate before running lints. @@ -543,9 +559,8 @@ fn run_global_ctxt(tcx: TyCtxt<'_>, resolver: Rc, resolver: Rc \ for more information", From 2934fd0a48026dc8e4bdf496158f1ac337cdb5b6 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 16 Aug 2020 18:41:13 -0400 Subject: [PATCH 7/9] Time how long it takes to render HTML --- src/librustdoc/core.rs | 9 ++++++--- src/librustdoc/lib.rs | 10 +++++----- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 81241e00f9119..79b7097049e01 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -280,7 +280,9 @@ where (lint_opts, lint_caps) } -pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOptions) { +pub fn run_core( + options: RustdocOptions, +) -> (clean::Crate, RenderInfo, RenderOptions, Lrc) { // Parse, resolve, and typecheck the given crate. let RustdocOptions { @@ -457,7 +459,7 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - sess.time("run_global_ctxt", || { + let (krate, render_info, opts) = sess.time("run_global_ctxt", || { global_ctxt.enter(|tcx| { run_global_ctxt( tcx, @@ -468,7 +470,8 @@ pub fn run_core(options: RustdocOptions) -> (clean::Crate, RenderInfo, RenderOpt output_format, ) }) - }) + }); + (krate, render_info, opts, Lrc::clone(sess)) }) }) } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b017fee7e2726..35e4245c02104 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -501,7 +501,7 @@ fn main_options(options: config::Options) -> MainResult { let crate_name = options.crate_name.clone(); let crate_version = options.crate_version.clone(); let output_format = options.output_format; - let (mut krate, renderinfo, renderopts) = core::run_core(options); + let (mut krate, renderinfo, renderopts, sess) = core::run_core(options); info!("finished with rustc"); @@ -524,11 +524,11 @@ fn main_options(options: config::Options) -> MainResult { let (error_format, edition, debugging_options) = diag_opts; let diag = core::new_handler(error_format, None, &debugging_options); match output_format { - None | Some(config::OutputFormat::Html) => { + None | Some(config::OutputFormat::Html) => sess.time("render html", || { run_renderer::(krate, renderopts, renderinfo, &diag, edition) - } - Some(config::OutputFormat::Json) => { + }), + Some(config::OutputFormat::Json) => sess.time("render json", || { run_renderer::(krate, renderopts, renderinfo, &diag, edition) - } + }), } } From a549c3ae70c88c04621a57cf1a5feb0982224176 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Tue, 18 Aug 2020 16:49:37 -0400 Subject: [PATCH 8/9] Use underscores instead of spaces --- src/librustdoc/core.rs | 6 +++--- src/librustdoc/lib.rs | 4 ++-- src/librustdoc/passes/collect_trait_impls.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 79b7097049e01..695ebbc0b903f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -409,7 +409,7 @@ pub fn run_core( let hir = tcx.hir(); let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(def_id))); debug!("visiting body for {:?}", def_id); - tcx.sess.time("emit ignored resolution errors", || { + tcx.sess.time("emit_ignored_resolution_errors", || { EmitIgnoredResolutionErrors::new(tcx).visit_body(body); }); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) @@ -433,7 +433,7 @@ pub fn run_core( // actually be loaded, just in case they're only referred to inside // intra-doc-links resolver.borrow_mut().access(|resolver| { - sess.time("load extern crates", || { + sess.time("load_extern_crates", || { for extern_name in &extern_names { resolver .resolve_str_path_error( @@ -551,7 +551,7 @@ fn run_global_ctxt( }; debug!("crate: {:?}", tcx.hir().krate()); - let mut krate = tcx.sess.time("clean crate", || clean::krate(&mut ctxt)); + let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt)); if let Some(ref m) = krate.module { if let None | Some("") = m.doc_value() { diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 35e4245c02104..6d79924a06b5b 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -524,10 +524,10 @@ fn main_options(options: config::Options) -> MainResult { let (error_format, edition, debugging_options) = diag_opts; let diag = core::new_handler(error_format, None, &debugging_options); match output_format { - None | Some(config::OutputFormat::Html) => sess.time("render html", || { + None | Some(config::OutputFormat::Html) => sess.time("render_html", || { run_renderer::(krate, renderopts, renderinfo, &diag, edition) }), - Some(config::OutputFormat::Json) => sess.time("render json", || { + Some(config::OutputFormat::Json) => sess.time("render_json", || { run_renderer::(krate, renderopts, renderinfo, &diag, edition) }), } diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index b6bb96ef455ef..b2c4c30d8ff08 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -29,7 +29,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { for &cnum in cx.tcx.crates().iter() { for &(did, _) in cx.tcx.all_trait_implementations(cnum).iter() { - cx.tcx.sess.time("build extern trait impl", || { + cx.tcx.sess.time("build_extern_trait_impl", || { inline::build_impl(cx, did, None, &mut new_items); }); } @@ -89,7 +89,7 @@ pub fn collect_trait_impls(krate: Crate, cx: &DocContext<'_>) -> Crate { for &trait_did in cx.tcx.all_traits(LOCAL_CRATE).iter() { for &impl_node in cx.tcx.hir().trait_impls(trait_did) { let impl_did = cx.tcx.hir().local_def_id(impl_node); - cx.tcx.sess.time("build local trait impl", || { + cx.tcx.sess.time("build_local_trait_impl", || { inline::build_impl(cx, impl_did.to_def_id(), None, &mut new_items); }); } From 6e3e74dd719334e84edd70ba0a842f5d4f94d266 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Sun, 23 Aug 2020 22:57:47 -0400 Subject: [PATCH 9/9] Fix bad rebase Had to use -Xignore-whitespace-conflicts to avoid awful conflicts, but that threw off the indentation --- src/librustdoc/core.rs | 328 ++++++++++++++++++++--------------------- 1 file changed, 164 insertions(+), 164 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 695ebbc0b903f..7a0cf3717c93f 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -410,7 +410,7 @@ pub fn run_core( let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(def_id))); debug!("visiting body for {:?}", def_id); tcx.sess.time("emit_ignored_resolution_errors", || { - EmitIgnoredResolutionErrors::new(tcx).visit_body(body); + EmitIgnoredResolutionErrors::new(tcx).visit_body(body); }); (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id) }; @@ -434,19 +434,19 @@ pub fn run_core( // intra-doc-links resolver.borrow_mut().access(|resolver| { sess.time("load_extern_crates", || { - for extern_name in &extern_names { - resolver - .resolve_str_path_error( - DUMMY_SP, - extern_name, - TypeNS, - LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), - ) - .unwrap_or_else(|()| { - panic!("Unable to resolve external crate {}", extern_name) - }); - } - }); + for extern_name in &extern_names { + resolver + .resolve_str_path_error( + DUMMY_SP, + extern_name, + TypeNS, + LocalDefId { local_def_index: CRATE_DEF_INDEX }.to_def_id(), + ) + .unwrap_or_else(|()| { + panic!("Unable to resolve external crate {}", extern_name) + }); + } + }); }); // Now we're good to clone the resolver because everything should be loaded @@ -484,176 +484,176 @@ fn run_global_ctxt( render_options: RenderOptions, output_format: Option, ) -> (clean::Crate, RenderInfo, RenderOptions) { - // Certain queries assume that some checks were run elsewhere - // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), - // so type-check everything other than function bodies in this crate before running lints. - - // NOTE: this does not call `tcx.analysis()` so that we won't - // typeck function bodies or run the default rustc lints. - // (see `override_queries` in the `config`) - - // HACK(jynelson) this calls an _extremely_ limited subset of `typeck` - // and might break if queries change their assumptions in the future. - - // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes. - tcx.sess.time("item_types_checking", || { - for &module in tcx.hir().krate().modules.keys() { - tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); - } - }); - tcx.sess.abort_if_errors(); + // Certain queries assume that some checks were run elsewhere + // (see https://github.com/rust-lang/rust/pull/73566#issuecomment-656954425), + // so type-check everything other than function bodies in this crate before running lints. + + // NOTE: this does not call `tcx.analysis()` so that we won't + // typeck function bodies or run the default rustc lints. + // (see `override_queries` in the `config`) + + // HACK(jynelson) this calls an _extremely_ limited subset of `typeck` + // and might break if queries change their assumptions in the future. + + // NOTE: This is copy/pasted from typeck/lib.rs and should be kept in sync with those changes. + tcx.sess.time("item_types_checking", || { + for &module in tcx.hir().krate().modules.keys() { + tcx.ensure().check_mod_item_types(tcx.hir().local_def_id(module)); + } + }); + tcx.sess.abort_if_errors(); tcx.sess.time("missing_docs", || { - rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); - }); + rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new); + }); tcx.sess.time("check_mod_attrs", || { - for &module in tcx.hir().krate().modules.keys() { - let local_def_id = tcx.hir().local_def_id(module); - tcx.ensure().check_mod_attrs(local_def_id); - } + for &module in tcx.hir().krate().modules.keys() { + let local_def_id = tcx.hir().local_def_id(module); + tcx.ensure().check_mod_attrs(local_def_id); + } }); - let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); - // Convert from a HirId set to a DefId set since we don't always have easy access - // to the map from defid -> hirid - let access_levels = AccessLevels { - map: access_levels - .map - .iter() - .map(|(&k, &v)| (tcx.hir().local_def_id(k).to_def_id(), v)) - .collect(), - }; - - let mut renderinfo = RenderInfo::default(); - renderinfo.access_levels = access_levels; - renderinfo.output_format = output_format; - - let mut ctxt = DocContext { - tcx, - resolver, - external_traits: Default::default(), - active_extern_traits: Default::default(), - renderinfo: RefCell::new(renderinfo), - ty_substs: Default::default(), - lt_substs: Default::default(), - ct_substs: Default::default(), - impl_trait_bounds: Default::default(), - fake_def_ids: Default::default(), - all_fake_def_ids: Default::default(), - generated_synthetics: Default::default(), - auto_traits: tcx - .all_traits(LOCAL_CRATE) - .iter() - .cloned() - .filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id)) - .collect(), - render_options, - module_trait_cache: RefCell::new(FxHashMap::default()), - }; - debug!("crate: {:?}", tcx.hir().krate()); + let access_levels = tcx.privacy_access_levels(LOCAL_CRATE); + // Convert from a HirId set to a DefId set since we don't always have easy access + // to the map from defid -> hirid + let access_levels = AccessLevels { + map: access_levels + .map + .iter() + .map(|(&k, &v)| (tcx.hir().local_def_id(k).to_def_id(), v)) + .collect(), + }; + + let mut renderinfo = RenderInfo::default(); + renderinfo.access_levels = access_levels; + renderinfo.output_format = output_format; + + let mut ctxt = DocContext { + tcx, + resolver, + external_traits: Default::default(), + active_extern_traits: Default::default(), + renderinfo: RefCell::new(renderinfo), + ty_substs: Default::default(), + lt_substs: Default::default(), + ct_substs: Default::default(), + impl_trait_bounds: Default::default(), + fake_def_ids: Default::default(), + all_fake_def_ids: Default::default(), + generated_synthetics: Default::default(), + auto_traits: tcx + .all_traits(LOCAL_CRATE) + .iter() + .cloned() + .filter(|trait_def_id| tcx.trait_is_auto(*trait_def_id)) + .collect(), + render_options, + module_trait_cache: RefCell::new(FxHashMap::default()), + }; + debug!("crate: {:?}", tcx.hir().krate()); let mut krate = tcx.sess.time("clean_crate", || clean::krate(&mut ctxt)); - if let Some(ref m) = krate.module { - if let None | Some("") = m.doc_value() { - let help = "The following guide may be of use:\n\ - https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ - .html"; - tcx.struct_lint_node( - rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS, - ctxt.as_local_hir_id(m.def_id).unwrap(), - |lint| { + if let Some(ref m) = krate.module { + if let None | Some("") = m.doc_value() { + let help = "The following guide may be of use:\n\ + https://doc.rust-lang.org/nightly/rustdoc/how-to-write-documentation\ + .html"; + tcx.struct_lint_node( + rustc_lint::builtin::MISSING_CRATE_LEVEL_DOCS, + ctxt.as_local_hir_id(m.def_id).unwrap(), + |lint| { let mut diag = lint.build("no documentation found for this crate's top-level module"); - diag.help(help); - diag.emit(); - }, - ); - } - } + diag.help(help); + diag.emit(); + }, + ); + } + } - fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) { + fn report_deprecated_attr(name: &str, diag: &rustc_errors::Handler) { let mut msg = diag .struct_warn(&format!("the `#![doc({})]` attribute is considered deprecated", name)); - msg.warn( - "see issue #44136 \ - for more information", - ); + msg.warn( + "see issue #44136 \ + for more information", + ); + + if name == "no_default_passes" { + msg.help("you may want to use `#![doc(document_private_items)]`"); + } - if name == "no_default_passes" { - msg.help("you may want to use `#![doc(document_private_items)]`"); - } + msg.emit(); + } - msg.emit(); + // Process all of the crate attributes, extracting plugin metadata along + // with the passes which we are supposed to run. + for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { + let diag = ctxt.sess().diagnostic(); + + let name = attr.name_or_empty(); + if attr.is_word() { + if name == sym::no_default_passes { + report_deprecated_attr("no_default_passes", diag); + if default_passes == passes::DefaultPassOption::Default { + default_passes = passes::DefaultPassOption::None; + } + } + } else if let Some(value) = attr.value_str() { + let sink = match name { + sym::passes => { + report_deprecated_attr("passes = \"...\"", diag); + &mut manual_passes + } + sym::plugins => { + report_deprecated_attr("plugins = \"...\"", diag); + eprintln!( + "WARNING: `#![doc(plugins = \"...\")]` \ + no longer functions; see CVE-2018-1000622" + ); + continue; } + _ => continue, + }; + for name in value.as_str().split_whitespace() { + sink.push(name.to_string()); + } + } - // Process all of the crate attributes, extracting plugin metadata along - // with the passes which we are supposed to run. - for attr in krate.module.as_ref().unwrap().attrs.lists(sym::doc) { - let diag = ctxt.sess().diagnostic(); - - let name = attr.name_or_empty(); - if attr.is_word() { - if name == sym::no_default_passes { - report_deprecated_attr("no_default_passes", diag); - if default_passes == passes::DefaultPassOption::Default { - default_passes = passes::DefaultPassOption::None; - } - } - } else if let Some(value) = attr.value_str() { - let sink = match name { - sym::passes => { - report_deprecated_attr("passes = \"...\"", diag); - &mut manual_passes - } - sym::plugins => { - report_deprecated_attr("plugins = \"...\"", diag); - eprintln!( - "WARNING: `#![doc(plugins = \"...\")]` \ - no longer functions; see CVE-2018-1000622" - ); - continue; - } - _ => continue, - }; - for name in value.as_str().split_whitespace() { - sink.push(name.to_string()); - } - } + if attr.is_word() && name == sym::document_private_items { + ctxt.render_options.document_private = true; + } + } - if attr.is_word() && name == sym::document_private_items { - ctxt.render_options.document_private = true; - } - } + let passes = passes::defaults(default_passes).iter().copied().chain( + manual_passes.into_iter().flat_map(|name| { + if let Some(pass) = passes::find_pass(&name) { + Some(ConditionalPass::always(pass)) + } else { + error!("unknown pass {}, skipping", name); + None + } + }), + ); - let passes = passes::defaults(default_passes).iter().copied().chain( - manual_passes.into_iter().flat_map(|name| { - if let Some(pass) = passes::find_pass(&name) { - Some(ConditionalPass::always(pass)) - } else { - error!("unknown pass {}, skipping", name); - None - } - }), - ); - - info!("Executing passes"); - - for p in passes { - let run = match p.condition { - Always => true, - WhenDocumentPrivate => ctxt.render_options.document_private, - WhenNotDocumentPrivate => !ctxt.render_options.document_private, - WhenNotDocumentHidden => !ctxt.render_options.document_hidden, - }; - if run { - debug!("running pass {}", p.pass.name); - krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &ctxt)); - } - } + info!("Executing passes"); + + for p in passes { + let run = match p.condition { + Always => true, + WhenDocumentPrivate => ctxt.render_options.document_private, + WhenNotDocumentPrivate => !ctxt.render_options.document_private, + WhenNotDocumentHidden => !ctxt.render_options.document_hidden, + }; + if run { + debug!("running pass {}", p.pass.name); + krate = ctxt.tcx.sess.time(p.pass.name, || (p.pass.run)(krate, &ctxt)); + } + } - ctxt.sess().abort_if_errors(); + ctxt.sess().abort_if_errors(); - (krate, ctxt.renderinfo.into_inner(), ctxt.render_options) + (krate, ctxt.renderinfo.into_inner(), ctxt.render_options) } /// Due to https://github.com/rust-lang/rust/pull/73566,