about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-12-18 08:44:50 +0000
committerbors <bors@rust-lang.org>2020-12-18 08:44:50 +0000
commitd8d3ab96aa94423f1bdfbb605098a506ab5edc7e (patch)
tree2936a3802e2b60ed442868598dfaab61b4005128 /src
parentfee693d08e98d25f566075cbed73e12236c05abd (diff)
parent0c2f76a4bf515a9c1bdb930ffb7f32b7ba6bd726 (diff)
downloadrust-d8d3ab96aa94423f1bdfbb605098a506ab5edc7e.tar.gz
rust-d8d3ab96aa94423f1bdfbb605098a506ab5edc7e.zip
Auto merge of #80090 - jyn514:tcx-in-render, r=GuillaumeGomez
Pass a `TyCtxt` through to `FormatRender`

This is the next step after https://github.com/rust-lang/rust/pull/79957 for https://github.com/rust-lang/rust/issues/76382. Eventually I plan to use this to remove `stability`, `const_stability`, and `deprecation` from `Item`, but that needs more extensive changes (in particular, https://github.com/rust-lang/rust/pull/75355 or something like it).

This has no actual changes to behavior, it's just moving types around.

ccc https://github.com/rust-lang/rust/pull/80014#issuecomment-746810284
Diffstat (limited to 'src')
-rw-r--r--src/librustdoc/core.rs122
-rw-r--r--src/librustdoc/formats/renderer.rs13
-rw-r--r--src/librustdoc/html/render/mod.rs125
-rw-r--r--src/librustdoc/html/sources.rs12
-rw-r--r--src/librustdoc/json/conversions.rs8
-rw-r--r--src/librustdoc/json/mod.rs18
-rw-r--r--src/librustdoc/lib.rs107
7 files changed, 226 insertions, 179 deletions
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index b2eeaf584bf..7e85342ac7d 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};
@@ -273,12 +273,9 @@ where
     (lint_opts, lint_caps)
 }
 
-crate fn run_core(
-    options: RustdocOptions,
-) -> (clean::Crate, RenderInfo, RenderOptions, Lrc<Session>) {
-    // Parse, resolve, and typecheck the given crate.
-
-    let RustdocOptions {
+/// Parse, resolve, and typecheck the given crate.
+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<String> = 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,68 +403,50 @@ crate fn run_core(
         }),
         make_codegen_backend: None,
         registry: rustc_driver::diagnostics_registry(),
-    };
-
-    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 = {
-                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()
-            };
+crate fn create_resolver<'a>(
+    externs: config::Externs,
+    queries: &Queries<'a>,
+    sess: &Session,
+) -> Rc<RefCell<interface::BoxedResolver>> {
+    let extern_names: Vec<String> = externs
+        .iter()
+        .filter(|(_, entry)| entry.add_prelude)
+        .map(|(name, _)| name)
+        .cloned()
+        .collect();
 
-            if sess.has_errors() {
-                sess.fatal("Compilation failed, aborting rustdoc");
+    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)
+                    });
             }
+        });
+    });
 
-            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))
-        })
-    })
+    // Now we're good to clone the resolver because everything should be loaded
+    resolver.clone()
 }
 
