Skip to content

Generate metadata by iterating on DefId instead of traversing the HIR tree 1/N #80919

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Jan 24, 2021
Merged
4 changes: 4 additions & 0 deletions compiler/rustc_hir/src/definitions.rs
Original file line number Diff line number Diff line change
@@ -419,6 +419,10 @@ impl Definitions {
pub fn add_parent_module_of_macro_def(&mut self, expn_id: ExpnId, module: DefId) {
self.parent_modules_of_macro_defs.insert(expn_id, module);
}

pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k)
}
}

#[derive(Copy, Clone, PartialEq, Debug)]
78 changes: 24 additions & 54 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
@@ -618,43 +618,6 @@ impl MetadataBlob {
}
}

impl EntryKind {
fn def_kind(&self) -> DefKind {
match *self {
EntryKind::AnonConst(..) => DefKind::AnonConst,
EntryKind::Const(..) => DefKind::Const,
EntryKind::AssocConst(..) => DefKind::AssocConst,
EntryKind::ImmStatic
| EntryKind::MutStatic
| EntryKind::ForeignImmStatic
| EntryKind::ForeignMutStatic => DefKind::Static,
EntryKind::Struct(_, _) => DefKind::Struct,
EntryKind::Union(_, _) => DefKind::Union,
EntryKind::Fn(_) | EntryKind::ForeignFn(_) => DefKind::Fn,
EntryKind::AssocFn(_) => DefKind::AssocFn,
EntryKind::Type => DefKind::TyAlias,
EntryKind::TypeParam => DefKind::TyParam,
EntryKind::ConstParam => DefKind::ConstParam,
EntryKind::OpaqueTy => DefKind::OpaqueTy,
EntryKind::AssocType(_) => DefKind::AssocTy,
EntryKind::Mod(_) => DefKind::Mod,
EntryKind::Variant(_) => DefKind::Variant,
EntryKind::Trait(_) => DefKind::Trait,
EntryKind::TraitAlias => DefKind::TraitAlias,
EntryKind::Enum(..) => DefKind::Enum,
EntryKind::MacroDef(_) => DefKind::Macro(MacroKind::Bang),
EntryKind::ProcMacro(kind) => DefKind::Macro(kind),
EntryKind::ForeignType => DefKind::ForeignTy,
EntryKind::Impl(_) => DefKind::Impl,
EntryKind::Closure => DefKind::Closure,
EntryKind::ForeignMod => DefKind::ForeignMod,
EntryKind::GlobalAsm => DefKind::GlobalAsm,
EntryKind::Field => DefKind::Field,
EntryKind::Generator(_) => DefKind::Generator,
}
}
}

impl CrateRoot<'_> {
crate fn is_proc_macro_crate(&self) -> bool {
self.proc_macro_data.is_some()
@@ -685,21 +648,6 @@ impl CrateRoot<'_> {
}

impl<'a, 'tcx> CrateMetadataRef<'a> {
fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
}

fn kind(&self, item_id: DefIndex) -> EntryKind {
self.maybe_kind(item_id).unwrap_or_else(|| {
bug!(
"CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
item_id,
self.root.name,
self.cnum,
)
})
}

fn raw_proc_macro(&self, id: DefIndex) -> &ProcMacro {
// DefIndex's in root.proc_macro_data have a one-to-one correspondence
// with items in 'raw_proc_macros'.
@@ -736,8 +684,30 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
self.try_item_ident(item_index, sess).unwrap()
}

