Skip to content

Commit 563ef23

Browse files
committed
Auto merge of #95899 - petrochenkov:modchild2, r=cjgillot
rustc_metadata: Do not encode unnecessary module children This should remove the syntax context shift and the special case for `ExternCrate` in decoder in #95880. This PR also shifts some work from decoding to encoding, which is typically useful for performance (but probably not much in this case). r? `@cjgillot`
2 parents 878c783 + 233fa65 commit 563ef23

File tree

4 files changed

+96
-71
lines changed

4 files changed

+96
-71
lines changed

compiler/rustc_data_structures/src/lib.rs

+25
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#![feature(control_flow_enum)]
1515
#![feature(core_intrinsics)]
1616
#![feature(extend_one)]
17+
#![feature(generator_trait)]
18+
#![feature(generators)]
1719
#![feature(let_else)]
1820
#![feature(hash_raw_entry)]
1921
#![feature(maybe_uninit_uninit_array)]
@@ -112,6 +114,9 @@ pub mod unhash;
112114
pub use ena::undo_log;
113115
pub use ena::unify;
114116

117+
use std::ops::{Generator, GeneratorState};
118+
use std::pin::Pin;
119+
115120
pub struct OnDrop<F: Fn()>(pub F);
116121

117122
impl<F: Fn()> OnDrop<F> {
@@ -130,6 +135,26 @@ impl<F: Fn()> Drop for OnDrop<F> {
130135
}
131136
}
132137

