From 5407a69aa4a816fdfd9cf6f659643f78659c1f88 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Thu, 22 Apr 2021 18:54:48 -0400
Subject: [PATCH 1/4] Remove src field from ExternCrate

---
 src/librustdoc/clean/mod.rs     |  4 +---
 src/librustdoc/clean/types.rs   | 10 +++++++++-
 src/librustdoc/clean/utils.rs   |  4 +++-
 src/librustdoc/formats/cache.rs |  2 +-
 4 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 7d33cf210139c..1b8c82b8323f5 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -86,8 +86,6 @@ impl Clean<ExternalCrate> for CrateNum {
     fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate {
         let tcx = cx.tcx;
         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
-        let krate_span = tcx.def_span(root);
-        let krate_src = cx.sess().source_map().span_to_filename(krate_span);
 
         // Collect all inner modules which are tagged as implementations of
         // primitives.
@@ -195,8 +193,8 @@ impl Clean<ExternalCrate> for CrateNum {
         };
 
         ExternalCrate {
+            crate_num: *self,
             name: tcx.crate_name(*self),
-            src: krate_src,
             attrs: tcx.get_attrs(root).clean(cx),
             primitives,
             keywords,
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 2b25c6a26bcc4..b24d441f0f85c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -72,13 +72,21 @@ crate struct TraitWithExtraInfo {
 
 #[derive(Clone, Debug)]
 crate struct ExternalCrate {
+    crate crate_num: CrateNum,
     crate name: Symbol,
-    crate src: FileName,
     crate attrs: Attributes,
     crate primitives: ThinVec<(DefId, PrimitiveType)>,
     crate keywords: ThinVec<(DefId, Symbol)>,
 }
 
+impl ExternalCrate {
+    crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
+        let root = DefId { krate: self.crate_num, index: rustc_hir::def_id::CRATE_DEF_INDEX };
+        let krate_span = tcx.def_span(root);
+        tcx.sess.source_map().span_to_filename(krate_span)
+    }
+}
+
 /// Anything with a source location and set of attributes and, optionally, a
 /// name. That is, anything that can be documented. This doesn't correspond
 /// directly to the AST's concept of an item; it's a strict superset.
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index c2a971d637513..7d058f9e92c60 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -54,7 +54,9 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
         _ => unreachable!(),
     }
 
-    let ExternalCrate { name, src, primitives, keywords, .. } = LOCAL_CRATE.clean(cx);
+    let local_crate = LOCAL_CRATE.clean(cx);
+    let src = local_crate.src(cx.tcx);
+    let ExternalCrate { name, primitives, keywords, .. } = local_crate;
     {
         let m = match *module.kind {
             ItemKind::ModuleItem(ref mut m) => m,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index b2b895cc6726e..5766ed7497d7f 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -155,7 +155,7 @@ impl Cache {
         // Cache where all our extern crates are located
         // FIXME: this part is specific to HTML so it'd be nice to remove it from the common code
         for &(n, ref e) in &krate.externs {
-            let src_root = match e.src {
+            let src_root = match e.src(tcx) {
                 FileName::Real(ref p) => match p.local_path().parent() {
                     Some(p) => p.to_path_buf(),
                     None => PathBuf::new(),

From 3bef65ffaf3ea435fa653bd99c72b3adde93ea95 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Thu, 22 Apr 2021 19:02:09 -0400
Subject: [PATCH 2/4] Remove `name` field from ExternalCrate

---
 src/librustdoc/clean/mod.rs         | 1 -
 src/librustdoc/clean/types.rs       | 5 ++++-
 src/librustdoc/clean/utils.rs       | 3 ++-
 src/librustdoc/formats/cache.rs     | 7 ++++---
 src/librustdoc/html/render/cache.rs | 3 ++-
 5 files changed, 12 insertions(+), 7 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 1b8c82b8323f5..2ea119626fe42 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -194,7 +194,6 @@ impl Clean<ExternalCrate> for CrateNum {
 
         ExternalCrate {
             crate_num: *self,
-            name: tcx.crate_name(*self),
             attrs: tcx.get_attrs(root).clean(cx),
             primitives,
             keywords,
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index b24d441f0f85c..a28e94eb2c8c5 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -73,7 +73,6 @@ crate struct TraitWithExtraInfo {
 #[derive(Clone, Debug)]
 crate struct ExternalCrate {
     crate crate_num: CrateNum,
-    crate name: Symbol,
     crate attrs: Attributes,
     crate primitives: ThinVec<(DefId, PrimitiveType)>,
     crate keywords: ThinVec<(DefId, Symbol)>,
@@ -85,6 +84,10 @@ impl ExternalCrate {
         let krate_span = tcx.def_span(root);
         tcx.sess.source_map().span_to_filename(krate_span)
     }
+
+    crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
+        tcx.crate_name(self.crate_num)
+    }
 }
 
 /// Anything with a source location and set of attributes and, optionally, a
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 7d058f9e92c60..6f230e27534af 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -56,7 +56,8 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
 
     let local_crate = LOCAL_CRATE.clean(cx);
     let src = local_crate.src(cx.tcx);
-    let ExternalCrate { name, primitives, keywords, .. } = local_crate;
+    let name = local_crate.name(cx.tcx);
+    let ExternalCrate { primitives, keywords, .. } = local_crate;
     {
         let m = match *module.kind {
             ItemKind::ModuleItem(ref mut m) => m,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 5766ed7497d7f..5c011c5a13c19 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -162,12 +162,13 @@ impl Cache {
                 },
                 _ => PathBuf::new(),
             };
-            let extern_url = extern_html_root_urls.get(&*e.name.as_str()).map(|u| &**u);
+            let name = e.name(tcx);
+            let extern_url = extern_html_root_urls.get(&*name.as_str()).map(|u| &**u);
             self.extern_locations
-                .insert(n, (e.name, src_root, extern_location(e, extern_url, &dst)));
+                .insert(n, (name, src_root, extern_location(e, extern_url, &dst, tcx)));
 
             let did = DefId { krate: n, index: CRATE_DEF_INDEX };
-            self.external_paths.insert(did, (vec![e.name.to_string()], ItemType::Module));
+            self.external_paths.insert(did, (vec![name.to_string()], ItemType::Module));
         }
 
         // Cache where all known primitives have their documentation located.
diff --git a/src/librustdoc/html/render/cache.rs b/src/librustdoc/html/render/cache.rs
index 2265905dcbaf4..b8544a0f439a7 100644
--- a/src/librustdoc/html/render/cache.rs
+++ b/src/librustdoc/html/render/cache.rs
@@ -31,10 +31,11 @@ crate fn extern_location(
     e: &clean::ExternalCrate,
     extern_url: Option<&str>,
     dst: &Path,
+    tcx: TyCtxt<'_>,
 ) -> ExternalLocation {
     use ExternalLocation::*;
     // See if there's documentation generated into the local directory
-    let local_location = dst.join(&*e.name.as_str());
+    let local_location = dst.join(&*e.name(tcx).as_str());
     if local_location.is_dir() {
         return Local;
     }

From d1d173967367c4ebc8a824b64a2ba965b89aac47 Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Thu, 22 Apr 2021 19:10:22 -0400
Subject: [PATCH 3/4] Get rid of ExternCrate::primitives

---
 src/librustdoc/clean/mod.rs     | 75 ++-------------------------------
 src/librustdoc/clean/types.rs   | 74 ++++++++++++++++++++++++++++++--
 src/librustdoc/clean/utils.rs   |  3 +-
 src/librustdoc/formats/cache.rs |  2 +-
 4 files changed, 77 insertions(+), 77 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 2ea119626fe42..10ab757c5fce1 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -87,73 +87,9 @@ impl Clean<ExternalCrate> for CrateNum {
         let tcx = cx.tcx;
         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
 
-        // Collect all inner modules which are tagged as implementations of
-        // primitives.
-        //
-        // Note that this loop only searches the top-level items of the crate,
-        // and this is intentional. If we were to search the entire crate for an
-        // item tagged with `#[doc(primitive)]` then we would also have to
-        // search the entirety of external modules for items tagged
-        // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
-        // all that metadata unconditionally).
-        //
-        // In order to keep the metadata load under control, the
-        // `#[doc(primitive)]` feature is explicitly designed to only allow the
-        // primitive tags to show up as the top level items in a crate.
-        //
-        // Also note that this does not attempt to deal with modules tagged
-        // duplicately for the same primitive. This is handled later on when
-        // rendering by delegating everything to a hash map.
-        let mut as_primitive = |res: Res| {
+        let as_keyword = |res: Res| {
             if let Res::Def(DefKind::Mod, def_id) = res {
-                let attrs = cx.tcx.get_attrs(def_id).clean(cx);
-                let mut prim = None;
-                for attr in attrs.lists(sym::doc) {
-                    if let Some(v) = attr.value_str() {
-                        if attr.has_name(sym::primitive) {
-                            prim = PrimitiveType::from_symbol(v);
-                            if prim.is_some() {
-                                break;
-                            }
-                            // FIXME: should warn on unknown primitives?
-                        }
-                    }
-                }
-                return prim.map(|p| (def_id, p));
-            }
-            None
-        };
-        let primitives = if root.is_local() {
-            tcx.hir()
-                .krate()
-                .item
-                .item_ids
-                .iter()
-                .filter_map(|&id| {
-                    let item = tcx.hir().item(id);
-                    match item.kind {
-                        hir::ItemKind::Mod(_) => {
-                            as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
-                        }
-                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
-                            if item.vis.node.is_pub() =>
-                        {
-                            as_primitive(path.res).map(|(_, prim)| {
-                                // Pretend the primitive is local.
-                                (id.def_id.to_def_id(), prim)
-                            })
-                        }
-                        _ => None,
-                    }
-                })
-                .collect()
-        } else {
-            tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
-        };
-
-        let mut as_keyword = |res: Res| {
-            if let Res::Def(DefKind::Mod, def_id) = res {
-                let attrs = tcx.get_attrs(def_id).clean(cx);
+                let attrs = tcx.get_attrs(def_id);
                 let mut keyword = None;
                 for attr in attrs.lists(sym::doc) {
                     if attr.has_name(sym::keyword) {
@@ -192,12 +128,7 @@ impl Clean<ExternalCrate> for CrateNum {
             tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
         };
 
-        ExternalCrate {
-            crate_num: *self,
-            attrs: tcx.get_attrs(root).clean(cx),
-            primitives,
-            keywords,
-        }
+        ExternalCrate { crate_num: *self, attrs: tcx.get_attrs(root).clean(cx), keywords }
     }
 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index a28e94eb2c8c5..1d32db062ee68 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -17,8 +17,8 @@ use rustc_attr::{ConstStability, Deprecation, Stability, StabilityLevel};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::thin_vec::ThinVec;
 use rustc_hir as hir;
-use rustc_hir::def::{CtorKind, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex};
+use rustc_hir::def::{CtorKind, DefKind, Res};
+use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX};
 use rustc_hir::lang_items::LangItem;
 use rustc_hir::{BodyId, Mutability};
 use rustc_index::vec::IndexVec;
@@ -74,7 +74,6 @@ crate struct TraitWithExtraInfo {
 crate struct ExternalCrate {
     crate crate_num: CrateNum,
     crate attrs: Attributes,
-    crate primitives: ThinVec<(DefId, PrimitiveType)>,
     crate keywords: ThinVec<(DefId, Symbol)>,
 }
 
@@ -88,6 +87,75 @@ impl ExternalCrate {
     crate fn name(&self, tcx: TyCtxt<'_>) -> Symbol {
         tcx.crate_name(self.crate_num)
     }
+
+    crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
+        let root = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
+
+        // Collect all inner modules which are tagged as implementations of
+        // primitives.
+        //
+        // Note that this loop only searches the top-level items of the crate,
+        // and this is intentional. If we were to search the entire crate for an
+        // item tagged with `#[doc(primitive)]` then we would also have to
+        // search the entirety of external modules for items tagged
+        // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
+        // all that metadata unconditionally).
+        //
+        // In order to keep the metadata load under control, the
+        // `#[doc(primitive)]` feature is explicitly designed to only allow the
+        // primitive tags to show up as the top level items in a crate.
+        //
+        // Also note that this does not attempt to deal with modules tagged
+        // duplicately for the same primitive. This is handled later on when
+        // rendering by delegating everything to a hash map.
+        let as_primitive = |res: Res| {
+            if let Res::Def(DefKind::Mod, def_id) = res {
+                let attrs = tcx.get_attrs(def_id);
+                let mut prim = None;
+                for attr in attrs.lists(sym::doc) {
+                    if let Some(v) = attr.value_str() {
+                        if attr.has_name(sym::primitive) {
+                            prim = PrimitiveType::from_symbol(v);
+                            if prim.is_some() {
+                                break;
+                            }
+                            // FIXME: should warn on unknown primitives?
+                        }
+                    }
+                }
+                return prim.map(|p| (def_id, p));
+            }
+            None
+        };
+
+        if root.is_local() {
+            tcx.hir()
+                .krate()
+                .item
+                .item_ids
+                .iter()
+                .filter_map(|&id| {
+                    let item = tcx.hir().item(id);
+                    match item.kind {
+                        hir::ItemKind::Mod(_) => {
+                            as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
+                        }
+                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
+                            if item.vis.node.is_pub() =>
+                        {
+                            as_primitive(path.res).map(|(_, prim)| {
+                                // Pretend the primitive is local.
+                                (id.def_id.to_def_id(), prim)
+                            })
+                        }
+                        _ => None,
+                    }
+                })
+                .collect()
+        } else {
+            tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
+        }
+    }
 }
 
 /// Anything with a source location and set of attributes and, optionally, a
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index 6f230e27534af..a066777609d92 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -57,7 +57,8 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     let local_crate = LOCAL_CRATE.clean(cx);
     let src = local_crate.src(cx.tcx);
     let name = local_crate.name(cx.tcx);
-    let ExternalCrate { primitives, keywords, .. } = local_crate;
+    let primitives = local_crate.primitives(cx.tcx);
+    let ExternalCrate { keywords, .. } = local_crate;
     {
         let m = match *module.kind {
             ItemKind::ModuleItem(ref mut m) => m,
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 5c011c5a13c19..9a61f963a3ec3 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -176,7 +176,7 @@ impl Cache {
         // Favor linking to as local extern as possible, so iterate all crates in
         // reverse topological order.
         for &(_, ref e) in krate.externs.iter().rev() {
-            for &(def_id, prim) in &e.primitives {
+            for &(def_id, prim) in &e.primitives(tcx) {
                 self.primitive_locations.insert(prim, def_id);
             }
         }

From 6c6bd88ab36593f60e9dcf252a3bd9511374874a Mon Sep 17 00:00:00 2001
From: Joshua Nelson <jyn514@gmail.com>
Date: Thu, 22 Apr 2021 19:16:41 -0400
Subject: [PATCH 4/4] Remove `keywords` from ExternCrate

---
 src/librustdoc/clean/mod.rs   | 45 +---------------------------
 src/librustdoc/clean/types.rs | 56 ++++++++++++++++++++++++++++++++---
 src/librustdoc/clean/utils.rs |  8 ++---
 3 files changed, 57 insertions(+), 52 deletions(-)

diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 10ab757c5fce1..72046645e3a97 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -84,51 +84,8 @@ impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
 
 impl Clean<ExternalCrate> for CrateNum {
     fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate {
-        let tcx = cx.tcx;
         let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
-
-        let as_keyword = |res: Res| {
-            if let Res::Def(DefKind::Mod, def_id) = res {
-                let attrs = tcx.get_attrs(def_id);
-                let mut keyword = None;
-                for attr in attrs.lists(sym::doc) {
-                    if attr.has_name(sym::keyword) {
-                        if let Some(v) = attr.value_str() {
-                            keyword = Some(v);
-                            break;
-                        }
-                    }
-                }
-                return keyword.map(|p| (def_id, p));
-            }
-            None
-        };
-        let keywords = if root.is_local() {
-            tcx.hir()
-                .krate()
-                .item
-                .item_ids
-                .iter()
-                .filter_map(|&id| {
-                    let item = tcx.hir().item(id);
-                    match item.kind {
-                        hir::ItemKind::Mod(_) => {
-                            as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
-                        }
-                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
-                            if item.vis.node.is_pub() =>
-                        {
-                            as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
-                        }
-                        _ => None,
-                    }
-                })
-                .collect()
-        } else {
-            tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
-        };
-
-        ExternalCrate { crate_num: *self, attrs: tcx.get_attrs(root).clean(cx), keywords }
+        ExternalCrate { crate_num: *self, attrs: cx.tcx.get_attrs(root).clean(cx) }
     }
 }
 
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 1d32db062ee68..9f686d19e3c91 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -74,13 +74,16 @@ crate struct TraitWithExtraInfo {
 crate struct ExternalCrate {
     crate crate_num: CrateNum,
     crate attrs: Attributes,
-    crate keywords: ThinVec<(DefId, Symbol)>,
 }
 
 impl ExternalCrate {
+    #[inline]
+    fn def_id(&self) -> DefId {
+        DefId { krate: self.crate_num, index: CRATE_DEF_INDEX }
+    }
+
     crate fn src(&self, tcx: TyCtxt<'_>) -> FileName {
-        let root = DefId { krate: self.crate_num, index: rustc_hir::def_id::CRATE_DEF_INDEX };
-        let krate_span = tcx.def_span(root);
+        let krate_span = tcx.def_span(self.def_id());
         tcx.sess.source_map().span_to_filename(krate_span)
     }
 
@@ -88,8 +91,53 @@ impl ExternalCrate {
         tcx.crate_name(self.crate_num)
     }
 
+    crate fn keywords(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, Symbol)> {
+        let root = self.def_id();
+
+        let as_keyword = |res: Res| {
+            if let Res::Def(DefKind::Mod, def_id) = res {
+                let attrs = tcx.get_attrs(def_id);
+                let mut keyword = None;
+                for attr in attrs.lists(sym::doc) {
+                    if attr.has_name(sym::keyword) {
+                        if let Some(v) = attr.value_str() {
+                            keyword = Some(v);
+                            break;
+                        }
+                    }
+                }
+                return keyword.map(|p| (def_id, p));
+            }
+            None
+        };
+        if root.is_local() {
+            tcx.hir()
+                .krate()
+                .item
+                .item_ids
+                .iter()
+                .filter_map(|&id| {
+                    let item = tcx.hir().item(id);
+                    match item.kind {
+                        hir::ItemKind::Mod(_) => {
+                            as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
+                        }
+                        hir::ItemKind::Use(ref path, hir::UseKind::Single)
+                            if item.vis.node.is_pub() =>
+                        {
+                            as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
+                        }
+                        _ => None,
+                    }
+                })
+                .collect()
+        } else {
+            tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
+        }
+    }
+
     crate fn primitives(&self, tcx: TyCtxt<'_>) -> ThinVec<(DefId, PrimitiveType)> {
-        let root = DefId { krate: self.crate_num, index: CRATE_DEF_INDEX };
+        let root = self.def_id();
 
         // Collect all inner modules which are tagged as implementations of
         // primitives.
diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs
index a066777609d92..55a0cb42a2081 100644
--- a/src/librustdoc/clean/utils.rs
+++ b/src/librustdoc/clean/utils.rs
@@ -1,9 +1,9 @@
 use crate::clean::auto_trait::AutoTraitFinder;
 use crate::clean::blanket_impl::BlanketImplFinder;
 use crate::clean::{
-    inline, Clean, Crate, ExternalCrate, Generic, GenericArg, GenericArgs, ImportSource, Item,
-    ItemKind, Lifetime, MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type,
-    TypeBinding, TypeKind,
+    inline, Clean, Crate, Generic, GenericArg, GenericArgs, ImportSource, Item, ItemKind, Lifetime,
+    MacroKind, Path, PathSegment, Primitive, PrimitiveType, ResolvedPath, Type, TypeBinding,
+    TypeKind,
 };
 use crate::core::DocContext;
 
@@ -58,7 +58,7 @@ crate fn krate(cx: &mut DocContext<'_>) -> Crate {
     let src = local_crate.src(cx.tcx);
     let name = local_crate.name(cx.tcx);
     let primitives = local_crate.primitives(cx.tcx);
-    let ExternalCrate { keywords, .. } = local_crate;
+    let keywords = local_crate.keywords(cx.tcx);
     {
         let m = match *module.kind {
             ItemKind::ModuleItem(ref mut m) => m,