fn def_kind(&self, index: DefIndex) -> DefKind {
self.kind(index).def_kind()
fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind> {
self.root.tables.kind.get(self, item_id).map(|k| k.decode(self))
}

fn kind(&self, item_id: DefIndex) -> EntryKind {
self.maybe_kind(item_id).unwrap_or_else(|| {
bug!(
"CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}",
item_id,
self.root.name,
self.cnum,
)
})
}

fn def_kind(&self, item_id: DefIndex) -> DefKind {
self.root.tables.def_kind.get(self, item_id).map(|k| k.decode(self)).unwrap_or_else(|| {
bug!(
"CrateMetadata::def_kind({:?}): id not found, in crate {:?} with number {}",
item_id,
self.root.name,
self.cnum,
)
})
}

fn get_span(&self, index: DefIndex, sess: &Session) -> Span {
2 changes: 1 addition & 1 deletion compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
Original file line number Diff line number Diff line change
@@ -130,7 +130,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
is_foreign_item => { cdata.is_foreign_item(def_id.index) }
static_mutability => { cdata.static_mutability(def_id.index) }
generator_kind => { cdata.generator_kind(def_id.index) }
def_kind => { cdata.def_kind(def_id.index) }
opt_def_kind => { Some(cdata.def_kind(def_id.index)) }
def_span => { cdata.get_span(def_id.index, &tcx.sess) }
def_ident_span => {
cdata.try_item_ident(def_id.index, &tcx.sess).ok().map(|ident| ident.span)
345 changes: 197 additions & 148 deletions compiler/rustc_metadata/src/rmeta/encoder.rs

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion compiler/rustc_metadata/src/rmeta/mod.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use rustc_attr as attr;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_hir as hir;
use rustc_hir::def::CtorKind;
use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{DefId, DefIndex, DefPathHash};
use rustc_hir::definitions::DefKey;
use rustc_hir::lang_items;
@@ -279,6 +279,7 @@ macro_rules! define_tables {
}

define_tables! {
def_kind: Table<DefIndex, Lazy<DefKind>>,
kind: Table<DefIndex, Lazy<EntryKind>>,
visibility: Table<DefIndex, Lazy<ty::Visibility>>,
span: Table<DefIndex, Lazy<Span>>,
100 changes: 54 additions & 46 deletions compiler/rustc_middle/src/hir/map/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use self::collector::NodeCollector;

use crate::hir::{Owner, OwnerNodes};
use crate::ty::query::Providers;
use crate::ty::TyCtxt;
use rustc_ast as ast;
use rustc_data_structures::svh::Svh;
@@ -183,14 +182,18 @@ impl<'hir> Map<'hir> {
self.tcx.definitions.opt_local_def_id_to_hir_id(def_id)
}

pub fn def_kind(&self, local_def_id: LocalDefId) -> DefKind {
pub fn iter_local_def_id(&self) -> impl Iterator<Item = LocalDefId> + '_ {
self.tcx.definitions.iter_local_def_id()
}

pub fn opt_def_kind(&self, local_def_id: LocalDefId) -> Option<DefKind> {
// FIXME(eddyb) support `find` on the crate root.
if local_def_id.to_def_id().index == CRATE_DEF_INDEX {
return DefKind::Mod;
return Some(DefKind::Mod);
}

let hir_id = self.local_def_id_to_hir_id(local_def_id);
match self.get(hir_id) {
let def_kind = match self.find(hir_id)? {
Node::Item(item) => match item.kind {
ItemKind::Static(..) => DefKind::Static,
ItemKind::Const(..) => DefKind::Const,
@@ -249,6 +252,7 @@ impl<'hir> Map<'hir> {
GenericParamKind::Type { .. } => DefKind::TyParam,
GenericParamKind::Const { .. } => DefKind::ConstParam,
},
Node::Crate(_) => DefKind::Mod,
Node::Stmt(_)
| Node::PathSegment(_)
| Node::Ty(_)
@@ -260,9 +264,14 @@ impl<'hir> Map<'hir> {
| Node::Arm(_)
| Node::Lifetime(_)
| Node::Visibility(_)
| Node::Block(_)
| Node::Crate(_) => bug!("def_kind: unsupported node: {}", self.node_to_string(hir_id)),
}
| Node::Block(_) => return None,
};
Some(def_kind)
}

pub fn def_kind(&self, local_def_id: LocalDefId) -> DefKind {
self.opt_def_kind(local_def_id)
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", local_def_id))
}

fn find_entry(&self, id: HirId) -> Option<Entry<'hir>> {
@@ -514,9 +523,7 @@ impl<'hir> Map<'hir> {

/// Retrieves the `Node` corresponding to `id`, returning `None` if cannot be found.
pub fn find(&self, hir_id: HirId) -> Option<Node<'hir>> {
self.find_entry(hir_id).and_then(|entry| {
if let Node::Crate(..) = entry.node { None } else { Some(entry.node) }
})
self.find_entry(hir_id).map(|entry| entry.node)
}

/// Similar to `get_parent`; returns the parent HIR Id, or just `hir_id` if there
@@ -848,50 +855,55 @@ impl<'hir> Map<'hir> {
/// Gets the span of the definition of the specified HIR node.
/// This is used by `tcx.get_span`
pub fn span(&self, hir_id: HirId) -> Span {
match self.find_entry(hir_id).map(|entry| entry.node) {
Some(Node::Param(param)) => param.span,
Some(Node::Item(item)) => match &item.kind {
self.opt_span(hir_id)
.unwrap_or_else(|| bug!("hir::map::Map::span: id not in map: {:?}", hir_id))
}

pub fn opt_span(&self, hir_id: HirId) -> Option<Span> {
let span = match self.find_entry(hir_id)?.node {
Node::Param(param) => param.span,
Node::Item(item) => match &item.kind {
ItemKind::Fn(sig, _, _) => sig.span,
_ => item.span,
},
Some(Node::ForeignItem(foreign_item)) => foreign_item.span,
Some(Node::TraitItem(trait_item)) => match &trait_item.kind {
Node::ForeignItem(foreign_item) => foreign_item.span,
Node::TraitItem(trait_item) => match &trait_item.kind {
TraitItemKind::Fn(sig, _) => sig.span,
_ => trait_item.span,
},
Some(Node::ImplItem(impl_item)) => match &impl_item.kind {
Node::ImplItem(impl_item) => match &impl_item.kind {
ImplItemKind::Fn(sig, _) => sig.span,
_ => impl_item.span,
},
Some(Node::Variant(variant)) => variant.span,
Some(Node::Field(field)) => field.span,
Some(Node::AnonConst(constant)) => self.body(constant.body).value.span,
Some(Node::Expr(expr)) => expr.span,
Some(Node::Stmt(stmt)) => stmt.span,
Some(Node::PathSegment(seg)) => seg.ident.span,
Some(Node::Ty(ty)) => ty.span,
Some(Node::TraitRef(tr)) => tr.path.span,
Some(Node::Binding(pat)) => pat.span,
Some(Node::Pat(pat)) => pat.span,
Some(Node::Arm(arm)) => arm.span,
Some(Node::Block(block)) => block.span,
Some(Node::Ctor(..)) => match self.find(self.get_parent_node(hir_id)) {
Some(Node::Item(item)) => item.span,
Some(Node::Variant(variant)) => variant.span,
Node::Variant(variant) => variant.span,
Node::Field(field) => field.span,
Node::AnonConst(constant) => self.body(constant.body).value.span,
Node::Expr(expr) => expr.span,
Node::Stmt(stmt) => stmt.span,
Node::PathSegment(seg) => seg.ident.span,
Node::Ty(ty) => ty.span,
Node::TraitRef(tr) => tr.path.span,
Node::Binding(pat) => pat.span,
Node::Pat(pat) => pat.span,
Node::Arm(arm) => arm.span,
Node::Block(block) => block.span,
Node::Ctor(..) => match self.find(self.get_parent_node(hir_id))? {
Node::Item(item) => item.span,
Node::Variant(variant) => variant.span,
_ => unreachable!(),
},
Some(Node::Lifetime(lifetime)) => lifetime.span,
Some(Node::GenericParam(param)) => param.span,
Some(Node::Visibility(&Spanned {
Node::Lifetime(lifetime) => lifetime.span,
Node::GenericParam(param) => param.span,
Node::Visibility(&Spanned {
node: VisibilityKind::Restricted { ref path, .. },
..
})) => path.span,
Some(Node::Visibility(v)) => bug!("unexpected Visibility {:?}", v),
Some(Node::Local(local)) => local.span,
Some(Node::MacroDef(macro_def)) => macro_def.span,
Some(Node::Crate(item)) => item.span,
None => bug!("hir::map::Map::span: id not in map: {:?}", hir_id),
}
}) => path.span,
Node::Visibility(v) => bug!("unexpected Visibility {:?}", v),
Node::Local(local) => local.span,
Node::MacroDef(macro_def) => macro_def.span,
Node::Crate(item) => item.span,
};
Some(span)
}

/// Like `hir.span()`, but includes the body of function items
@@ -907,7 +919,7 @@ impl<'hir> Map<'hir> {
}

pub fn span_if_local(&self, id: DefId) -> Option<Span> {
id.as_local().map(|id| self.span(self.local_def_id_to_hir_id(id)))
id.as_local().and_then(|id| self.opt_span(self.local_def_id_to_hir_id(id)))
}

pub fn res_span(&self, res: Res) -> Option<Span> {
@@ -1101,7 +1113,3 @@ fn hir_id_to_string(map: &Map<'_>, id: HirId) -> String {
None => format!("unknown node{}", id_str),
}
}

pub fn provide(providers: &mut Providers) {
providers.def_kind = |tcx, def_id| tcx.hir().def_kind(def_id.expect_local());
}
4 changes: 3 additions & 1 deletion compiler/rustc_middle/src/hir/mod.rs
Original file line number Diff line number Diff line change
@@ -15,6 +15,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_hir::def_id::{LocalDefId, LOCAL_CRATE};
use rustc_hir::*;
use rustc_index::vec::IndexVec;
use rustc_span::DUMMY_SP;

pub struct Owner<'tcx> {
parent: HirId,
@@ -77,6 +78,7 @@ pub fn provide(providers: &mut Providers) {
};
providers.hir_owner = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].signature;
providers.hir_owner_nodes = |tcx, id| tcx.index_hir(LOCAL_CRATE).map[id].with_bodies.as_deref();
providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP);
providers.fn_arg_names = |tcx, id| {
let hir = tcx.hir();
let hir_id = hir.local_def_id_to_hir_id(id.expect_local());
@@ -92,5 +94,5 @@ pub fn provide(providers: &mut Providers) {
span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
}
};
map::provide(providers);
providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id.expect_local());
}
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/query/mod.rs
Original file line number Diff line number Diff line change
@@ -878,7 +878,7 @@ rustc_queries! {
cache_on_disk_if { true }
}

query def_kind(def_id: DefId) -> DefKind {
query opt_def_kind(def_id: DefId) -> Option<DefKind> {
desc { |tcx| "looking up definition kind of `{}`", tcx.def_path_str(def_id) }
}

16 changes: 16 additions & 0 deletions compiler/rustc_middle/src/ty/query/mod.rs
Original file line number Diff line number Diff line change
@@ -130,3 +130,19 @@ mod sealed {
}

use sealed::IntoQueryParam;

impl TyCtxt<'tcx> {
pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
let def_id = def_id.into_query_param();
self.opt_def_kind(def_id)
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
}
}

impl TyCtxtAt<'tcx> {
pub fn def_kind(self, def_id: impl IntoQueryParam<DefId>) -> DefKind {
let def_id = def_id.into_query_param();
self.opt_def_kind(def_id)
.unwrap_or_else(|| bug!("def_kind: unsupported node: {:?}", def_id))
}
}
1 change: 1 addition & 0 deletions compiler/rustc_passes/src/reachable.rs
Original file line number Diff line number Diff line change
@@ -307,6 +307,7 @@ impl<'tcx> ReachableContext<'tcx> {
| Node::Ctor(..)
| Node::Field(_)
| Node::Ty(_)
| Node::Crate(_)
| Node::MacroDef(_) => {}
_ => {
bug!(
5 changes: 0 additions & 5 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -218,10 +218,6 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssociatedItems<'_> {
ty::AssociatedItems::new(items)
}

fn def_span(tcx: TyCtxt<'_>, def_id: DefId) -> Span {
tcx.hir().span_if_local(def_id).unwrap()
}

fn def_ident_span(tcx: TyCtxt<'_>, def_id: DefId) -> Option<Span> {
tcx.hir().get_if_local(def_id).and_then(|node| node.ident()).map(|ident| ident.span)
}
@@ -495,7 +491,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
associated_item_def_ids,
associated_items,
adt_sized_constraint,
def_span,
def_ident_span,
param_env,
param_env_reveal_all_normalized,
10 changes: 2 additions & 8 deletions src/test/ui/lint/lint-const-item-mutation.stderr
Original file line number Diff line number Diff line change
@@ -109,14 +109,8 @@ LL | VEC.push(0);
note: mutable reference created due to call to this method
--> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
|
LL | / pub fn push(&mut self, value: T) {
LL | | // This will panic or abort if we would allocate > isize::MAX bytes
LL | | // or if the length increment would overflow for zero-sized types.
LL | | if self.len == self.buf.capacity() {
... |
LL | | }
LL | | }
| |_____^
LL | pub fn push(&mut self, value: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: `const` item defined here
--> $DIR/lint-const-item-mutation.rs:31:1
|