Auto merge of #86644 - Stupremee:replace-fakedefids-with-itemid, r=jyn514

rustdoc: Replace `FakeDefId` with new `ItemId` type

Follow up from #84707

`@Manishearth` [suggested](https://github.com/rust-lang/rust/pull/84707#issuecomment-831994669) that there should be a new `ItemId` type that can distinguish between auto traits, normal ids, and blanket impls instead of using `FakeDefId`s.

This type is introduced by this PR.

There are still some `FIXME`s left, because I was unsure what the best solution for them would be.

Especially the naming in general now is a bit weird right now and needs to be cleaned up. Now there are no "fake" ids so the `is_fake` method on `Item` does not really make sense and maybe the methods on `ItemId` should be renamed too?

Also, we need to represent the new item ids in the JSON backend somehow.
This commit is contained in:
bors 2021-07-06 04:13:52 +00:00
commit 9a27044f42
20 changed files with 188 additions and 179 deletions

View file

@ -113,7 +113,7 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
name: None,
attrs: Default::default(),
visibility: Inherited,
def_id: FakeDefId::new_fake(item_def_id.krate),
def_id: ItemId::Auto { trait_: trait_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
span: Span::dummy(),
unsafety: hir::Unsafety::Normal,

View file

@ -96,7 +96,7 @@ impl<'a, 'tcx> BlanketImplFinder<'a, 'tcx> {
name: None,
attrs: Default::default(),
visibility: Inherited,
def_id: FakeDefId::new_fake(item_def_id.krate),
def_id: ItemId::Blanket { impl_id: impl_def_id, for_: item_def_id },
kind: box ImplItem(Impl {
span: self.cx.tcx.def_span(impl_def_id).clean(self.cx),
unsafety: hir::Unsafety::Normal,

View file

@ -15,7 +15,7 @@ use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym, Symbol};
use crate::clean::{
self, utils, Attributes, AttributesExt, FakeDefId, GetDefId, NestedAttributesExt, Type,
self, utils, Attributes, AttributesExt, GetDefId, ItemId, NestedAttributesExt, Type,
};
use crate::core::DocContext;
use crate::formats::item_type::ItemType;
@ -483,10 +483,11 @@ fn build_module(
}
if let Res::PrimTy(p) = item.res {
// Primitive types can't be inlined so generate an import instead.
let prim_ty = clean::PrimitiveType::from(p);
items.push(clean::Item {
name: None,
attrs: box clean::Attributes::default(),
def_id: FakeDefId::new_fake(did.krate),
def_id: ItemId::Primitive(prim_ty, did.krate),
visibility: clean::Public,
kind: box clean::ImportItem(clean::Import::new_simple(
item.ident.name,
@ -495,7 +496,7 @@ fn build_module(
global: false,
res: item.res,
segments: vec![clean::PathSegment {
name: clean::PrimitiveType::from(p).as_sym(),
name: prim_ty.as_sym(),
args: clean::GenericArgs::AngleBracketed {
args: Vec::new(),
bindings: Vec::new(),

View file

@ -1,4 +1,4 @@
use std::cell::{Cell, RefCell};
use std::cell::RefCell;
use std::default::Default;
use std::hash::{Hash, Hasher};
use std::iter::FromIterator;
@ -48,73 +48,68 @@ use self::ItemKind::*;
use self::SelfTy::*;
use self::Type::*;
crate type FakeDefIdSet = FxHashSet<FakeDefId>;
crate type ItemIdSet = FxHashSet<ItemId>;
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
crate enum FakeDefId {
Real(DefId),
Fake(DefIndex, CrateNum),
#[derive(Debug, Clone, PartialEq, Eq, Hash, Copy)]
crate enum ItemId {
/// A "normal" item that uses a [`DefId`] for identification.
DefId(DefId),
/// Identifier that is used for auto traits.
Auto { trait_: DefId, for_: DefId },
/// Identifier that is used for blanket implementations.
Blanket { impl_id: DefId, for_: DefId },
/// Identifier for primitive types.
Primitive(PrimitiveType, CrateNum),
}
impl FakeDefId {
#[cfg(parallel_compiler)]
crate fn new_fake(crate: CrateNum) -> Self {
unimplemented!("")
}
#[cfg(not(parallel_compiler))]
crate fn new_fake(krate: CrateNum) -> Self {
thread_local!(static FAKE_DEF_ID_COUNTER: Cell<usize> = Cell::new(0));
let id = FAKE_DEF_ID_COUNTER.with(|id| {
let tmp = id.get();
id.set(tmp + 1);
tmp
});
Self::Fake(DefIndex::from(id), krate)
}
impl ItemId {
#[inline]
crate fn is_local(self) -> bool {
match self {
FakeDefId::Real(id) => id.is_local(),
FakeDefId::Fake(_, krate) => krate == LOCAL_CRATE,
ItemId::Auto { for_: id, .. }
| ItemId::Blanket { for_: id, .. }
| ItemId::DefId(id) => id.is_local(),
ItemId::Primitive(_, krate) => krate == LOCAL_CRATE,
}
}
#[inline]
#[track_caller]
crate fn expect_real(self) -> rustc_hir::def_id::DefId {
self.as_real().unwrap_or_else(|| panic!("FakeDefId::expect_real: `{:?}` isn't real", self))
crate fn expect_def_id(self) -> DefId {
self.as_def_id()
.unwrap_or_else(|| panic!("ItemId::expect_def_id: `{:?}` isn't a DefId", self))
}
#[inline]
crate fn as_real(self) -> Option<DefId> {
crate fn as_def_id(self) -> Option<DefId> {
match self {
FakeDefId::Real(id) => Some(id),
FakeDefId::Fake(_, _) => None,
ItemId::DefId(id) => Some(id),
_ => None,
}
}
#[inline]
crate fn krate(self) -> CrateNum {
match self {
FakeDefId::Real(id) => id.krate,
FakeDefId::Fake(_, krate) => krate,
ItemId::Auto { for_: id, .. }
| ItemId::Blanket { for_: id, .. }
| ItemId::DefId(id) => id.krate,
ItemId::Primitive(_, krate) => krate,
}
}
#[inline]
crate fn index(self) -> Option<DefIndex> {
match self {
FakeDefId::Real(id) => Some(id.index),
FakeDefId::Fake(_, _) => None,
ItemId::DefId(id) => Some(id.index),
_ => None,
}
}
}
impl From<DefId> for FakeDefId {
impl From<DefId> for ItemId {
fn from(id: DefId) -> Self {
Self::Real(id)
Self::DefId(id)
}
}
@ -338,14 +333,14 @@ crate struct Item {
/// Information about this item that is specific to what kind of item it is.
/// E.g., struct vs enum vs function.
crate kind: Box<ItemKind>,
crate def_id: FakeDefId,
crate def_id: ItemId,
crate cfg: Option<Arc<Cfg>>,
}
// `Item` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Item, 48);
rustc_data_structures::static_assert_size!(Item, 56);
crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
Span::from_rustc_span(def_id.as_local().map_or_else(
@ -359,19 +354,19 @@ crate fn rustc_span(def_id: DefId, tcx: TyCtxt<'_>) -> Span {
impl Item {
crate fn stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx Stability> {
if self.is_fake() { None } else { tcx.lookup_stability(self.def_id.expect_real()) }
self.def_id.as_def_id().and_then(|did| tcx.lookup_stability(did))
}
crate fn const_stability<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Option<&'tcx ConstStability> {
if self.is_fake() { None } else { tcx.lookup_const_stability(self.def_id.expect_real()) }
self.def_id.as_def_id().and_then(|did| tcx.lookup_const_stability(did))
}
crate fn deprecation(&self, tcx: TyCtxt<'_>) -> Option<Deprecation> {
if self.is_fake() { None } else { tcx.lookup_deprecation(self.def_id.expect_real()) }
self.def_id.as_def_id().and_then(|did| tcx.lookup_deprecation(did))
}
crate fn inner_docs(&self, tcx: TyCtxt<'_>) -> bool {
if self.is_fake() { false } else { tcx.get_attrs(self.def_id.expect_real()).inner_docs() }
self.def_id.as_def_id().map(|did| tcx.get_attrs(did).inner_docs()).unwrap_or(false)
}
crate fn span(&self, tcx: TyCtxt<'_>) -> Span {
@ -383,10 +378,8 @@ impl Item {
kind
{
*span
} else if self.is_fake() {
Span::dummy()
} else {
rustc_span(self.def_id.expect_real(), tcx)
self.def_id.as_def_id().map(|did| rustc_span(did, tcx)).unwrap_or_else(|| Span::dummy())
}
}
@ -551,7 +544,7 @@ impl Item {
}
crate fn is_crate(&self) -> bool {
self.is_mod() && self.def_id.as_real().map_or(false, |did| did.index == CRATE_DEF_INDEX)
self.is_mod() && self.def_id.as_def_id().map_or(false, |did| did.index == CRATE_DEF_INDEX)
}
crate fn is_mod(&self) -> bool {
self.type_() == ItemType::Module
@ -662,10 +655,6 @@ impl Item {
_ => false,
}
}
crate fn is_fake(&self) -> bool {
matches!(self.def_id, FakeDefId::Fake(_, _))
}
}
#[derive(Clone, Debug)]

View file

@ -30,7 +30,7 @@ use std::mem;
use std::rc::Rc;
use crate::clean::inline::build_external_trait;
use crate::clean::{self, FakeDefId, TraitWithExtraInfo};
use crate::clean::{self, ItemId, TraitWithExtraInfo};
use crate::config::{Options as RustdocOptions, OutputFormat, RenderOptions};
use crate::formats::cache::Cache;
use crate::passes::{self, Condition::*, ConditionalPass};
@ -78,7 +78,7 @@ crate struct DocContext<'tcx> {
/// This same cache is used throughout rustdoc, including in [`crate::html::render`].
crate cache: Cache,
/// Used by [`clean::inline`] to tell if an item has already been inlined.
crate inlined: FxHashSet<FakeDefId>,
crate inlined: FxHashSet<ItemId>,
/// Used by `calculate_doc_coverage`.
crate output_format: OutputFormat,
}
@ -128,12 +128,13 @@ impl<'tcx> DocContext<'tcx> {
/// Like `hir().local_def_id_to_hir_id()`, but skips calling it on fake DefIds.
/// (This avoids a slice-index-out-of-bounds panic.)
crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: FakeDefId) -> Option<HirId> {
crate fn as_local_hir_id(tcx: TyCtxt<'_>, def_id: ItemId) -> Option<HirId> {
match def_id {
FakeDefId::Real(real_id) => {
ItemId::DefId(real_id) => {
real_id.as_local().map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id))
}
FakeDefId::Fake(_, _) => None,
// FIXME: Can this be `Some` for `Auto` or `Blanket`?
_ => None,
}
}
}

View file

@ -8,7 +8,7 @@ use rustc_middle::middle::privacy::AccessLevels;
use rustc_middle::ty::TyCtxt;
use rustc_span::symbol::sym;
use crate::clean::{self, FakeDefId, GetDefId};
use crate::clean::{self, GetDefId, ItemId};
use crate::fold::DocFolder;
use crate::formats::item_type::ItemType;
use crate::formats::Impl;
@ -122,7 +122,7 @@ crate struct Cache {
/// All intra-doc links resolved so far.
///
/// Links are indexed by the DefId of the item they document.
crate intra_doc_links: BTreeMap<FakeDefId, Vec<clean::ItemLink>>,
crate intra_doc_links: FxHashMap<ItemId, Vec<clean::ItemLink>>,
}
/// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`.
@ -215,7 +215,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// Propagate a trait method's documentation to all implementors of the
// trait.
if let clean::TraitItem(ref t) = *item.kind {
self.cache.traits.entry(item.def_id.expect_real()).or_insert_with(|| {
self.cache.traits.entry(item.def_id.expect_def_id()).or_insert_with(|| {
clean::TraitWithExtraInfo {
trait_: t.clone(),
is_notable: item.attrs.has_doc_flag(sym::notable_trait),
@ -348,11 +348,11 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
// `public_items` map, so we can skip inserting into the
// paths map if there was already an entry present and we're
// not a public item.
if !self.cache.paths.contains_key(&item.def_id.expect_real())
|| self.cache.access_levels.is_public(item.def_id.expect_real())
if !self.cache.paths.contains_key(&item.def_id.expect_def_id())
|| self.cache.access_levels.is_public(item.def_id.expect_def_id())
{
self.cache.paths.insert(
item.def_id.expect_real(),
item.def_id.expect_def_id(),
(self.cache.stack.clone(), item.type_()),
);
}
@ -361,7 +361,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
clean::PrimitiveItem(..) => {
self.cache
.paths
.insert(item.def_id.expect_real(), (self.cache.stack.clone(), item.type_()));
.insert(item.def_id.expect_def_id(), (self.cache.stack.clone(), item.type_()));
}
clean::ExternCrateItem { .. }
@ -391,7 +391,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
| clean::StructItem(..)
| clean::UnionItem(..)
| clean::VariantItem(..) => {
self.cache.parent_stack.push(item.def_id.expect_real());
self.cache.parent_stack.push(item.def_id.expect_def_id());
self.cache.parent_is_trait_impl = false;
true
}

View file

@ -19,7 +19,7 @@ use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_target::spec::abi::Abi;
use crate::clean::{
self, utils::find_nearest_parent_module, ExternalCrate, FakeDefId, GetDefId, PrimitiveType,
self, utils::find_nearest_parent_module, ExternalCrate, GetDefId, ItemId, PrimitiveType,
};
use crate::formats::item_type::ItemType;
use crate::html::escape::Escape;
@ -1181,7 +1181,7 @@ impl clean::FnDecl {
impl clean::Visibility {
crate fn print_with_space<'a, 'tcx: 'a>(
self,
item_did: FakeDefId,
item_did: ItemId,
cx: &'a Context<'tcx>,
) -> impl fmt::Display + 'a + Captures<'tcx> {
let to_print = match self {
@ -1191,7 +1191,7 @@ impl clean::Visibility {
// FIXME(camelid): This may not work correctly if `item_did` is a module.
// However, rustdoc currently never displays a module's
// visibility, so it shouldn't matter.
let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_real());
let parent_module = find_nearest_parent_module(cx.tcx(), item_did.expect_def_id());
if vis_did.index == CRATE_DEF_INDEX {
"pub(crate) ".to_owned()

View file

@ -230,7 +230,7 @@ impl<'tcx> Context<'tcx> {
&self.shared.style_files,
)
} else {
if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_real()) {
if let Some(&(ref names, ty)) = self.cache.paths.get(&it.def_id.expect_def_id()) {
let mut path = String::new();
for name in &names[..names.len() - 1] {
path.push_str(name);

View file

@ -53,7 +53,7 @@ use rustc_span::symbol::{kw, sym, Symbol};
use serde::ser::SerializeSeq;
use serde::{Serialize, Serializer};
use crate::clean::{self, FakeDefId, GetDefId, RenderedLink, SelfTy};
use crate::clean::{self, GetDefId, ItemId, RenderedLink, SelfTy};
use crate::docfs::PathError;
use crate::error::Error;
use crate::formats::cache::Cache;
@ -735,7 +735,7 @@ fn naive_assoc_href(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
AssocItemLink::Anchor(Some(ref id)) => format!("#{}", id),
AssocItemLink::Anchor(None) => anchor,
AssocItemLink::GotoSource(did, _) => {
href(did.expect_real(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
href(did.expect_def_id(), cx).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
}
}
}
@ -867,7 +867,7 @@ fn render_assoc_item(
ItemType::TyMethod
};
href(did.expect_real(), cx)
href(did.expect_def_id(), cx)
.map(|p| format!("{}#{}.{}", p.0, ty, name))
.unwrap_or_else(|| format!("#{}.{}", ty, name))
}
@ -987,7 +987,7 @@ fn render_attributes_in_code(w: &mut Buffer, it: &clean::Item) {
#[derive(Copy, Clone)]
enum AssocItemLink<'a> {
Anchor(Option<&'a str>),
GotoSource(FakeDefId, &'a FxHashSet<Symbol>),
GotoSource(ItemId, &'a FxHashSet<Symbol>),
}
impl<'a> AssocItemLink<'a> {
@ -1819,7 +1819,7 @@ fn small_url_encode(s: String) -> String {
}
fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
let did = it.def_id.expect_real();
let did = it.def_id.expect_def_id();
if let Some(v) = cx.cache.impls.get(&did) {
let mut used_links = FxHashSet::default();
let cache = cx.cache();
@ -2109,7 +2109,7 @@ fn sidebar_trait(cx: &Context<'_>, buf: &mut Buffer, it: &clean::Item, t: &clean
"</div>",
);
if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) {
if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
let cache = cx.cache();
let mut res = implementors
.iter()

View file

@ -289,7 +289,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
w,
"<div class=\"item-left\"><code>{}extern crate {} as {};",
myitem.visibility.print_with_space(myitem.def_id, cx),
anchor(myitem.def_id.expect_real(), &*src.as_str(), cx),
anchor(myitem.def_id.expect_def_id(), &*src.as_str(), cx),
myitem.name.as_ref().unwrap(),
),
None => write!(
@ -297,7 +297,7 @@ fn item_module(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item, items: &[cl
"<div class=\"item-left\"><code>{}extern crate {};",
myitem.visibility.print_with_space(myitem.def_id, cx),
anchor(
myitem.def_id.expect_real(),
myitem.def_id.expect_def_id(),
&*myitem.name.as_ref().unwrap().as_str(),
cx
),
@ -669,9 +669,9 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
}
// If there are methods directly on this trait object, render them here.
render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All);
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All);
if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_real()) {
if let Some(implementors) = cx.cache.implementors.get(&it.def_id.expect_def_id()) {
// The DefId is for the first Type found with that name. The bool is
// if any Types with the same name but different DefId have been found.
let mut implementor_dups: FxHashMap<Symbol, (DefId, bool)> = FxHashMap::default();
@ -787,7 +787,7 @@ fn item_trait(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Tra
path = if it.def_id.is_local() {
cx.current.join("/")
} else {
let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_real()];
let (ref path, _) = cx.cache.external_paths[&it.def_id.expect_def_id()];
path[..path.len() - 1].join("/")
},
ty = it.type_(),
@ -813,7 +813,7 @@ fn item_trait_alias(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clea
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::OpaqueTy) {
@ -834,7 +834,7 @@ fn item_opaque_ty(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean:
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
// we need #14072 to make sense of the generics.
render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::Typedef) {
@ -851,7 +851,7 @@ fn item_typedef(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, t: &clean::T
document(w, cx, it, None);
let def_id = it.def_id.expect_real();
let def_id = it.def_id.expect_def_id();
// Render any items associated directly to this alias, as otherwise they
// won't be visible anywhere in the docs. It would be nice to also show
// associated items from the aliased type (see discussion in #32077), but
@ -903,7 +903,7 @@ fn item_union(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::Uni
document(w, cx, field, Some(it));
}
}
let def_id = it.def_id.expect_real();
let def_id = it.def_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
@ -1041,7 +1041,7 @@ fn item_enum(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, e: &clean::Enum
}
}
}
let def_id = it.def_id.expect_real();
let def_id = it.def_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
@ -1093,7 +1093,7 @@ fn item_proc_macro(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, m: &clean
fn item_primitive(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
document(w, cx, it, None);
render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_constant(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, c: &clean::Constant) {
@ -1182,7 +1182,7 @@ fn item_struct(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item, s: &clean::St
}
}
}
let def_id = it.def_id.expect_real();
let def_id = it.def_id.expect_def_id();
render_assoc_items(w, cx, it, def_id, AssocItemRender::All);
document_type_layout(w, cx, def_id);
}
@ -1213,7 +1213,7 @@ fn item_foreign_type(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {
document(w, cx, it, None);
render_assoc_items(w, cx, it, it.def_id.expect_real(), AssocItemRender::All)
render_assoc_items(w, cx, it, it.def_id.expect_def_id(), AssocItemRender::All)
}
fn item_keyword(w: &mut Buffer, cx: &Context<'_>, it: &clean::Item) {

View file

@ -5,9 +5,10 @@
#![allow(rustc::default_hash_types)]
use std::convert::From;
use std::fmt;
use rustc_ast::ast;
use rustc_hir::def::CtorKind;
use rustc_hir::{def::CtorKind, def_id::DefId};
use rustc_middle::ty::TyCtxt;
use rustc_span::def_id::CRATE_DEF_INDEX;
use rustc_span::Pos;
@ -15,7 +16,7 @@ use rustc_span::Pos;
use rustdoc_json_types::*;
use crate::clean::utils::print_const_expr;
use crate::clean::{self, FakeDefId};
use crate::clean::{self, ItemId};
use crate::formats::item_type::ItemType;
use crate::json::JsonRenderer;
use std::collections::HashSet;
@ -30,7 +31,7 @@ impl JsonRenderer<'_> {
.into_iter()
.flatten()
.filter_map(|clean::ItemLink { link, did, .. }| {
did.map(|did| (link.clone(), from_def_id(did.into())))
did.map(|did| (link.clone(), from_item_id(did.into())))
})
.collect();
let docs = item.attrs.collapsed_doc_value();
@ -47,7 +48,7 @@ impl JsonRenderer<'_> {
_ => from_clean_item(item, self.tcx),
};
Some(Item {
id: from_def_id(def_id),
id: from_item_id(def_id),
crate_id: def_id.krate().as_u32(),
name: name.map(|sym| sym.to_string()),
span: self.convert_span(span),
@ -86,7 +87,7 @@ impl JsonRenderer<'_> {
Inherited => Visibility::Default,
Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
Restricted(did) => Visibility::Restricted {
parent: from_def_id(did.into()),
parent: from_item_id(did.into()),
path: self.tcx.def_path(did).to_string_no_crate_verbose(),
},
}
@ -170,12 +171,24 @@ impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
}
}
crate fn from_def_id(did: FakeDefId) -> Id {
crate fn from_item_id(did: ItemId) -> Id {
struct DisplayDefId(DefId);
impl fmt::Display for DisplayDefId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{}", self.0.krate.as_u32(), u32::from(self.0.index))
}
}
match did {
FakeDefId::Real(did) => Id(format!("{}:{}", did.krate.as_u32(), u32::from(did.index))),
// We need to differentiate real and fake ids, because the indices might overlap for fake
// and real DefId's, which would cause two different Id's treated as they were the same.
FakeDefId::Fake(idx, krate) => Id(format!("F{}:{}", krate.as_u32(), u32::from(idx))),
ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
ItemId::Blanket { for_, impl_id } => {
Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
}
ItemId::Auto { for_, trait_ } => {
Id(format!("a:{}-{}", DisplayDefId(trait_), DisplayDefId(for_)))
}
ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
}
}
@ -375,7 +388,7 @@ impl FromWithTcx<clean::Type> for Type {
match ty {
ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath {
name: path.whole_name(),
id: from_def_id(did.into()),
id: from_item_id(did.into()),
args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
param_names: Vec::new(),
},
@ -387,7 +400,7 @@ impl FromWithTcx<clean::Type> for Type {
Type::ResolvedPath {
name: path.whole_name(),
id: from_def_id(id.into()),
id: from_item_id(id.into()),
args: path
.segments
.last()
@ -568,13 +581,13 @@ impl FromWithTcx<clean::Import> for Import {
Simple(s) => Import {
source: import.source.path.whole_name(),
name: s.to_string(),
id: import.source.did.map(FakeDefId::from).map(from_def_id),
id: import.source.did.map(ItemId::from).map(from_item_id),
glob: false,
},
Glob => Import {
source: import.source.path.whole_name(),
name: import.source.path.last_name().to_string(),
id: import.source.did.map(FakeDefId::from).map(from_def_id),
id: import.source.did.map(ItemId::from).map(from_item_id),
glob: true,
},
}
@ -668,5 +681,5 @@ impl FromWithTcx<ItemType> for ItemKind {
}
fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_def_id(i.def_id)).collect()
items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
}

View file

@ -25,7 +25,7 @@ use crate::error::Error;
use crate::formats::cache::Cache;
use crate::formats::FormatRenderer;
use crate::html::render::cache::ExternalLocation;
use crate::json::conversions::{from_def_id, IntoWithTcx};
use crate::json::conversions::{from_item_id, IntoWithTcx};
#[derive(Clone)]
crate struct JsonRenderer<'tcx> {
@ -53,7 +53,7 @@ impl JsonRenderer<'tcx> {
.map(|i| {
let item = &i.impl_item;
self.item(item.clone()).unwrap();
from_def_id(item.def_id)
from_item_id(item.def_id)
})
.collect()
})
@ -71,7 +71,7 @@ impl JsonRenderer<'tcx> {
let item = &i.impl_item;
if item.def_id.is_local() {
self.item(item.clone()).unwrap();
Some(from_def_id(item.def_id))
Some(from_item_id(item.def_id))
} else {
None
}
@ -91,9 +91,9 @@ impl JsonRenderer<'tcx> {
let trait_item = &trait_item.trait_;
trait_item.items.clone().into_iter().for_each(|i| self.item(i).unwrap());
Some((
from_def_id(id.into()),
from_item_id(id.into()),
types::Item {
id: from_def_id(id.into()),
id: from_item_id(id.into()),
crate_id: id.krate.as_u32(),
name: self
.cache
@ -164,13 +164,13 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
let id = item.def_id;
if let Some(mut new_item) = self.convert_item(item) {
if let types::ItemEnum::Trait(ref mut t) = new_item.inner {
t.implementors = self.get_trait_implementors(id.expect_real())
t.implementors = self.get_trait_implementors(id.expect_def_id())
} else if let types::ItemEnum::Struct(ref mut s) = new_item.inner {
s.impls = self.get_impls(id.expect_real())
s.impls = self.get_impls(id.expect_def_id())
} else if let types::ItemEnum::Enum(ref mut e) = new_item.inner {
e.impls = self.get_impls(id.expect_real())
e.impls = self.get_impls(id.expect_def_id())
}
let removed = self.index.borrow_mut().insert(from_def_id(id), new_item.clone());
let removed = self.index.borrow_mut().insert(from_item_id(id), new_item.clone());
// FIXME(adotinthevoid): Currently, the index is duplicated. This is a sanity check
// to make sure the items are unique. The main place this happens is when an item, is
@ -207,7 +207,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
.chain(self.cache.external_paths.clone().into_iter())
.map(|(k, (path, kind))| {
(
from_def_id(k.into()),
from_item_id(k.into()),
types::ItemSummary {
crate_id: k.krate.as_u32(),
path,

View file

@ -213,13 +213,13 @@ impl<'a, 'b> fold::DocFolder for CoverageCalculator<'a, 'b> {
let filename = i.span(self.ctx.tcx).filename(self.ctx.sess());
let has_doc_example = tests.found_tests != 0;
// The `expect_real()` should be okay because `local_def_id_to_hir_id`
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
let hir_id = self
.ctx
.tcx
.hir()
.local_def_id_to_hir_id(i.def_id.expect_real().expect_local());
.local_def_id_to_hir_id(i.def_id.expect_def_id().expect_local());
let (level, source) = self.ctx.tcx.lint_level_at_node(MISSING_DOCS, hir_id);
// `missing_docs` is allow-by-default, so don't treat this as ignoring the item
// unless the user had an explicit `allow`

View file

@ -53,7 +53,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
return;
}
let local_id = match item.def_id.as_real().and_then(|x| x.as_local()) {
let local_id = match item.def_id.as_def_id().and_then(|x| x.as_local()) {
Some(id) => id,
// We don't need to check the syntax for other crates so returning
// without doing anything should not be a problem.
@ -137,7 +137,7 @@ impl<'a, 'tcx> DocFolder for SyntaxChecker<'a, 'tcx> {
let sp = item.attr_span(self.cx.tcx);
let extra = crate::html::markdown::ExtraInfo::new_did(
self.cx.tcx,
item.def_id.expect_real(),
item.def_id.expect_def_id(),
sp,
);
for code_block in markdown::rust_code_blocks(&dox, &extra) {

View file

@ -830,49 +830,48 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
fn fold_item(&mut self, item: Item) -> Option<Item> {
use rustc_middle::ty::DefIdTree;
let parent_node = if item.is_fake() {
None
} else {
find_nearest_parent_module(self.cx.tcx, item.def_id.expect_real())
};
let parent_node =
item.def_id.as_def_id().and_then(|did| find_nearest_parent_module(self.cx.tcx, did));
if parent_node.is_some() {
trace!("got parent node for {:?} {:?}, id {:?}", item.type_(), item.name, item.def_id);
}
// find item's parent to resolve `Self` in item's docs below
debug!("looking for the `Self` type");
let self_id = if item.is_fake() {
None
// Checking if the item is a field in an enum variant
} else if (matches!(self.cx.tcx.def_kind(item.def_id.expect_real()), DefKind::Field)
&& matches!(
self.cx.tcx.def_kind(self.cx.tcx.parent(item.def_id.expect_real()).unwrap()),
DefKind::Variant
))
{
self.cx
.tcx
.parent(item.def_id.expect_real())
.and_then(|item_id| self.cx.tcx.parent(item_id))
} else if matches!(
self.cx.tcx.def_kind(item.def_id.expect_real()),
DefKind::AssocConst
| DefKind::AssocFn
| DefKind::AssocTy
| DefKind::Variant
| DefKind::Field
) {
self.cx.tcx.parent(item.def_id.expect_real())
// HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
// Fixing this breaks `fn render_deref_methods`.
// As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
// regardless of what rustdoc wants to call it.
} else if let Some(parent) = self.cx.tcx.parent(item.def_id.expect_real()) {
let parent_kind = self.cx.tcx.def_kind(parent);
Some(if parent_kind == DefKind::Impl { parent } else { item.def_id.expect_real() })
} else {
Some(item.def_id.expect_real())
let self_id = match item.def_id.as_def_id() {
None => None,
Some(did)
if (matches!(self.cx.tcx.def_kind(did), DefKind::Field)
&& matches!(
self.cx.tcx.def_kind(self.cx.tcx.parent(did).unwrap()),
DefKind::Variant
)) =>
{
self.cx.tcx.parent(did).and_then(|item_id| self.cx.tcx.parent(item_id))
}
Some(did)
if matches!(
self.cx.tcx.def_kind(did),
DefKind::AssocConst
| DefKind::AssocFn
| DefKind::AssocTy
| DefKind::Variant
| DefKind::Field
) =>
{
self.cx.tcx.parent(did)
}
Some(did) => match self.cx.tcx.parent(did) {
// HACK(jynelson): `clean` marks associated types as `TypedefItem`, not as `AssocTypeItem`.
// Fixing this breaks `fn render_deref_methods`.
// As a workaround, see if the parent of the item is an `impl`; if so this must be an associated item,
// regardless of what rustdoc wants to call it.
Some(parent) => {
let parent_kind = self.cx.tcx.def_kind(parent);
Some(if parent_kind == DefKind::Impl { parent } else { did })
}
None => Some(did),
},
};
// FIXME(jynelson): this shouldn't go through stringification, rustdoc should just use the DefId directly
@ -897,7 +896,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
let inner_docs = item.inner_docs(self.cx.tcx);
if item.is_mod() && inner_docs {
self.mod_ids.push(item.def_id.expect_real());
self.mod_ids.push(item.def_id.expect_def_id());
}
// We want to resolve in the lexical scope of the documentation.
@ -924,7 +923,7 @@ impl<'a, 'tcx> DocFolder for LinkCollector<'a, 'tcx> {
Some(if item.is_mod() {
if !inner_docs {
self.mod_ids.push(item.def_id.expect_real());
self.mod_ids.push(item.def_id.expect_def_id());
}
let ret = self.fold_item_recur(item);
@ -1235,10 +1234,10 @@ impl LinkCollector<'_, '_> {
// item can be non-local e.g. when using #[doc(primitive = "pointer")]
if let Some((src_id, dst_id)) = id
.as_local()
// The `expect_real()` should be okay because `local_def_id_to_hir_id`
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
.and_then(|dst_id| {
item.def_id.expect_real().as_local().map(|src_id| (src_id, dst_id))
item.def_id.expect_def_id().as_local().map(|src_id| (src_id, dst_id))
})
{
let hir_src = self.cx.tcx.hir().local_def_id_to_hir_id(src_id);

View file

@ -136,10 +136,15 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
fn fold_item(&mut self, i: Item) -> Option<Item> {
if i.is_struct() || i.is_enum() || i.is_union() {
// FIXME(eddyb) is this `doc(hidden)` check needed?
if !self.cx.tcx.get_attrs(i.def_id.expect_real()).lists(sym::doc).has_word(sym::hidden)
if !self
.cx
.tcx
.get_attrs(i.def_id.expect_def_id())
.lists(sym::doc)
.has_word(sym::hidden)
{
self.impls
.extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_real()));
.extend(get_auto_trait_and_blanket_impls(self.cx, i.def_id.expect_def_id()));
}
}
@ -149,7 +154,7 @@ impl<'a, 'tcx> DocFolder for SyntheticImplCollector<'a, 'tcx> {
#[derive(Default)]
struct ItemCollector {
items: FxHashSet<FakeDefId>,
items: FxHashSet<ItemId>,
}
impl ItemCollector {
@ -168,7 +173,7 @@ impl DocFolder for ItemCollector {
struct BadImplStripper {
prims: FxHashSet<PrimitiveType>,
items: FxHashSet<FakeDefId>,
items: FxHashSet<ItemId>,
}
impl BadImplStripper {
@ -185,7 +190,7 @@ impl BadImplStripper {
}
}
fn keep_impl_with_def_id(&self, did: FakeDefId) -> bool {
fn keep_impl_with_def_id(&self, did: ItemId) -> bool {
self.items.contains(&did)
}
}

View file

@ -53,7 +53,7 @@ impl crate::doctest::Tester for Tests {
}
crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> bool {
if !cx.cache.access_levels.is_public(item.def_id.expect_real())
if !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
|| matches!(
*item.kind,
clean::StructFieldItem(_)
@ -71,9 +71,9 @@ crate fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) -> boo
{
return false;
}
// The `expect_real()` should be okay because `local_def_id_to_hir_id`
// The `expect_def_id()` should be okay because `local_def_id_to_hir_id`
// would presumably panic if a fake `DefIndex` were passed.
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_real().expect_local());
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(item.def_id.expect_def_id().expect_local());
if cx.tcx.hir().attrs(hir_id).lists(sym::doc).has_word(sym::hidden)
|| inherits_doc_hidden(cx.tcx, hir_id)
{
@ -107,7 +107,8 @@ crate fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item) {
|lint| lint.build("missing code example in this documentation").emit(),
);
}
} else if tests.found_tests > 0 && !cx.cache.access_levels.is_public(item.def_id.expect_real())
} else if tests.found_tests > 0
&& !cx.cache.access_levels.is_public(item.def_id.expect_def_id())
{
cx.tcx.struct_span_lint_hir(
crate::lint::PRIVATE_DOC_TESTS,

View file

@ -2,7 +2,7 @@ use rustc_span::symbol::sym;
use std::mem;
use crate::clean;
use crate::clean::{FakeDefIdSet, Item, NestedAttributesExt};
use crate::clean::{Item, ItemIdSet, NestedAttributesExt};
use crate::core::DocContext;
use crate::fold::{strip_item, DocFolder};
use crate::passes::{ImplStripper, Pass};
@ -15,7 +15,7 @@ crate const STRIP_HIDDEN: Pass = Pass {
/// Strip items marked `#[doc(hidden)]`
crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Crate {
let mut retained = FakeDefIdSet::default();
let mut retained = ItemIdSet::default();
// strip all #[doc(hidden)] items
let krate = {
@ -29,7 +29,7 @@ crate fn strip_hidden(krate: clean::Crate, _: &mut DocContext<'_>) -> clean::Cra
}
struct Stripper<'a> {
retained: &'a mut FakeDefIdSet,
retained: &'a mut ItemIdSet,
update_retained: bool,
}

View file

@ -1,4 +1,4 @@
use crate::clean::{self, FakeDefIdSet};
use crate::clean::{self, ItemIdSet};
use crate::core::DocContext;
use crate::fold::DocFolder;
use crate::passes::{ImplStripper, ImportStripper, Pass, Stripper};
@ -14,7 +14,7 @@ crate const STRIP_PRIVATE: Pass = Pass {
/// crate, specified by the `xcrate` flag.
crate fn strip_private(mut krate: clean::Crate, cx: &mut DocContext<'_>) -> clean::Crate {
// This stripper collects all *retained* nodes.
let mut retained = FakeDefIdSet::default();
let mut retained = ItemIdSet::default();
// strip all private items
{

View file

@ -2,11 +2,11 @@ use rustc_hir::def_id::DefId;
use rustc_middle::middle::privacy::AccessLevels;
use std::mem;
use crate::clean::{self, FakeDefIdSet, GetDefId, Item};
use crate::clean::{self, GetDefId, Item, ItemIdSet};
use crate::fold::{strip_item, DocFolder};
crate struct Stripper<'a> {
crate retained: &'a mut FakeDefIdSet,
crate retained: &'a mut ItemIdSet,
crate access_levels: &'a AccessLevels<DefId>,
crate update_retained: bool,
}
@ -42,7 +42,7 @@ impl<'a> DocFolder for Stripper<'a> {
| clean::TraitAliasItem(..)
| clean::ForeignTypeItem => {
if i.def_id.is_local() {
if !self.access_levels.is_exported(i.def_id.expect_real()) {
if !self.access_levels.is_exported(i.def_id.expect_def_id()) {
debug!("Stripper: stripping {:?} {:?}", i.type_(), i.name);
return None;
}
@ -116,7 +116,7 @@ impl<'a> DocFolder for Stripper<'a> {
/// This stripper discards all impls which reference stripped items
crate struct ImplStripper<'a> {
crate retained: &'a FakeDefIdSet,
crate retained: &'a ItemIdSet,
}
impl<'a> DocFolder for ImplStripper<'a> {