-fn run_global_ctxt(
+crate fn run_global_ctxt(
     tcx: TyCtxt<'_>,
     resolver: Rc<RefCell<interface::BoxedResolver>>,
     mut default_passes: passes::DefaultPassOption,
diff --git a/src/librustdoc/formats/renderer.rs b/src/librustdoc/formats/renderer.rs
index f61919d78a0..fbbd3c1ccf5 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;
@@ -12,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(
@@ -21,7 +20,7 @@ crate trait FormatRenderer: Clone {
         render_info: RenderInfo,
         edition: Edition,
         cache: &mut Cache,
-        sess: Lrc<Session>,
+        tcx: ty::TyCtxt<'tcx>,
     ) -> Result<(Self, clean::Crate), Error>;
 
     /// Renders a single non-module item. This means no recursive sub-item rendering is required.
@@ -46,13 +45,13 @@ crate trait FormatRenderer: Clone {
 }
 
 /// Main method for rendering a crate.
-crate fn run_format<T: FormatRenderer>(
+crate fn run_format<'tcx, T: FormatRenderer<'tcx>>(
     krate: clean::Crate,
     options: RenderOptions,
     render_info: RenderInfo,
     diag: &rustc_errors::Handler,
     edition: Edition,
-    sess: Lrc<Session>,
+    tcx: ty::TyCtxt<'tcx>,
 ) -> Result<(), Error> {
     let (krate, mut cache) = Cache::from_krate(
         render_info.clone(),
@@ -63,7 +62,7 @@ crate fn run_format<T: FormatRenderer>(
     );
 
     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 62dac717968..67ccc3d4cf8 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -52,11 +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;
@@ -102,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<String>,
@@ -115,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<RefCell<IdMap>>,
-    crate shared: Arc<SharedContext>,
+    crate shared: Arc<SharedContext<'tcx>>,
     all: Rc<RefCell<AllTypes>>,
     /// Storage for the errors produced while generating documentation so they
     /// can be printed together at the end.
     crate errors: Rc<Receiver<String>>,
 }
 
-crate struct SharedContext {
-    crate sess: Lrc<Session>,
+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,
@@ -163,7 +164,7 @@ crate struct SharedContext {
     playground: Option<markdown::Playground>,
 }
 
-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
@@ -176,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) {
@@ -381,15 +382,15 @@ crate fn initial_ids() -> Vec<String> {
 }
 
 /// 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,
-        sess: Lrc<Session>,
-    ) -> 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 {
@@ -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,
@@ -688,7 +689,7 @@ impl FormatRenderer for Context {
 }
 
 fn write_shared(
-    cx: &Context,
+    cx: &Context<'_>,
     krate: &clean::Crate,
     search_index: String,
     options: &RenderOptions,
@@ -1205,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,
@@ -1516,7 +1517,7 @@ fn settings(root_path: &str, suffix: &str, themes: &[StylePath]) -> Result<Strin
     ))
 }
 
-impl Context {
+impl Context<'_> {
     fn derive_id(&self, id: String) -> String {
         let mut map = self.id_map.borrow_mut();
         map.derive(id)
@@ -1701,7 +1702,7 @@ where
     write!(w, "</div>")
 }
 
-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, "<h1 class=\"fqn\"><span class=\"out-of-band\">");
@@ -1816,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);
     }
@@ -1834,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<RenderedLink>,
     prefix: &str,
@@ -1863,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,
@@ -1904,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);
@@ -1925,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>,
@@ -2029,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::<Vec<usize>>();
@@ -2271,7 +2278,11 @@ fn portability(item: &clean::Item, parent: Option<&clean::Item>) -> Option<Strin
 
 /// Render the stability, deprecation and portability information that is displayed at the top of
 /// the item's documentation.
-fn short_item_info(item: &clean::Item, cx: &Context, parent: Option<&clean::Item>) -> Vec<String> {
+fn short_item_info(
+    item: &clean::Item,
+    cx: &Context<'_>,
+    parent: Option<&clean::Item>,
+) -> Vec<String> {
     let mut extra_info = vec![];
     let error_codes = cx.shared.codes;
 
@@ -2361,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, "<pre class=\"rust const\">");
     render_attributes(w, it, false);
 
@@ -2396,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, "<pre class=\"rust static\">");
     render_attributes(w, it, false);
     write!(
@@ -2410,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(),
@@ -2444,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,
@@ -2481,7 +2492,7 @@ fn render_implementor(
 }
 
 fn render_impls(
-    cx: &Context,
+    cx: &Context<'_>,
     w: &mut Buffer,
     traits: &[&&Impl],
     containing_item: &clean::Item,
@@ -2540,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::<Vec<_>>();
     let consts = t.items.iter().filter(|m| m.is_associated_const()).collect::<Vec<_>>();
@@ -2636,7 +2647,13 @@ fn item_trait(w: &mut Buffer, cx: &Context, it: &clean::Item, t: &clean::Trait,
         write!(w, "{}<span class=\"loading-content\">Loading content...</span>", 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_();
@@ -3039,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, "<pre class=\"rust struct\">");
         render_attributes(w, it, true);
@@ -3089,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, "<pre class=\"rust union\">");
         render_attributes(w, it, true);
@@ -3135,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, "<pre class=\"rust enum\">");
         render_attributes(w, it, true);
@@ -3443,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<'_>,
@@ -3559,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,
@@ -3675,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<'_>,
@@ -3769,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<'_>,
@@ -3906,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,
@@ -3966,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,
@@ -3993,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,
@@ -4018,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, "<pre class=\"rust typedef\">");
     render_attributes(w, it, false);
     write!(
@@ -4039,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, "<pre class=\"rust foreigntype\">extern {{");
     render_attributes(w, it, false);
     write!(
@@ -4054,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()
@@ -4685,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(),
@@ -4697,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 => {
@@ -4727,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 b6c3300906b..87934c8a0e5 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<clean::Crate, Error> {
     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<clean::Item> {
         // 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 9dc27e3411d..99587f4ec64 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<Item> {
         let item_type = ItemType::from(&item);
         let clean::Item {
@@ -57,10 +57,10 @@ impl JsonRenderer {
     }
 
     fn convert_span(&self, span: clean::Span) -> Option<Span> {
-        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 7af26558b76..dc2bc14e7ce 100644
--- a/src/librustdoc/json/mod.rs
+++ b/src/librustdoc/json/mod.rs
@@ -13,7 +13,7 @@ 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;
 
@@ -25,8 +25,8 @@ use crate::formats::FormatRenderer;
 use crate::html::render::cache::ExternalLocation;
 
 #[derive(Clone)]
-crate struct JsonRenderer {
-    sess: Lrc<Session>,
+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<RefCell<FxHashMap<types::Id, types::Item>>>,
@@ -34,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,
@@ -120,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,
-        sess: Lrc<Session>,
+        tcx: ty::TyCtxt<'tcx>,
     ) -> Result<(Self, clean::Crate), Error> {
         debug!("Initializing json renderer");
         Ok((
             JsonRenderer {
-                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 24045b4e29d..72f1b817d5d 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -62,11 +62,12 @@ 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]
@@ -468,15 +469,15 @@ fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainRes
     }
 }
 
-fn run_renderer<T: formats::FormatRenderer>(
+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,
-    sess: Lrc<Session>,
+    tcx: ty::TyCtxt<'tcx>,
 ) -> MainResult {
-    match formats::run_format::<T>(krate, renderopts, render_info, &diag, edition, sess) {
+    match formats::run_format::<T>(krate, renderopts, render_info, &diag, edition, tcx) {
         Ok(_) => Ok(()),
         Err(e) => {
             let mut msg = diag.struct_err(&format!("couldn't generate documentation: {}", e.error));
@@ -520,34 +521,80 @@ 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);
+    // 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();
+    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::<html::render::Context>(
-                krate, renderopts, renderinfo, &diag, edition, sess,
-            )
-        }),
-        Some(config::OutputFormat::Json) => sess_time.time("render_json", || {
-            run_renderer::<json::JsonRenderer>(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");
+
+                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);
+                match output_format {
+                    None | Some(config::OutputFormat::Html) => sess.time("render_html", || {
+                        run_renderer::<html::render::Context<'_>>(
+                            krate,
+                            render_opts,
+                            render_info,
+                            &diag,
+                            edition,
+                            tcx,
+                        )
+                    }),
+                    Some(config::OutputFormat::Json) => sess.time("render_json", || {
+                        run_renderer::<json::JsonRenderer<'_>>(
+                            krate,
+                            render_opts,
+                            render_info,
+                            &diag,
+                            edition,
+                            tcx,
+                        )
+                    }),
+                }
+            })
+        })
+    })
 }