138+
struct IterFromGenerator<G>(G);
139+
140+
impl<G: Generator<Return = ()> + Unpin> Iterator for IterFromGenerator<G> {
141+
type Item = G::Yield;
142+
143+
fn next(&mut self) -> Option<Self::Item> {
144+
match Pin::new(&mut self.0).resume(()) {
145+
GeneratorState::Yielded(n) => Some(n),
146+
GeneratorState::Complete(_) => None,
147+
}
148+
}
149+
}
150+
151+
/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`.
152+
pub fn iter_from_generator<G: Generator<Return = ()> + Unpin>(
153+
generator: G,
154+
) -> impl Iterator<Item = G::Yield> {
155+
IterFromGenerator(generator)
156+
}
157+
133158
// See comments in src/librustc_middle/lib.rs
134159
#[doc(hidden)]
135160
pub fn __noop_fix_for_27438() {}

compiler/rustc_metadata/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
#![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
22
#![feature(crate_visibility_modifier)]
33
#![feature(drain_filter)]
4+
#![feature(generators)]
45
#![feature(let_else)]
56
#![feature(nll)]
67
#![feature(once_cell)]

compiler/rustc_metadata/src/rmeta/decoder.rs

+50-57
Original file line numberDiff line numberDiff line change
@@ -1089,63 +1089,32 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10891089
// Iterate over all children.
10901090
if let Some(children) = self.root.tables.children.get(self, id) {
10911091
for child_index in children.decode((self, sess)) {
1092-
if let Some(ident) = self.opt_item_ident(child_index, sess) {
1093-
let kind = self.def_kind(child_index);
1094-
let def_id = self.local_def_id(child_index);
1095-
let res = Res::Def(kind, def_id);
1096-
let vis = self.get_visibility(child_index);
1097-
let span = self.get_span(child_index, sess);
1098-
let macro_rules = match kind {
1099-
DefKind::Macro(..) => match self.kind(child_index) {
1100-
EntryKind::MacroDef(_, macro_rules) => macro_rules,
1101-
_ => unreachable!(),
1102-
},
1103-
_ => false,
1104-
};
1105-
1106-
callback(ModChild { ident, res, vis, span, macro_rules });
1107-
1108-
// For non-re-export structs and variants add their constructors to children.
1109-
// Re-export lists automatically contain constructors when necessary.
1110-
match kind {
1111-
DefKind::Struct => {
1112-
if let Some((ctor_def_id, ctor_kind)) =
1113-
self.get_ctor_def_id_and_kind(child_index)
1114-
{
1115-
let ctor_res =
1116-
Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
1117-
let vis = self.get_visibility(ctor_def_id.index);
1118-
callback(ModChild {
1119-
ident,
1120-
res: ctor_res,
1121-
vis,
1122-
span,
1123-
macro_rules: false,
1124-
});
1125-
}
1126-
}
1127-
DefKind::Variant => {
1128-
// Braced variants, unlike structs, generate unusable names in
1129-
// value namespace, they are reserved for possible future use.
1130-
// It's ok to use the variant's id as a ctor id since an
1131-
// error will be reported on any use of such resolution anyway.
1132-
let (ctor_def_id, ctor_kind) = self
1133-
.get_ctor_def_id_and_kind(child_index)
1134-
.unwrap_or((def_id, CtorKind::Fictive));
1092+
let ident = self.item_ident(child_index, sess);
1093+
let kind = self.def_kind(child_index);
1094+
let def_id = self.local_def_id(child_index);
1095+
let res = Res::Def(kind, def_id);
1096+
let vis = self.get_visibility(child_index);
1097+
let span = self.get_span(child_index, sess);
1098+
let macro_rules = match kind {
1099+
DefKind::Macro(..) => match self.kind(child_index) {
1100+
EntryKind::MacroDef(_, macro_rules) => macro_rules,
1101+
_ => unreachable!(),
1102+
},
1103+
_ => false,
1104+
};
1105+
1106+
callback(ModChild { ident, res, vis, span, macro_rules });
1107+
1108+
// For non-re-export structs and variants add their constructors to children.
1109+
// Re-export lists automatically contain constructors when necessary.
1110+
match kind {
1111+
DefKind::Struct => {
1112+
if let Some((ctor_def_id, ctor_kind)) =
1113+
self.get_ctor_def_id_and_kind(child_index)
1114+
{
11351115
let ctor_res =
1136-
Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
1137-
let mut vis = self.get_visibility(ctor_def_id.index);
1138-
if ctor_def_id == def_id && vis.is_public() {
1139-
// For non-exhaustive variants lower the constructor visibility to
1140-
// within the crate. We only need this for fictive constructors,
1141-
// for other constructors correct visibilities
1142-
// were already encoded in metadata.
1143-
let mut attrs = self.get_item_attrs(def_id.index, sess);
1144-
if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
1145-
let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
1146-
vis = ty::Visibility::Restricted(crate_def_id);
1147-
}
1148-
}
1116+
Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
1117+
let vis = self.get_visibility(ctor_def_id.index);
11491118
callback(ModChild {
11501119
ident,
11511120
res: ctor_res,
@@ -1154,8 +1123,32 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
11541123
macro_rules: false,
11551124
});
11561125
}
1157-
_ => {}
11581126
}
1127+
DefKind::Variant => {
1128+
// Braced variants, unlike structs, generate unusable names in
1129+
// value namespace, they are reserved for possible future use.
1130+
// It's ok to use the variant's id as a ctor id since an
1131+
// error will be reported on any use of such resolution anyway.
1132+
let (ctor_def_id, ctor_kind) = self
1133+
.get_ctor_def_id_and_kind(child_index)
1134+
.unwrap_or((def_id, CtorKind::Fictive));
1135+
let ctor_res =
1136+
Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id);
1137+
let mut vis = self.get_visibility(ctor_def_id.index);
1138+
if ctor_def_id == def_id && vis.is_public() {
1139+
// For non-exhaustive variants lower the constructor visibility to
1140+
// within the crate. We only need this for fictive constructors,
1141+
// for other constructors correct visibilities
1142+
// were already encoded in metadata.
1143+
let mut attrs = self.get_item_attrs(def_id.index, sess);
1144+
if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
1145+
let crate_def_id = self.local_def_id(CRATE_DEF_INDEX);
1146+
vis = ty::Visibility::Restricted(crate_def_id);
1147+
}
1148+
}
1149+
callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
1150+
}
1151+
_ => {}
11591152
}
11601153
}
11611154
}

compiler/rustc_metadata/src/rmeta/encoder.rs

+20-14
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::rmeta::*;
44

55
use rustc_data_structures::fingerprint::Fingerprint;
66
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
7+
use rustc_data_structures::iter_from_generator;
78
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
89
use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator};
910
use rustc_hir as hir;
@@ -1107,21 +1108,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
11071108
// Encode this here because we don't do it in encode_def_ids.
11081109
record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id));
11091110
} else {
1110-
let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index);
1111-
// Foreign items are planted into their parent modules from name resolution point of view.
1112-
let tcx = self.tcx;
1113-
let foreign_item_children = md
1114-
.item_ids
1115-
.iter()
1116-
.filter_map(|item_id| match tcx.hir().item(*item_id).kind {
1117-
hir::ItemKind::ForeignMod { items, .. } => {
1118-
Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index))
1111+
record!(self.tables.children[def_id] <- iter_from_generator(|| {
1112+
for item_id in md.item_ids {
1113+
match tcx.hir().item(*item_id).kind {
1114+
// Foreign items are planted into their parent modules
1115+
// from name resolution point of view.
1116+
hir::ItemKind::ForeignMod { items, .. } => {
1117+
for foreign_item in items {
1118+
yield foreign_item.id.def_id.local_def_index;
1119+
}
1120+
}
1121+
// Only encode named non-reexport children, reexports are encoded
1122+
// separately and unnamed items are not used by name resolution.
1123+
hir::ItemKind::ExternCrate(..) => continue,
1124+
_ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => {
1125+
yield item_id.def_id.local_def_index;
1126+
}
1127+
_ => continue,
11191128
}
1120-
_ => None,
1121-
})
1122-
.flatten();
1123-
1124-
record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children));
1129+
}
1130+
}));
11251131
}
11261132
}
11271133

0 commit comments

Comments
 (0)