about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustdoc/core.rs384
-rw-r--r--src/librustdoc/lib.rs10
-rw-r--r--src/librustdoc/passes/collect_trait_impls.rs8
3 files changed, 216 insertions, 186 deletions
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index a2f6d33a27a..7a0cf3717c9 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;
 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};
@@ -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<Session>) {
     // Parse, resolve, and typecheck the given crate.
 
     let RustdocOptions {
@@ -299,8 +301,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,
@@ -407,7 +409,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);
-                EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
+                tcx.sess.time("emit_ignored_resolution_errors", || {
+                    EmitIgnoredResolutionErrors::new(tcx).visit_body(body);
+                });
                 (rustc_interface::DEFAULT_QUERY_PROVIDERS.typeck)(tcx, def_id)
             };
         }),
@@ -429,18 +433,20 @@ 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| {
-                    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)
-                            });
-                    }
+                    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)
+                                });
+                        }
+                    });
                 });
 
                 // Now we're good to clone the resolver because everything should be loaded
@@ -453,181 +459,201 @@ 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| {
-                // 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.
+            let (krate, render_info, opts) = sess.time("run_global_ctxt", || {
+                global_ctxt.enter(|tcx| {
+                    run_global_ctxt(
+                        tcx,
+                        resolver,
+                        default_passes,
+                        manual_passes,
+                        render_options,
+                        output_format,
+                    )
+                })
+            });
+            (krate, render_info, opts, Lrc::clone(sess))
+        })
+    })
+}
 
-                // 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`)
+fn run_global_ctxt(
+    tcx: TyCtxt<'_>,
+    resolver: Rc<RefCell<interface::BoxedResolver>>,
+    mut default_passes: passes::DefaultPassOption,
+    mut manual_passes: Vec<String>,
+    render_options: RenderOptions,
+    output_format: Option<OutputFormat>,
+) -> (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();
+    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);
+        }
+    });
 
-                // HACK(jynelson) this calls an _extremely_ limited subset of `typeck`
-                // and might break if queries change their assumptions in the future.
+    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(),
+    };
 
-                // 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();
-                sess.time("missing_docs", || {
-                    rustc_lint::check_crate(tcx, rustc_lint::builtin::MissingDoc::new);
-                });
-                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 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| {
+                    let mut diag =
+                        lint.build("no documentation found for this crate's top-level module");
+                    diag.help(help);
+                    diag.emit();
+                },
+            );
+        }
+    }
 
-                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 = 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| {
-                                let mut diag = lint.build(
-                                    "no documentation found for this crate's top-level module",
-                                );
-                                diag.help(help);
-                                diag.emit();
-                            },
-                        );
-                    }
-                }
+    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 <https://github.com/rust-lang/rust/issues/44136> \
+                for more information",
+        );
 
-                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 <https://github.com/rust-lang/rust/issues/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 = (p.pass.run)(krate, &ctxt);
-                    }
-                }
+    info!("Executing passes");
 
-                ctxt.sess().abort_if_errors();
+    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));
+        }
+    }
 
-                (krate, ctxt.renderinfo.into_inner(), ctxt.render_options)
-            })
-        })
-    })
+    ctxt.sess().abort_if_errors();
+
+    (krate, ctxt.renderinfo.into_inner(), ctxt.render_options)
 }
 
 /// Due to https://github.com/rust-lang/rust/pull/73566,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index b017fee7e27..6d79924a06b 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::<html::render::Context>(krate, renderopts, renderinfo, &diag, edition)
-        }
-        Some(config::OutputFormat::Json) => {
+        }),
+        Some(config::OutputFormat::Json) => sess.time("render_json", || {
             run_renderer::<json::JsonRenderer>(krate, renderopts, renderinfo, &diag, edition)
-        }
+        }),
     }
 }
diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs
index 24baff46dcf..b2c4c30d8ff 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);
+            });
         }
     }