Skip to content

Commit 96c6a50

Browse files
committed
rustc_metadata: Optimize and document module children decoding
1 parent 23ce5fc commit 96c6a50

File tree

5 files changed

+50
-38
lines changed

5 files changed

+50
-38
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+14-15
Original file line numberDiff line numberDiff line change
@@ -1075,15 +1075,16 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10751075
}
10761076
}
10771077

1078-
/// Iterates over each child of the given item.
1078+
/// Iterates over all named children of the given module,
1079+
/// including both proper items and reexports.
1080+
/// Module here is understood in name resolution sense - it can be a `mod` item,
1081+
/// or a crate root, or an enum, or a trait.
10791082
fn each_child_of_item(&self, id: DefIndex, mut callback: impl FnMut(Export), sess: &Session) {
10801083
if let Some(data) = &self.root.proc_macro_data {
1081-
/* If we are loading as a proc macro, we want to return the view of this crate
1082-
* as a proc macro crate.
1083-
*/
1084+
// If we are loading as a proc macro, we want to return
1085+
// the view of this crate as a proc macro crate.
10841086
if id == CRATE_DEF_INDEX {
1085-
let macros = data.macros.decode(self);
1086-
for def_index in macros {
1087+
for def_index in data.macros.decode(self) {
10871088
let raw_macro = self.raw_proc_macro(def_index);
10881089
let res = Res::Def(
10891090
DefKind::Macro(macro_kind(raw_macro)),
@@ -1096,12 +1097,6 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10961097
return;
10971098
}
10981099

1099-
// Find the item.
1100-
let kind = match self.maybe_kind(id) {
1101-
None => return,
1102-
Some(kind) => kind,
1103-
};
1104-
11051100
// Iterate over all children.
11061101
if let Some(children) = self.root.tables.children.get(self, id) {
11071102
for child_index in children.decode((self, sess)) {
@@ -1162,10 +1157,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
11621157
}
11631158
}
11641159

1165-
if let EntryKind::Mod(exports) = kind {
1166-
for exp in exports.decode((self, sess)) {
1167-
callback(exp);
1160+
match self.kind(id) {
1161+
EntryKind::Mod(exports) => {
1162+
for exp in exports.decode((self, sess)) {
1163+
callback(exp);
1164+
}
11681165
}
1166+
EntryKind::Enum(..) | EntryKind::Trait(..) => {}
1167+
_ => bug!("`each_child_of_item` is called on a non-module: {:?}", self.def_kind(id)),
11691168
}
11701169
}
11711170

compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use crate::native_libs;
44

55
use rustc_ast as ast;
66
use rustc_data_structures::stable_map::FxHashMap;
7-
use rustc_hir::def::{CtorKind, DefKind};
7+
use rustc_hir::def::{CtorKind, DefKind, Res};
88
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, CRATE_DEF_INDEX, LOCAL_CRATE};
99
use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
1010
use rustc_middle::hir::exports::Export;
@@ -309,28 +309,33 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
309309
bfs_queue.push_back(DefId { krate: cnum, index: CRATE_DEF_INDEX });
310310
}
311311

312-
let mut add_child = |bfs_queue: &mut VecDeque<_>, export: &Export, parent: DefId| {
313-
if !export.vis.is_public() {
312+
let mut add_child = |bfs_queue: &mut VecDeque<_>, child: &Export, parent: DefId| {
313+
if !child.vis.is_public() {
314314
return;
315315
}
316316

317-
if let Some(child) = export.res.opt_def_id() {
318-
if export.ident.name == kw::Underscore {
319-
fallback_map.insert(child, parent);
317+
if let Some(def_id) = child.res.opt_def_id() {
318+
if child.ident.name == kw::Underscore {
319+
fallback_map.insert(def_id, parent);
320320
return;
321321
}
322322

323-
match visible_parent_map.entry(child) {
323+
match visible_parent_map.entry(def_id) {
324324
Entry::Occupied(mut entry) => {
325325
// If `child` is defined in crate `cnum`, ensure
326326
// that it is mapped to a parent in `cnum`.
327-
if child.is_local() && entry.get().is_local() {
327+
if def_id.is_local() && entry.get().is_local() {
328328
entry.insert(parent);
329329
}
330330
}
331331
Entry::Vacant(entry) => {
332332
entry.insert(parent);
333-
bfs_queue.push_back(child);
333+
if matches!(
334+
child.res,
335+
Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, _)
336+
) {
337+
bfs_queue.push_back(def_id);
338+
}
334339
}
335340
}
336341
}

compiler/rustc_metadata/src/rmeta/encoder.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1104,7 +1104,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11041104

11051105
record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
11061106
if self.is_proc_macro {
1107-
record!(self.tables.children[def_id] <- &[]);
11081107
// Encode this here because we don't do it in encode_def_ids.
11091108
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
11101109
} else {

compiler/rustc_middle/src/ty/print/pretty.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -2615,7 +2615,9 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
26152615
collect_fn(&child.ident, ns, def_id);
26162616
}
26172617

2618-
if seen_defs.insert(def_id) {
2618+
if matches!(defkind, DefKind::Mod | DefKind::Enum | DefKind::Trait)
2619+
&& seen_defs.insert(def_id)
2620+
{
26192621
queue.push(def_id);
26202622
}
26212623
}

src/tools/clippy/clippy_utils/src/lib.rs

+19-12
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ use rustc_hir::{
8282
TraitItemKind, TraitRef, TyKind, UnOp, ArrayLen
8383
};
8484
use rustc_lint::{LateContext, Level, Lint, LintContext};
85-
use rustc_middle::hir::exports::Export;
8685
use rustc_middle::hir::map::Map;
8786
use rustc_middle::hir::place::PlaceBase;
8887
use rustc_middle::ty as rustc_ty;
@@ -523,10 +522,21 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
523522
}
524523
};
525524
}
526-
fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<&'tcx Export> {
527-
tcx.item_children(def_id)
528-
.iter()
529-
.find(|item| item.ident.name.as_str() == name)
525+
fn item_child_by_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, name: &str) -> Option<Res> {
526+
match tcx.def_kind(def_id) {
527+
DefKind::Mod | DefKind::Enum | DefKind::Trait => tcx
528+
.item_children(def_id)
529+
.iter()
530+
.find(|item| item.ident.name.as_str() == name)
531+
.map(|child| child.res.expect_non_local()),
532+
DefKind::Impl => tcx
533+
.associated_item_def_ids(def_id)
534+
.iter()
535+
.copied()
536+
.find(|assoc_def_id| tcx.item_name(*assoc_def_id).as_str() == name)
537+
.map(|assoc_def_id| Res::Def(tcx.def_kind(assoc_def_id), assoc_def_id)),
538+
_ => None,
539+
}
530540
}
531541

532542
let (krate, first, path) = match *path {
@@ -543,15 +553,12 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
543553
let last = path
544554
.iter()
545555
.copied()
546-
// `get_def_path` seems to generate these empty segments for extern blocks.
547-
// We can just ignore them.
548-
.filter(|segment| !segment.is_empty())
549556
// for each segment, find the child item
550-
.try_fold(first, |item, segment| {
551-
let def_id = item.res.def_id();
557+
.try_fold(first, |res, segment| {
558+
let def_id = res.def_id();
552559
if let Some(item) = item_child_by_name(tcx, def_id, segment) {
553560
Some(item)
554-
} else if matches!(item.res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
561+
} else if matches!(res, Res::Def(DefKind::Enum | DefKind::Struct, _)) {
555562
// it is not a child item so check inherent impl items
556563
tcx.inherent_impls(def_id)
557564
.iter()
@@ -560,7 +567,7 @@ pub fn path_to_res(cx: &LateContext<'_>, path: &[&str]) -> Res {
560567
None
561568
}
562569
});
563-
try_res!(last).res.expect_non_local()
570+
try_res!(last).expect_non_local()
564571
}
565572

566573
/// Convenience function to get the `DefId` of a trait by path.

0 commit comments

Comments
 (0)