From 0ac58f7bf86cd8a3616484b3ff1a794521368536 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 11 Dec 2020 21:37:14 -0500 Subject: [PATCH 1/8] Split apart create_config and run_core --- src/librustdoc/core.rs | 46 +++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index b2eeaf584bf20..ed3bc02a5de65 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -273,12 +273,9 @@ where (lint_opts, lint_caps) } -crate fn run_core( - options: RustdocOptions, -) -> (clean::Crate, RenderInfo, RenderOptions, Lrc) { - // Parse, resolve, and typecheck the given crate. - - let RustdocOptions { +/// Parse, resolve, and typecheck the given crate. +fn create_config( + RustdocOptions { input, crate_name, proc_macro_crate, @@ -294,21 +291,10 @@ crate fn run_core( lint_opts, describe_lints, lint_cap, - default_passes, - manual_passes, display_warnings, - render_options, - output_format, .. - } = options; - - let extern_names: Vec = externs - .iter() - .filter(|(_, entry)| entry.add_prelude) - .map(|(name, _)| name) - .cloned() - .collect(); - + }: RustdocOptions, +) -> rustc_interface::Config { // Add the doc cfg into the doc build. cfgs.push("doc".to_string()); @@ -374,7 +360,7 @@ crate fn run_core( ..Options::default() }; - let config = interface::Config { + interface::Config { opts: sessopts, crate_cfg: interface::parse_cfgspecs(cfgs), input, @@ -417,7 +403,25 @@ crate fn run_core( }), make_codegen_backend: None, registry: rustc_driver::diagnostics_registry(), - }; + } +} + +crate fn run_core( + options: RustdocOptions, +) -> (clean::Crate, RenderInfo, RenderOptions, Lrc) { + let extern_names: Vec = options + .externs + .iter() + .filter(|(_, entry)| entry.add_prelude) + .map(|(name, _)| name) + .cloned() + .collect(); + let default_passes = options.default_passes; + let output_format = options.output_format; + // TODO: fix this clone (especially render_options) + let manual_passes = options.manual_passes.clone(); + let render_options = options.render_options.clone(); + let config = create_config(options); interface::create_compiler_and_run(config, |compiler| { compiler.enter(|queries| { From 34e8b0aae1fe66e0e0c0f70957cc647361a79ff5 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 11 Dec 2020 21:46:58 -0500 Subject: [PATCH 2/8] Separate `create_resolver` into a new function --- src/librustdoc/core.rs | 79 +++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index ed3bc02a5de65..cd05d922f5fe6 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -11,7 +11,7 @@ use rustc_hir::{ intravisit::{self, NestedVisitorMap, Visitor}, Path, }; -use rustc_interface::interface; +use rustc_interface::{interface, Queries}; use rustc_middle::hir::map::Map; use rustc_middle::middle::privacy::AccessLevels; use rustc_middle::ty::{ParamEnv, Ty, TyCtxt}; @@ -409,16 +409,10 @@ fn create_config( crate fn run_core( options: RustdocOptions, ) -> (clean::Crate, RenderInfo, RenderOptions, Lrc) { - let extern_names: Vec = options - .externs - .iter() - .filter(|(_, entry)| entry.add_prelude) - .map(|(name, _)| name) - .cloned() - .collect(); let default_passes = options.default_passes; let output_format = options.output_format; // TODO: fix this clone (especially render_options) + let externs = options.externs.clone(); let manual_passes = options.manual_passes.clone(); let render_options = options.render_options.clone(); let config = create_config(options); @@ -430,34 +424,7 @@ crate fn run_core( // We need to hold on to the complete resolver, so we cause everything to be // cloned for the analysis passes to use. Suboptimal, but necessary in the // current architecture. - let resolver = { - let parts = abort_on_err(queries.expansion(), sess).peek(); - let resolver = parts.1.borrow(); - - // Before we actually clone it, let's force all the extern'd crates to - // 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 { - debug!("loading extern crate {}", extern_name); - 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 - resolver.clone() - }; + let resolver = create_resolver(externs, queries, &sess); if sess.has_errors() { sess.fatal("Compilation failed, aborting rustdoc"); @@ -482,6 +449,46 @@ crate fn run_core( }) } +fn create_resolver<'a>( + externs: config::Externs, + queries: &Queries<'a>, + sess: &Session, +) -> Lrc> { + let extern_names: Vec = externs + .iter() + .filter(|(_, entry)| entry.add_prelude) + .map(|(name, _)| name) + .cloned() + .collect(); + + let parts = abort_on_err(queries.expansion(), sess).peek(); + let resolver = parts.1.borrow(); + + // Before we actually clone it, let's force all the extern'd crates to + // 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 { + debug!("loading extern crate {}", extern_name); + 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 + resolver.clone() +} + fn run_global_ctxt( tcx: TyCtxt<'_>, resolver: Rc>, From 79ab333cf0e8b49676cabc7d8bdaa785a688a67a Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Fri, 11 Dec 2020 21:57:48 -0500 Subject: [PATCH 3/8] Move `run_renderer` into the main `global_ctxt` closure --- src/librustdoc/core.rs | 49 ++------------------ src/librustdoc/lib.rs | 103 +++++++++++++++++++++++++++++++---------- 2 files changed, 81 insertions(+), 71 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index cd05d922f5fe6..3b789dfd66f4c 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -274,7 +274,7 @@ where } /// Parse, resolve, and typecheck the given crate. -fn create_config( +crate fn create_config( RustdocOptions { input, crate_name, @@ -406,50 +406,7 @@ fn create_config( } } -crate fn run_core( - options: RustdocOptions, -) -> (clean::Crate, RenderInfo, RenderOptions, Lrc) { - let default_passes = options.default_passes; - let output_format = options.output_format; - // TODO: fix this clone (especially render_options) - let externs = options.externs.clone(); - let manual_passes = options.manual_passes.clone(); - let render_options = options.render_options.clone(); - let config = create_config(options); - - interface::create_compiler_and_run(config, |compiler| { - compiler.enter(|queries| { - let sess = compiler.session(); - - // We need to hold on to the complete resolver, so we cause everything to be - // cloned for the analysis passes to use. Suboptimal, but necessary in the - // current architecture. - let resolver = create_resolver(externs, queries, &sess); - - if sess.has_errors() { - sess.fatal("Compilation failed, aborting rustdoc"); - } - - let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); - - 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)) - }) - }) -} - -fn create_resolver<'a>( +crate fn create_resolver<'a>( externs: config::Externs, queries: &Queries<'a>, sess: &Session, @@ -489,7 +446,7 @@ fn create_resolver<'a>( resolver.clone() } -fn run_global_ctxt( +crate fn run_global_ctxt( tcx: TyCtxt<'_>, resolver: Rc>, mut default_passes: passes::DefaultPassOption, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 24045b4e29dc9..93c849859aba5 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -63,7 +63,9 @@ use std::env; use std::process; use rustc_data_structures::sync::Lrc; +use rustc_driver::abort_on_err; use rustc_errors::ErrorReported; +use rustc_interface::interface; use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; use rustc_session::getopts; use rustc_session::Session; @@ -520,34 +522,85 @@ fn main_options(options: config::Options) -> MainResult { // then generated from the cleaned AST of the crate. This runs all the // plug/cleaning passes. let crate_version = options.crate_version.clone(); + + let default_passes = options.default_passes; let output_format = options.output_format; - let (mut krate, renderinfo, renderopts, sess) = core::run_core(options); + // TODO: fix this clone (especially render_options) + let externs = options.externs.clone(); + let manual_passes = options.manual_passes.clone(); + let render_options = options.render_options.clone(); + let config = core::create_config(options); - info!("finished with rustc"); + interface::create_compiler_and_run(config, |compiler| { + compiler.enter(|queries| { + let sess = compiler.session(); - krate.version = crate_version; + // We need to hold on to the complete resolver, so we cause everything to be + // cloned for the analysis passes to use. Suboptimal, but necessary in the + // current architecture. + let resolver = core::create_resolver(externs, queries, &sess); - if show_coverage { - // if we ran coverage, bail early, we don't need to also generate docs at this point - // (also we didn't load in any of the useful passes) - return Ok(()); - } else if run_check { - // Since we're in "check" mode, no need to generate anything beyond this point. - return Ok(()); - } + if sess.has_errors() { + sess.fatal("Compilation failed, aborting rustdoc"); + } - info!("going to format"); - let (error_format, edition, debugging_options) = diag_opts; - let diag = core::new_handler(error_format, None, &debugging_options); - let sess_time = sess.clone(); - match output_format { - None | Some(config::OutputFormat::Html) => sess_time.time("render_html", || { - run_renderer::( - krate, renderopts, renderinfo, &diag, edition, sess, - ) - }), - Some(config::OutputFormat::Json) => sess_time.time("render_json", || { - run_renderer::(krate, renderopts, renderinfo, &diag, edition, sess) - }), - } + let mut global_ctxt = abort_on_err(queries.global_ctxt(), sess).take(); + + global_ctxt.enter(|tcx| { + let (mut krate, render_info, render_opts) = sess.time("run_global_ctxt", || { + core::run_global_ctxt( + tcx, + resolver, + default_passes, + manual_passes, + render_options, + output_format, + ) + }); + info!("finished with rustc"); + + if let Some(name) = crate_name { + krate.name = name + } + + krate.version = crate_version; + + if show_coverage { + // if we ran coverage, bail early, we don't need to also generate docs at this point + // (also we didn't load in any of the useful passes) + return Ok(()); + } else if run_check { + // Since we're in "check" mode, no need to generate anything beyond this point. + return Ok(()); + } + + info!("going to format"); + let (error_format, edition, debugging_options) = diag_opts; + let diag = core::new_handler(error_format, None, &debugging_options); + let sess_format = sess.clone(); + match output_format { + None | Some(config::OutputFormat::Html) => sess.time("render_html", || { + run_renderer::( + krate, + render_opts, + render_info, + &diag, + edition, + sess_format, + ) + }), + Some(config::OutputFormat::Json) => sess.time("render_json", || { + run_renderer::( + krate, + render_opts, + render_info, + &diag, + edition, + sess_format, + ) + }), + } + }) + }) + }) } From 9221d4d1d347ee50f31d2bf50e13ecfdf14c4611 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 16 Dec 2020 14:23:14 -0500 Subject: [PATCH 4/8] [tmp] Pass `TyCtxt` through to the render backend First actually useful step in https://github.com/rust-lang/rust/issues/76382 This doesn't yet compile because there's no way to get a `Lrc` from a TyCtxt, only a `&Session`. --- src/librustdoc/formats/renderer.rs | 9 ++++----- src/librustdoc/html/render/mod.rs | 5 +++-- src/librustdoc/json/mod.rs | 5 +++-- src/librustdoc/lib.rs | 13 +++++-------- 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index f61919d78a092..7ec29a70bd0a3 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -1,7 +1,6 @@ use std::sync::Arc; -use rustc_data_structures::sync::Lrc; -use rustc_session::Session; +use rustc_middle::ty; use rustc_span::edition::Edition; use crate::clean; @@ -21,7 +20,7 @@ crate trait FormatRenderer: Clone { render_info: RenderInfo, edition: Edition, cache: &mut Cache, - sess: Lrc, + tcx: ty::TyCtxt<'_>, ) -> Result<(Self, clean::Crate), Error>; /// Renders a single non-module item. This means no recursive sub-item rendering is required. @@ -52,7 +51,7 @@ crate fn run_format( render_info: RenderInfo, diag: &rustc_errors::Handler, edition: Edition, - sess: Lrc, + tcx: ty::TyCtxt<'_>, ) -> Result<(), Error> { let (krate, mut cache) = Cache::from_krate( render_info.clone(), @@ -63,7 +62,7 @@ crate fn run_format( ); let (mut format_renderer, mut krate) = - T::init(krate, options, render_info, edition, &mut cache, sess)?; + T::init(krate, options, render_info, edition, &mut cache, tcx)?; let cache = Arc::new(cache); // Freeze the cache now that the index has been built. Put an Arc into TLS for future diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a775c85435cb8..d8d46adfb63df 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -57,6 +57,7 @@ use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Mutability; use rustc_middle::middle::stability; +use rustc_middle::ty; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; @@ -388,7 +389,7 @@ impl FormatRenderer for Context { _render_info: RenderInfo, edition: Edition, cache: &mut Cache, - sess: Lrc, + tcx: ty::TyCtxt<'_>, ) -> Result<(Context, clean::Crate), Error> { // need to save a copy of the options for rendering the index page let md_opts = options.clone(); @@ -462,7 +463,7 @@ impl FormatRenderer for Context { } let (sender, receiver) = channel(); let mut scx = SharedContext { - sess, + tcx, collapsed: krate.collapsed, src_root, include_sources, diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index 7af26558b76ec..3d970918407c2 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -14,6 +14,7 @@ use std::rc::Rc; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sync::Lrc; +use rustc_middle::ty; use rustc_session::Session; use rustc_span::edition::Edition; @@ -127,12 +128,12 @@ impl FormatRenderer for JsonRenderer { _render_info: RenderInfo, _edition: Edition, _cache: &mut Cache, - sess: Lrc, + tcx: ty::TyCtxt<'_>, ) -> Result<(Self, clean::Crate), Error> { debug!("Initializing json renderer"); Ok(( JsonRenderer { - sess, + sess: tcx.sess, index: Rc::new(RefCell::new(FxHashMap::default())), out_path: options.output, }, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 93c849859aba5..caa0706fd2b56 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -62,13 +62,11 @@ use std::default::Default; use std::env; use std::process; -use rustc_data_structures::sync::Lrc; use rustc_driver::abort_on_err; use rustc_errors::ErrorReported; -use rustc_interface::interface; +use rustc_middle::ty; use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup}; use rustc_session::getopts; -use rustc_session::Session; use rustc_session::{early_error, early_warn}; #[macro_use] @@ -476,9 +474,9 @@ fn run_renderer( render_info: config::RenderInfo, diag: &rustc_errors::Handler, edition: rustc_span::edition::Edition, - sess: Lrc, + tcx: ty::TyCtxt<'_>, ) -> MainResult { - match formats::run_format::(krate, renderopts, render_info, &diag, edition, sess) { + match formats::run_format::(krate, renderopts, render_info, &diag, edition, tcx) { Ok(_) => Ok(()), Err(e) => { let mut msg = diag.struct_err(&format!("couldn't generate documentation: {}", e.error)); @@ -577,7 +575,6 @@ fn main_options(options: config::Options) -> MainResult { info!("going to format"); let (error_format, edition, debugging_options) = diag_opts; let diag = core::new_handler(error_format, None, &debugging_options); - let sess_format = sess.clone(); match output_format { None | Some(config::OutputFormat::Html) => sess.time("render_html", || { run_renderer::( @@ -586,7 +583,7 @@ fn main_options(options: config::Options) -> MainResult { render_info, &diag, edition, - sess_format, + tcx, ) }), Some(config::OutputFormat::Json) => sess.time("render_json", || { @@ -596,7 +593,7 @@ fn main_options(options: config::Options) -> MainResult { render_info, &diag, edition, - sess_format, + tcx, ) }), } From 47c969436adf2cc5acfbddf1061fb30d0fdacd34 Mon Sep 17 00:00:00 2001 From: Joshua Nelson Date: Wed, 16 Dec 2020 14:34:08 -0500 Subject: [PATCH 5/8] Make it compile --- src/librustdoc/formats/renderer.rs | 8 +- src/librustdoc/html/render/mod.rs | 122 ++++++++++++++++++----------- src/librustdoc/html/sources.rs | 12 +-- src/librustdoc/json/conversions.rs | 8 +- src/librustdoc/json/mod.rs | 17 ++-- src/librustdoc/lib.rs | 9 ++- 6 files changed, 104 insertions(+), 72 deletions(-) diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs index 7ec29a70bd0a3..fbbd3c1ccf514 100644 --- a/src/librustdoc/formats/renderer.rs +++ b/src/librustdoc/formats/renderer.rs @@ -11,7 +11,7 @@ use crate::formats::cache::{Cache, CACHE_KEY}; /// Allows for different backends to rustdoc to be used with the `run_format()` function. Each /// backend renderer has hooks for initialization, documenting an item, entering and exiting a /// module, and cleanup/finalizing output. -crate trait FormatRenderer: Clone { +crate trait FormatRenderer<'tcx>: Clone { /// Sets up any state required for the renderer. When this is called the cache has already been /// populated. fn init( @@ -20,7 +20,7 @@ crate trait FormatRenderer: Clone { render_info: RenderInfo, edition: Edition, cache: &mut Cache, - tcx: ty::TyCtxt<'_>, + tcx: ty::TyCtxt<'tcx>, ) -> Result<(Self, clean::Crate), Error>; /// Renders a single non-module item. This means no recursive sub-item rendering is required. @@ -45,13 +45,13 @@ crate trait FormatRenderer: Clone { } /// Main method for rendering a crate. -crate fn run_format( +crate fn run_format<'tcx, T: FormatRenderer<'tcx>>( krate: clean::Crate, options: RenderOptions, render_info: RenderInfo, diag: &rustc_errors::Handler, edition: Edition, - tcx: ty::TyCtxt<'_>, + tcx: ty::TyCtxt<'tcx>, ) -> Result<(), Error> { let (krate, mut cache) = Cache::from_krate( render_info.clone(), diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index d8d46adfb63df..e6d3fdbe185dd 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -52,12 +52,12 @@ use rustc_ast_pretty::pprust; use rustc_attr::{Deprecation, StabilityLevel}; use rustc_data_structures::flock; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::sync::Lrc; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::Mutability; use rustc_middle::middle::stability; use rustc_middle::ty; +use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; @@ -103,7 +103,7 @@ crate fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ { /// easily cloned because it is cloned per work-job (about once per item in the /// rustdoc tree). #[derive(Clone)] -crate struct Context { +crate struct Context<'tcx> { /// Current hierarchy of components leading down to what's currently being /// rendered crate current: Vec, @@ -116,15 +116,15 @@ crate struct Context { crate render_redirect_pages: bool, /// The map used to ensure all generated 'id=' attributes are unique. id_map: Rc>, - crate shared: Arc, + crate shared: Arc>, all: Rc>, /// Storage for the errors produced while generating documentation so they /// can be printed together at the end. crate errors: Rc>, } -crate struct SharedContext { - crate sess: Lrc, +crate struct SharedContext<'tcx> { + crate tcx: TyCtxt<'tcx>, /// The path to the crate root source minus the file name. /// Used for simplifying paths to the highlighted source code files. crate src_root: PathBuf, @@ -164,7 +164,7 @@ crate struct SharedContext { playground: Option, } -impl Context { +impl Context<'_> { fn path(&self, filename: &str) -> PathBuf { // We use splitn vs Path::extension here because we might get a filename // like `style.min.css` and we want to process that into @@ -177,11 +177,11 @@ impl Context { } fn sess(&self) -> &Session { - &self.shared.sess + &self.shared.tcx.sess } } -impl SharedContext { +impl SharedContext<'_> { crate fn ensure_dir(&self, dst: &Path) -> Result<(), Error> { let mut dirs = self.created_dirs.borrow_mut(); if !dirs.contains(dst) { @@ -382,15 +382,15 @@ crate fn initial_ids() -> Vec { } /// Generates the documentation for `crate` into the directory `dst` -impl FormatRenderer for Context { +impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> { fn init( mut krate: clean::Crate, options: RenderOptions, _render_info: RenderInfo, edition: Edition, cache: &mut Cache, - tcx: ty::TyCtxt<'_>, - ) -> Result<(Context, clean::Crate), Error> { + tcx: ty::TyCtxt<'tcx>, + ) -> Result<(Self, clean::Crate), Error> { // need to save a copy of the options for rendering the index page let md_opts = options.clone(); let RenderOptions { @@ -689,7 +689,7 @@ impl FormatRenderer for Context { } fn write_shared( - cx: &Context, + cx: &Context<'_>, krate: &clean::Crate, search_index: String, options: &RenderOptions, @@ -1206,7 +1206,7 @@ fn write_minify( } } -fn write_srclink(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) { +fn write_srclink(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Cache) { if let Some(l) = cx.src_href(item, cache) { write!( buf, @@ -1517,7 +1517,7 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result { fn derive_id(&self, id: String) -> String { let mut map = self.id_map.borrow_mut(); map.derive(id) @@ -1702,7 +1702,7 @@ where write!(w, "") } -fn print_item(cx: &Context, item: &clean::Item, buf: &mut Buffer, cache: &Cache) { +fn print_item(cx: &Context<'_>, item: &clean::Item, buf: &mut Buffer, cache: &Cache) { debug_assert!(!item.is_stripped()); // Write the breadcrumb trail header for the top write!(buf, "

"); @@ -1817,14 +1817,14 @@ fn item_path(ty: ItemType, name: &str) -> String { } } -fn full_path(cx: &Context, item: &clean::Item) -> String { +fn full_path(cx: &Context<'_>, item: &clean::Item) -> String { let mut s = cx.current.join("::"); s.push_str("::"); s.push_str(&item.name.unwrap().as_str()); s } -fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&clean::Item>) { +fn document(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, parent: Option<&clean::Item>) { if let Some(ref name) = item.name { info!("Documenting {}", name); } @@ -1835,7 +1835,7 @@ fn document(w: &mut Buffer, cx: &Context, item: &clean::Item, parent: Option<&cl /// Render md_text as markdown. fn render_markdown( w: &mut Buffer, - cx: &Context, + cx: &Context<'_>, md_text: &str, links: Vec, prefix: &str, @@ -1864,7 +1864,7 @@ fn render_markdown( fn document_short( w: &mut Buffer, item: &clean::Item, - cx: &Context, + cx: &Context<'_>, link: AssocItemLink<'_>, prefix: &str, is_hidden: bool, @@ -1905,7 +1905,13 @@ fn document_short( } } -fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str, is_hidden: bool) { +fn document_full( + w: &mut Buffer, + item: &clean::Item, + cx: &Context<'_>, + prefix: &str, + is_hidden: bool, +) { if let Some(s) = cx.shared.maybe_collapsed_doc_value(item) { debug!("Doc block: =====\n{}\n=====", s); render_markdown(w, cx, &*s, item.links(), prefix, is_hidden); @@ -1926,7 +1932,7 @@ fn document_full(w: &mut Buffer, item: &clean::Item, cx: &Context, prefix: &str, /// * Required features (through the `doc_cfg` feature) fn document_item_info( w: &mut Buffer, - cx: &Context, + cx: &Context<'_>, item: &clean::Item, is_hidden: bool, parent: Option<&clean::Item>, @@ -2030,7 +2036,7 @@ crate fn compare_names(mut lhs: &str, mut rhs: &str) -> Ordering { Ordering::Equal } -fn item_module(w: &mut Buffer, cx: &Context, item: &clean::Item, items: &[clean::Item]) { +fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) { document(w, cx, item, None); let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::>(); @@ -2272,7 +2278,11 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option) -> Vec { +fn short_item_info( + item: &clean::Item, + cx: &Context<'_>, + parent: Option<&clean::Item>, +) -> Vec { let mut extra_info = vec![]; let error_codes = cx.shared.codes; @@ -2362,7 +2372,7 @@ fn short_item_info(item: &clean::Item, cx: &Context, parent: Option<&clean::Item extra_info } -fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Constant) { +fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) { write!(w, "
");
     render_attributes(w, it, false);
 
@@ -2397,7 +2407,7 @@ fn item_constant(w: &mut Buffer, cx: &Context, it: &clean::Item, c: &clean::Cons
     document(w, cx, it, None)
 }
 
-fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static) {
+fn item_static(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Static) {
     write!(w, "
");
     render_attributes(w, it, false);
     write!(
@@ -2411,7 +2421,7 @@ fn item_static(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Static
     document(w, cx, it, None)
 }
 
-fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Function) {
+fn item_function(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, f: &clean::Function) {
     let header_len = format!(
         "{}{}{}{}{:#}fn {}{:#}",
         it.visibility.print_with_space(),
@@ -2445,7 +2455,7 @@ fn item_function(w: &mut Buffer, cx: &Context, it: &clean::Item, f: &clean::Func
 }
 
 fn render_implementor(
-    cx: &Context,
+    cx: &Context<'_>,
     implementor: &Impl,
     parent: &clean::Item,
     w: &mut Buffer,
@@ -2482,7 +2492,7 @@ fn render_implementor(
 }
 
 fn render_impls(
-    cx: &Context,
+    cx: &Context<'_>,
     w: &mut Buffer,
     traits: &[&&Impl],
     containing_item: &clean::Item,
@@ -2541,7 +2551,7 @@ fn compare_impl<'a, 'b>(lhs: &'a &&Impl, rhs: &'b &&Impl) -> Ordering {
     compare_names(&lhs, &rhs)
 }
 
-fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait, cache: &Cache) {
+fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Trait, cache: &Cache) {
     let bounds = bounds(&t.bounds, false);
     let types = t.items.iter().filter(|m| m.is_associated_type()).collect::>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::>();
@@ -2637,7 +2647,13 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
         write!(w, "{}Loading content...", extra_content)
     }
 
-    fn trait_item(w: &mut Buffer, cx: &Context, m: &clean::Item, t: &clean::Item, cache: &Cache) {
+    fn trait_item(
+        w: &mut Buffer,
+        cx: &Context<'_>,
+        m: &clean::Item,
+        t: &clean::Item,
+        cache: &Cache,
+    ) {
         let name = m.name.as_ref().unwrap();
         info!("Documenting {} on {:?}", name, t.name);
         let item_type = m.type_();
@@ -3040,7 +3056,13 @@ fn render_assoc_item(
     }
 }
 
-fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct, cache: &Cache) {
+fn item_struct(
+    w: &mut Buffer,
+    cx: &Context<'_>,
+    it: &clean::Item,
+    s: &clean::Struct,
+    cache: &Cache,
+) {
     wrap_into_docblock(w, |w| {
         write!(w, "
");
         render_attributes(w, it, true);
@@ -3090,7 +3112,7 @@ fn item_struct(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Struct
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union, cache: &Cache) {
+fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Union, cache: &Cache) {
     wrap_into_docblock(w, |w| {
         write!(w, "
");
         render_attributes(w, it, true);
@@ -3136,7 +3158,7 @@ fn item_union(w: &mut Buffer, cx: &Context, it: &clean::Item, s: &clean::Union,
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_enum(w: &mut Buffer, cx: &Context, it: &clean::Item, e: &clean::Enum, cache: &Cache) {
+fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum, cache: &Cache) {
     wrap_into_docblock(w, |w| {
         write!(w, "
");
         render_attributes(w, it, true);
@@ -3444,7 +3466,7 @@ impl<'a> AssocItemLink<'a> {
 
 fn render_assoc_items(
     w: &mut Buffer,
-    cx: &Context,
+    cx: &Context<'_>,
     containing_item: &clean::Item,
     it: DefId,
     what: AssocItemRender<'_>,
@@ -3560,7 +3582,7 @@ fn render_assoc_items(
 
 fn render_deref_methods(
     w: &mut Buffer,
-    cx: &Context,
+    cx: &Context<'_>,
     impl_: &Impl,
     container_item: &clean::Item,
     deref_mut: bool,
@@ -3676,7 +3698,7 @@ fn spotlight_decl(decl: &clean::FnDecl) -> String {
 
 fn render_impl(
     w: &mut Buffer,
-    cx: &Context,
+    cx: &Context<'_>,
     i: &Impl,
     parent: &clean::Item,
     link: AssocItemLink<'_>,
@@ -3770,7 +3792,7 @@ fn render_impl(
 
     fn doc_impl_item(
         w: &mut Buffer,
-        cx: &Context,
+        cx: &Context<'_>,
         item: &clean::Item,
         parent: &clean::Item,
         link: AssocItemLink<'_>,
@@ -3907,7 +3929,7 @@ fn render_impl(
 
     fn render_default_items(
         w: &mut Buffer,
-        cx: &Context,
+        cx: &Context<'_>,
         t: &clean::Trait,
         i: &clean::Impl,
         parent: &clean::Item,
@@ -3967,7 +3989,7 @@ fn render_impl(
 
 fn item_opaque_ty(
     w: &mut Buffer,
-    cx: &Context,
+    cx: &Context<'_>,
     it: &clean::Item,
     t: &clean::OpaqueTy,
     cache: &Cache,
@@ -3994,7 +4016,7 @@ fn item_opaque_ty(
 
 fn item_trait_alias(
     w: &mut Buffer,
-    cx: &Context,
+    cx: &Context<'_>,
     it: &clean::Item,
     t: &clean::TraitAlias,
     cache: &Cache,
@@ -4019,7 +4041,13 @@ fn item_trait_alias(
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typedef, cache: &Cache) {
+fn item_typedef(
+    w: &mut Buffer,
+    cx: &Context<'_>,
+    it: &clean::Item,
+    t: &clean::Typedef,
+    cache: &Cache,
+) {
     write!(w, "
");
     render_attributes(w, it, false);
     write!(
@@ -4040,7 +4068,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Typed
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
+fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache: &Cache) {
     writeln!(w, "
extern {{");
     render_attributes(w, it, false);
     write!(
@@ -4055,7 +4083,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cac
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn print_sidebar(cx: &Context, it: &clean::Item, buffer: &mut Buffer, cache: &Cache) {
+fn print_sidebar(cx: &Context<'_>, it: &clean::Item, buffer: &mut Buffer, cache: &Cache) {
     let parentlen = cx.current.len() - if it.is_mod() { 1 } else { 0 };
 
     if it.is_struct()
@@ -4686,7 +4714,7 @@ fn sidebar_foreign_type(buf: &mut Buffer, it: &clean::Item) {
     }
 }
 
-fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro) {
+fn item_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) {
     wrap_into_docblock(w, |w| {
         w.write_str(&highlight::render_with_highlighting(
             t.source.clone(),
@@ -4698,7 +4726,7 @@ fn item_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Macro)
     document(w, cx, it, None)
 }
 
-fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::ProcMacro) {
+fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) {
     let name = it.name.as_ref().expect("proc-macros always have names");
     match m.kind {
         MacroKind::Bang => {
@@ -4728,12 +4756,12 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context, it: &clean::Item, m: &clean::Pr
     document(w, cx, it, None)
 }
 
-fn item_primitive(w: &mut Buffer, cx: &Context, it: &clean::Item, cache: &Cache) {
+fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, cache: &Cache) {
     document(w, cx, it, None);
     render_assoc_items(w, cx, it, it.def_id, AssocItemRender::All, cache)
 }
 
-fn item_keyword(w: &mut Buffer, cx: &Context, it: &clean::Item) {
+fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
     document(w, cx, it, None)
 }
 
diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs
index b6c3300906bfd..87934c8a0e50e 100644
--- a/src/librustdoc/html/sources.rs
+++ b/src/librustdoc/html/sources.rs
@@ -15,7 +15,7 @@ use std::path::{Component, Path, PathBuf};
 
 crate fn render(
     dst: &Path,
-    scx: &mut SharedContext,
+    scx: &mut SharedContext<'_>,
     krate: clean::Crate,
 ) -> Result {
     info!("emitting source files");
@@ -26,14 +26,14 @@ crate fn render(
 }
 
 /// Helper struct to render all source code to HTML pages
-struct SourceCollector<'a> {
-    scx: &'a mut SharedContext,
+struct SourceCollector<'a, 'tcx> {
+    scx: &'a mut SharedContext<'tcx>,
 
     /// Root destination to place all HTML output into
     dst: PathBuf,
 }
 
-impl<'a> DocFolder for SourceCollector<'a> {
+impl DocFolder for SourceCollector<'_, '_> {
     fn fold_item(&mut self, item: clean::Item) -> Option {
         // If we're not rendering sources, there's nothing to do.
         // If we're including source files, and we haven't seen this file yet,
@@ -69,9 +69,9 @@ impl<'a> DocFolder for SourceCollector<'a> {
     }
 }
 
-impl<'a> SourceCollector<'a> {
+impl SourceCollector<'_, '_> {
     fn sess(&self) -> &Session {
-        &self.scx.sess
+        &self.scx.tcx.sess
     }
 
     /// Renders the given filename into its corresponding HTML source file.
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 809cfb9d7432d..c362b9d2b964e 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -14,7 +14,7 @@ use crate::formats::item_type::ItemType;
 use crate::json::types::*;
 use crate::json::JsonRenderer;
 
-impl JsonRenderer {
+impl JsonRenderer<'_> {
     pub(super) fn convert_item(&self, item: clean::Item) -> Option {
         let item_type = ItemType::from(&item);
         let clean::Item {
@@ -57,10 +57,10 @@ impl JsonRenderer {
     }
 
     fn convert_span(&self, span: clean::Span) -> Option {
-        match span.filename(&self.sess) {
+        match span.filename(self.sess()) {
             rustc_span::FileName::Real(name) => {
-                let hi = span.hi(&self.sess);
-                let lo = span.lo(&self.sess);
+                let hi = span.hi(self.sess());
+                let lo = span.lo(self.sess());
                 Some(Span {
                     filename: match name {
                         rustc_span::RealFileName::Named(path) => path,
diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs
index 3d970918407c2..dc2bc14e7ceb9 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -13,7 +13,6 @@ use std::path::PathBuf;
 use std::rc::Rc;
 
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sync::Lrc;
 use rustc_middle::ty;
 use rustc_session::Session;
 use rustc_span::edition::Edition;
@@ -26,8 +25,8 @@ use crate::formats::FormatRenderer;
 use crate::html::render::cache::ExternalLocation;
 
 #[derive(Clone)]
-crate struct JsonRenderer {
-    sess: Lrc,
+crate struct JsonRenderer<'tcx> {
+    tcx: ty::TyCtxt<'tcx>,
     /// A mapping of IDs that contains all local items for this crate which gets output as a top
     /// level field of the JSON blob.
     index: Rc>>,
@@ -35,7 +34,11 @@ crate struct JsonRenderer {
     out_path: PathBuf,
 }
 
-impl JsonRenderer {
+impl JsonRenderer<'_> {
+    fn sess(&self) -> &Session {
+        self.tcx.sess
+    }
+
     fn get_trait_implementors(
         &mut self,
         id: rustc_span::def_id::DefId,
@@ -121,19 +124,19 @@ impl JsonRenderer {
     }
 }
 
-impl FormatRenderer for JsonRenderer {
+impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
     fn init(
         krate: clean::Crate,
         options: RenderOptions,
         _render_info: RenderInfo,
         _edition: Edition,
         _cache: &mut Cache,
-        tcx: ty::TyCtxt<'_>,
+        tcx: ty::TyCtxt<'tcx>,
     ) -> Result<(Self, clean::Crate), Error> {
         debug!("Initializing json renderer");
         Ok((
             JsonRenderer {
-                sess: tcx.sess,
+                tcx,
                 index: Rc::new(RefCell::new(FxHashMap::default())),
                 out_path: options.output,
             },
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index caa0706fd2b56..2d3b4f8706856 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -64,6 +64,7 @@ use std::process;
 
 use rustc_driver::abort_on_err;
 use rustc_errors::ErrorReported;
+use rustc_interface::interface;
 use rustc_middle::ty;
 use rustc_session::config::{make_crate_type_option, ErrorOutputType, RustcOptGroup};
 use rustc_session::getopts;
@@ -468,13 +469,13 @@ fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainRes
     }
 }
 
-fn run_renderer(
+fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>(
     krate: clean::Crate,
     renderopts: config::RenderOptions,
     render_info: config::RenderInfo,
     diag: &rustc_errors::Handler,
     edition: rustc_span::edition::Edition,
-    tcx: ty::TyCtxt<'_>,
+    tcx: ty::TyCtxt<'tcx>,
 ) -> MainResult {
     match formats::run_format::(krate, renderopts, render_info, &diag, edition, tcx) {
         Ok(_) => Ok(()),
@@ -577,7 +578,7 @@ fn main_options(options: config::Options) -> MainResult {
                 let diag = core::new_handler(error_format, None, &debugging_options);
                 match output_format {
                     None | Some(config::OutputFormat::Html) => sess.time("render_html", || {
-                        run_renderer::(
+                        run_renderer::>(
                             krate,
                             render_opts,
                             render_info,
@@ -587,7 +588,7 @@ fn main_options(options: config::Options) -> MainResult {
                         )
                     }),
                     Some(config::OutputFormat::Json) => sess.time("render_json", || {
-                        run_renderer::(
+                        run_renderer::>(
                             krate,
                             render_opts,
                             render_info,

From 789c902914e66285b36987a4f397d06ac50fed9e Mon Sep 17 00:00:00 2001
From: Joshua Nelson 
Date: Wed, 16 Dec 2020 16:02:15 -0500
Subject: [PATCH 6/8] Fix error with `--cfg parallel_compiler`

Apparently expansion() really does return Rc, not Lrc
---
 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 3b789dfd66f4c..7e85342ac7d5d 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -410,7 +410,7 @@ crate fn create_resolver<'a>(
     externs: config::Externs,
     queries: &Queries<'a>,
     sess: &Session,
-) -> Lrc> {
+) -> Rc> {
     let extern_names: Vec = externs
         .iter()
         .filter(|(_, entry)| entry.add_prelude)

From b421f2e8e94e578ed200dde235b7510b6a7014ba Mon Sep 17 00:00:00 2001
From: Joshua Nelson 
Date: Wed, 16 Dec 2020 16:22:11 -0500
Subject: [PATCH 7/8] TODO -> FIXME

---
 src/librustdoc/lib.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 2d3b4f8706856..0275a6ecd093b 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -524,7 +524,7 @@ fn main_options(options: config::Options) -> MainResult {
 
     let default_passes = options.default_passes;
     let output_format = options.output_format;
-    // TODO: fix this clone (especially render_options)
+    // FIXME: fix this clone (especially render_options)
     let externs = options.externs.clone();
     let manual_passes = options.manual_passes.clone();
     let render_options = options.render_options.clone();

From 0c2f76a4bf515a9c1bdb930ffb7f32b7ba6bd726 Mon Sep 17 00:00:00 2001
From: Joshua Nelson 
Date: Thu, 17 Dec 2020 11:40:02 -0500
Subject: [PATCH 8/8] Fix rebase conflict

---
 src/librustdoc/lib.rs | 4 ----
 1 file changed, 4 deletions(-)

diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 0275a6ecd093b..72f1b817d5d87 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -558,10 +558,6 @@ fn main_options(options: config::Options) -> MainResult {
                 });
                 info!("finished with rustc");
 
-                if let Some(name) = crate_name {
-                    krate.name = name
-                }
-
                 krate.version = crate_version;
 
                 if show_coverage {