mirror of
https://github.com/rust-lang/rust
synced 2024-10-22 00:14:09 +00:00
rustc_metadata: Optimize and document module children decoding
This commit is contained in:
parent
23ce5fc465
commit
96c6a50e96
|
@ -1075,15 +1075,16 @@ fn get_diagnostic_items(&self) -> DiagnosticItems {
|
|||
}
|
||||
}
|
||||
|
||||
/// Iterates over each child of the given item.
|
||||
/// Iterates over all named children of the given module,
|
||||
/// including both proper items and reexports.
|
||||
/// Module here is understood in name resolution sense - it can be a `mod` item,
|
||||
/// or a crate root, or an enum, or a trait.
|
||||
fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) {
|
||||
if let Some(data) = &self.root.proc_macro_data {
|
||||
/* If we are loading as a proc macro, we want to return the view of this crate
|
||||
* as a proc macro crate.
|
||||
*/
|
||||
// If we are loading as a proc macro, we want to return
|
||||
// the view of this crate as a proc macro crate.
|
||||
if id == CRATE_DEF_INDEX {
|
||||
let macros = data.macros.decode(self);
|
||||
for def_index in macros {
|
||||
for def_index in data.macros.decode(self) {
|
||||
let raw_macro = self.raw_proc_macro(def_index);
|
||||
let res = Res::Def(
|
||||
DefKind::Macro(macro_kind(raw_macro)),
|
||||
|
@ -1096,12 +1097,6 @@ fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), ses
|
|||
return;
|
||||
}
|
||||
|
||||
// Find the item.
|
||||
let kind = match self.maybe_kind(id) {
|
||||
None => return,
|
||||
Some(kind) => kind,
|
||||
};
|
||||
|
||||
// Iterate over all children.
|
||||
if let Some(children) = self.root.tables.children.get(self, id) {
|
||||
for child_index in children.decode((self, sess)) {
|
||||
|
@ -1162,10 +1157,14 @@ fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), ses
|
|||
}
|
||||
}
|
||||
|
||||
if let EntryKind::Mod(exports) = kind {
|
||||
for exp in exports.decode((self, sess)) {
|
||||
callback(exp);
|
||||
match self.kind(id) {
|
||||
EntryKind::Mod(exports) => {
|
||||
for exp in exports.decode((self, sess)) {
|
||||
callback(exp);
|
||||
}
|
||||
}
|
||||
EntryKind::Enum(..) | EntryKind::Trait(..) => {}
|
||||
_ => bug!("`each_child_of_item` is called on a non-module: {:?}", self.def_kind(id)),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::stable_map::FxHashMap;
|
||||
use rustc_hir::def::{CtorKind, DefKind};
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
|
||||
use rustc_middle::hir::exports::Export;
|
||||
|
@ -309,28 +309,33 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
|
|||
bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX });
|
||||
}
|
||||
|
||||
let mut add_child = |bfs_queue: &mut VecDeque<_>, export: &Export, parent: DefId| {
|
||||
if !export.vis.is_public() {
|
||||
let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
|
||||
if !child.vis.is_public() {
|
||||
return;
|
||||
}
|
||||
|
||||
if let Some(child) = export.res.opt_def_id() {
|
||||
if export.ident.name == kw::Underscore {
|
||||
fallback_map.insert(child, parent);
|
||||
if let Some(def_id) = child.res.opt_def_id() {
|
||||
if child.ident.name == kw::Underscore {
|
||||
fallback_map.insert(def_id, parent);
|
||||
return;
|
||||
}
|
||||
|
||||
match visible_parent_map.entry(child) {
|
||||
match visible_parent_map.entry(def_id) {
|
||||
Entry::Occupied(mut entry) => {
|
||||
// If `child` is defined in crate `cnum`, ensure
|
||||
// that it is mapped to a parent in `cnum`.
|
||||
if child.is_local() && entry.get().is_local() {
|
||||
if def_id.is_local() && entry.get().is_local() {
|
||||
entry.insert(parent);
|
||||
}
|
||||
}
|
||||
Entry::Vacant(entry) => {
|
||||
entry.insert(parent);
|
||||
bfs_queue.push_back(child);
|
||||
if matches!(
|
||||
child.res,
|
||||
Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, _)
|
||||
) {
|
||||
bfs_queue.push_back(def_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1104,7 +1104,6 @@ fn encode_info_for_mod(&mut self, local_def_id: LocalDefId, md: &hir::Mod<'_>) {
|
|||
|
||||
record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
|
||||
if self.is_proc_macro {
|
||||
record!(self.tables.children[def_id] <- &[]);
|
||||
// Encode this here because we don't do it in encode_def_ids.
|
||||
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
|
||||
} else {
|
||||
|
|
|
@ -2615,7 +2615,9 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
|
|||
collect_fn(&child.ident, ns, def_id);
|
||||
}
|
||||
|
||||
if seen_defs.insert(def_id) {
|
||||
if matches!(defkind, DefKind::Mod | DefKind::Enum | DefKind::Trait)
|
||||
&& seen_defs.insert(def_id)
|
||||
{
|
||||
queue.push(def_id);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,6 @@
|
|||
TraitItemKind, TraitRef, TyKind, UnOp, ArrayLen
|
||||
};
|
||||
use rustc_lint::{LateContext, Level, Lint, LintContext};
|
||||
use rustc_middle::hir::exports::Export;
|
||||
use rustc_middle::hir::map::Map;
|
||||
use rustc_middle::hir::place::PlaceBase;
|
||||
use rustc_middle::ty as rustc_ty;
|
||||
|
@ -523,10 +522,21 @@ macro_rules! try_res {
|
|||
}
|
||||
};
|
||||
}
|
||||
fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> {
|
||||
tcx.item_children(def_id)
|
||||
.iter()
|
||||
.find(|item| item.ident.name.as_str() == name)
|
||||
fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<Res> {
|
||||
match tcx.def_kind(def_id) {
|
||||
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
|
||||
.item_children(def_id)
|
||||
.iter()
|
||||
.find(|item| item.ident.name.as_str() == name)
|
||||
.map(|child| child.res.expect_non_local()),
|
||||
DefKind::Impl => tcx
|
||||
.associated_item_def_ids(def_id)
|
||||
.iter()
|
||||
.copied()
|
||||
.find(|assoc_def_id| tcx.item_name(*assoc_def_id).as_str() == name)
|
||||
.map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
let (krate, first, path) = match *path {
|
||||
|
@ -543,15 +553,12 @@ fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Opt
|
|||
let last = path
|
||||
.iter()
|
||||
.copied()
|
||||
// `get_def_path` seems to generate these empty segments for extern blocks.
|
||||
// We can just ignore them.
|
||||
.filter(|segment| !segment.is_empty())
|
||||
// for each segment, find the child item
|
||||
.try_fold(first, |item, segment| {
|
||||
let def_id = item.res.def_id();
|
||||
.try_fold(first, |res, segment| {
|
||||
let def_id = res.def_id();
|
||||
if let Some(item) = item_child_by_name(tcx, def_id, segment) {
|
||||
Some(item)
|
||||
} else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
|
||||
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
|
||||
// it is not a child item so check inherent impl items
|
||||
tcx.inherent_impls(def_id)
|
||||
.iter()
|
||||
|
@ -560,7 +567,7 @@ fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Opt
|
|||
None
|
||||
}
|
||||
});
|
||||
try_res!(last).res.expect_non_local()
|
||||
try_res!(last).expect_non_local()
|
||||
}
|
||||
|
||||
/// Convenience function to get the `DefId` of a trait by path.
|
||||
|
|
Loading…
Reference in a new issue