Skip to content

Commit 7bd38c9

Browse files
committed
rustc_metadata: Switch each_child_of_item from callback to iterator
to avoid allocations.
1 parent d981633 commit 7bd38c9

File tree

4 files changed

+114
-123
lines changed

4 files changed

+114
-123
lines changed

compiler/rustc_metadata/src/rmeta/decoder.rs

+103-109
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ use rustc_span::symbol::{sym, Ident, Symbol};
4141
use rustc_span::{self, BytePos, ExpnId, Pos, Span, SyntaxContext, DUMMY_SP};
4242

4343
use proc_macro::bridge::client::ProcMacro;
44-
use std::io;
45-
use std::mem;
44+
use smallvec::SmallVec;
4645
use std::num::NonZeroUsize;
4746
use std::path::Path;
47+
use std::{io, iter, mem};
4848
use tracing::debug;
4949

5050
pub(super) use cstore_impl::provide;
@@ -1000,7 +1000,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10001000
.map(|index| self.get_variant(&self.kind(index), index, did))
10011001
.collect()
10021002
} else {
1003-
std::iter::once(self.get_variant(&kind, item_id, did)).collect()
1003+
iter::once(self.get_variant(&kind, item_id, did)).collect()
10041004
};
10051005

10061006
tcx.alloc_adt_def(did, adt_kind, variants, repr)
@@ -1055,118 +1055,122 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10551055
/// including both proper items and reexports.
10561056
/// Module here is understood in name resolution sense - it can be a `mod` item,
10571057
/// or a crate root, or an enum, or a trait.
1058-
fn for_each_module_child(
1058+
fn get_module_children(
10591059
self,
10601060
id: DefIndex,
1061-
mut callback: impl FnMut(ModChild),
1062-
sess: &Session,
1063-
) {
1064-
if let Some(data) = &self.root.proc_macro_data {
1065-
// If we are loading as a proc macro, we want to return
1066-
// the view of this crate as a proc macro crate.
1067-
if id == CRATE_DEF_INDEX {
1068-
for def_index in data.macros.decode(self) {
1069-
let raw_macro = self.raw_proc_macro(def_index);
1070-
let res = Res::Def(
1071-
DefKind::Macro(macro_kind(raw_macro)),
1072-
self.local_def_id(def_index),
1073-
);
1074-
let ident = self.item_ident(def_index, sess);
1075-
callback(ModChild {
1076-
ident,
1077-
res,
1078-
vis: ty::Visibility::Public,
1079-
span: ident.span,
1080-
macro_rules: false,
1081-
});
1082-
}
1061+
sess: &'a Session,
1062+
) -> impl Iterator<Item = ModChild> + 'a {
1063+
// If we are loading as a proc macro, we want to return
1064+
// the view of this crate as a proc macro crate.
1065+
let is_proc_macro = self.root.proc_macro_data.is_some();
1066+
let proc_macros = match &self.root.proc_macro_data {
1067+
Some(data) if id == CRATE_DEF_INDEX => data.macros,
1068+
_ => Lazy::empty(),
1069+
};
1070+
let proc_macros = proc_macros.decode(self).map(move |def_index| {
1071+
let ident = self.item_ident(def_index, sess);
1072+
let macro_kind = match self.raw_proc_macro(def_index) {
1073+
ProcMacro::CustomDerive { .. } => MacroKind::Derive,
1074+
ProcMacro::Attr { .. } => MacroKind::Attr,
1075+
ProcMacro::Bang { .. } => MacroKind::Bang,
1076+
};
1077+
ModChild {
1078+
ident,
1079+
res: Res::Def(DefKind::Macro(macro_kind), self.local_def_id(def_index)),
1080+
vis: ty::Visibility::Public,
1081+
span: ident.span,
1082+
macro_rules: false,
10831083
}
1084-
return;
1085-
}
1084+
});
10861085

10871086
// Iterate over all children.
1088-
if let Some(children) = self.root.tables.children.get(self, id) {
1089-
for child_index in children.decode((self, sess)) {
1090-
if let Some(ident) = self.opt_item_ident(child_index, sess) {
1091-
let kind = self.def_kind(child_index);
1092-
let def_id = self.local_def_id(child_index);
1093-
let res = Res::Def(kind, def_id);
1094-
let vis = self.get_visibility(child_index);
1095-
let span = self.get_span(child_index, sess);
1096-
let macro_rules = match kind {
1097-
DefKind::Macro(..) => match self.kind(child_index) {
1098-
EntryKind::MacroDef(_, macro_rules) => macro_rules,
1099-
_ => unreachable!(),
1100-
},
1101-
_ => false,
1102-
};
1103-
1104-
callback(ModChild { ident, res, vis, span, macro_rules });
1105-
1106-
// For non-re-export structs and variants add their constructors to children.
1107-
// Re-export lists automatically contain constructors when necessary.
1108-
match kind {
1109-
DefKind::Struct => {
1110-
if let Some((ctor_def_id, ctor_kind)) =
1111-
self.get_ctor_def_id_and_kind(child_index)
1112-
{
1113-
let ctor_res =
1114-
Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
1115-
let vis = self.get_visibility(ctor_def_id.index);
1116-
callback(ModChild {
1117-
ident,
1118-
res: ctor_res,
1119-
vis,
1120-
span,
1121-
macro_rules: false,
1122-
});
1123-
}
1124-
}
1125-
DefKind::Variant => {
1126-
// Braced variants, unlike structs, generate unusable names in
1127-
// value namespace, they are reserved for possible future use.
1128-
// It's ok to use the variant's id as a ctor id since an
1129-
// error will be reported on any use of such resolution anyway.
1130-
let (ctor_def_id, ctor_kind) = self
1131-
.get_ctor_def_id_and_kind(child_index)
1132-
.unwrap_or((def_id, CtorKind::Fictive));
1087+
let proper_items = match self.root.tables.children.get(self, id) {
1088+
Some(children) if !is_proc_macro => children,
1089+
_ => Lazy::empty(),
1090+
};
1091+
let proper_items = proper_items.decode((self, sess)).map(move |child_index| {
1092+
let mut result = SmallVec::<[_; 2]>::new();
1093+
1094+
if let Some(ident) = self.opt_item_ident(child_index, sess) {
1095+
let kind = self.def_kind(child_index);
1096+
let def_id = self.local_def_id(child_index);
1097+
let res = Res::Def(kind, def_id);
1098+
let vis = self.get_visibility(child_index);
1099+
let span = self.get_span(child_index, sess);
1100+
let macro_rules = match kind {
1101+
DefKind::Macro(..) => match self.kind(child_index) {
1102+
EntryKind::MacroDef(_, macro_rules) => macro_rules,
1103+
_ => unreachable!(),
1104+
},
1105+
_ => false,
1106+
};
1107+
1108+
result.push(ModChild { ident, res, vis, span, macro_rules });
1109+
1110+
// For non-re-export structs and variants add their constructors to children.
1111+
// Re-export lists automatically contain constructors when necessary.
1112+
match kind {
1113+
DefKind::Struct => {
1114+
if let Some((ctor_def_id, ctor_kind)) =
1115+
self.get_ctor_def_id_and_kind(child_index)
1116+
{
11331117
let ctor_res =
1134-
Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
1135-
let mut vis = self.get_visibility(ctor_def_id.index);
1136-
if ctor_def_id == def_id && vis.is_public() {
1137-
// For non-exhaustive variants lower the constructor visibility to
1138-
// within the crate. We only need this for fictive constructors,
1139-
// for other constructors correct visibilities
1140-
// were already encoded in metadata.
1141-
let mut attrs = self.get_item_attrs(def_id.index, sess);
1142-
if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
1143-
let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
1144-
vis = ty::Visibility::Restricted(crate_def_id);
1145-
}
1146-
}
1147-
callback(ModChild {
1118+
Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
1119+
let vis = self.get_visibility(ctor_def_id.index);
1120+
result.push(ModChild {
11481121
ident,
11491122
res: ctor_res,
11501123
vis,
11511124
span,
11521125
macro_rules: false,
11531126
});
11541127
}
1155-
_ => {}
11561128
}
1129+
DefKind::Variant => {
1130+
// Braced variants, unlike structs, generate unusable names in
1131+
// value namespace, they are reserved for possible future use.
1132+
// It's ok to use the variant's id as a ctor id since an
1133+
// error will be reported on any use of such resolution anyway.
1134+
let (ctor_def_id, ctor_kind) = self
1135+
.get_ctor_def_id_and_kind(child_index)
1136+
.unwrap_or((def_id, CtorKind::Fictive));
1137+
let ctor_res =
1138+
Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
1139+
let mut vis = self.get_visibility(ctor_def_id.index);
1140+
if ctor_def_id == def_id && vis.is_public() {
1141+
// For non-exhaustive variants lower the constructor visibility to
1142+
// within the crate. We only need this for fictive constructors,
1143+
// for other constructors correct visibilities
1144+
// were already encoded in metadata.
1145+
let mut attrs = self.get_item_attrs(def_id.index, sess);
1146+
if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
1147+
let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
1148+
vis = ty::Visibility::Restricted(crate_def_id);
1149+
}
1150+
}
1151+
result.push(ModChild {
1152+
ident,
1153+
res: ctor_res,
1154+
vis,
1155+
span,
1156+
macro_rules: false,
1157+
});
1158+
}
1159+
_ => {}
11571160
}
1158-
}
1159-
}
1161+
};
11601162

1161-
match self.kind(id) {
1162-
EntryKind::Mod(exports) => {
1163-
for exp in exports.decode((self, sess)) {
1164-
callback(exp);
1165-
}
1166-
}
1167-
EntryKind::Enum(..) | EntryKind::Trait(..) => {}
1168-
_ => bug!("`for_each_module_child` is called on a non-module: {:?}", self.def_kind(id)),
1169-
}
1163+
result
1164+
});
1165+
1166+
let exports = match self.kind(id) {
1167+
EntryKind::Mod(exports) if !is_proc_macro => exports,
1168+
EntryKind::Mod(..) | EntryKind::Enum(..) | EntryKind::Trait(..) => Lazy::empty(),
1169+
_ => bug!("`get_module_children` is called on a non-module: {:?}", self.def_kind(id)),
1170+
};
1171+
let exports = exports.decode((self, sess));
1172+
1173+
proc_macros.chain(proper_items.flatten()).chain(exports)
11701174
}
11711175

11721176
fn is_ctfe_mir_available(self, id: DefIndex) -> bool {
@@ -1878,13 +1882,3 @@ impl CrateMetadata {
18781882
None
18791883
}
18801884
}
1881-
1882-
// Cannot be implemented on 'ProcMacro', as libproc_macro
1883-
// does not depend on librustc_ast
1884-
fn macro_kind(raw: &ProcMacro) -> MacroKind {
1885-
match raw {
1886-
ProcMacro::CustomDerive { .. } => MacroKind::Derive,
1887-
ProcMacro::Attr { .. } => MacroKind::Attr,
1888-
ProcMacro::Bang { .. } => MacroKind::Bang,
1889-
}
1890-
}

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

+7-12
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use rustc_span::source_map::{Span, Spanned};
2020
use rustc_span::symbol::{kw, Symbol};
2121

2222
use rustc_data_structures::sync::Lrc;
23-
use smallvec::SmallVec;
2423
use std::any::Any;
2524

2625
macro_rules! provide_one {
@@ -205,9 +204,7 @@ provide! { <'tcx> tcx, def_id, other, cdata,
205204
r
206205
}
207206
module_children => {
208-
let mut result = SmallVec::<[_; 8]>::new();
209-
cdata.for_each_module_child(def_id.index, |child| result.push(child), tcx.sess);
210-
tcx.arena.alloc_slice(&result)
207+
tcx.arena.alloc_from_iter(cdata.get_module_children(def_id.index, tcx.sess))
211208
}
212209
defined_lib_features => { cdata.get_lib_features(tcx) }
213210
defined_lang_items => { tcx.arena.alloc_from_iter(cdata.get_lang_items()) }
@@ -400,14 +397,12 @@ impl CStore {
400397
self.get_crate_data(def.krate).get_visibility(def.index)
401398
}
402399

403-
pub fn module_children_untracked(&self, def_id: DefId, sess: &Session) -> Vec<ModChild> {
404-
let mut result = vec![];
405-
self.get_crate_data(def_id.krate).for_each_module_child(
406-
def_id.index,
407-
|child| result.push(child),
408-
sess,
409-
);
410-
result
400+
pub fn module_children_untracked<'a>(
401+
&'a self,
402+
def_id: DefId,
403+
sess: &'a Session,
404+
) -> impl Iterator<Item = ModChild> + 'a {
405+
self.get_crate_data(def_id.krate).get_module_children(def_id.index, sess)
411406
}
412407

413408
pub fn load_macro_untracked(&self, id: DefId, sess: &Session) -> LoadedMacro {

compiler/rustc_resolve/src/build_reduced_graph.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,9 @@ impl<'a> Resolver<'a> {
214214
}
215215

216216
crate fn build_reduced_graph_external(&mut self, module: Module<'a>) {
217-
for child in self.cstore().module_children_untracked(module.def_id(), self.session) {
217+
for child in
218+
Vec::from_iter(self.cstore().module_children_untracked(module.def_id(), self.session))
219+
{
218220
let parent_scope = ParentScope::module(module, self);
219221
BuildReducedGraphVisitor { r: self, parent_scope }
220222
.build_reduced_graph_for_external_crate_res(child);

compiler/rustc_resolve/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -3421,7 +3421,7 @@ impl<'a> Resolver<'a> {
34213421
if let Some(def_id) = def_id.as_local() {
34223422
self.reexport_map.get(&def_id).cloned().unwrap_or_default()
34233423
} else {
3424-
self.cstore().module_children_untracked(def_id, self.session)
3424+
self.cstore().module_children_untracked(def_id, self.session).collect()
34253425
}
34263426
}
34273427

0 commit comments

Comments
 (0)