Get rid of ExternCrate::primitives

This commit is contained in:
Joshua Nelson 2021-04-22 19:10:22 -04:00
parent 3bef65ffaf
commit d1d1739673
4 changed files with 77 additions and 77 deletions

View file

@ -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 }
}
}

View file

@ -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

View file

@ -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,

View file

@ -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);
}
}