Skip to content

Commit 813575f

Browse files
committed
rustc_metadata: Do not encode unnecessary module children
And add struct and variant constructors to module children at encoding time instead of decoding time
1 parent 52ca603 commit 813575f

File tree

9 files changed

+247
-181
lines changed

9 files changed

+247
-181
lines changed

compiler/rustc_data_structures/src/lib.rs

Lines changed: 25 additions & 0 deletions
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)]
@@ -113,6 +115,9 @@ pub mod unhash;
113115
pub use ena::undo_log;
114116
pub use ena::unify;
115117

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

118123
impl<F: Fn()> OnDrop<F> {
@@ -131,6 +136,26 @@ impl<F: Fn()> Drop for OnDrop<F> {
131136
}
132137
}
133138

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

compiler/rustc_metadata/src/lib.rs

Lines changed: 1 addition & 0 deletions
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

Lines changed: 44 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -836,7 +836,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
836836
}
837837

838838
fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> {
839-
self.def_key(item_index).disambiguated_data.data.get_opt_name()
839+
let def_key = self.def_key(item_index);
840+
def_key.disambiguated_data.data.get_opt_name().or_else(|| {
841+
if def_key.disambiguated_data.data == DefPathData::Ctor {
842+
let parent_index = def_key.parent.expect("no parent for a constructor");
843+
self.def_key(parent_index).disambiguated_data.data.get_opt_name()
844+
} else {
845+
None
846+
}
847+
})
840848
}
841849

842850
fn item_name(self, item_index: DefIndex) -> Symbol {
@@ -1089,73 +1097,43 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
10891097
// Iterate over all children.
10901098
if let Some(children) = self.root.tables.children.get(self, id) {
10911099
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));
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 {
1150-
ident,
1151-
res: ctor_res,
1152-
vis,
1153-
span,
1154-
macro_rules: false,
1155-
});
1100+
let ident = self.item_ident(child_index, sess);
1101+
let kind = self.def_kind(child_index);
1102+
let def_id = self.local_def_id(child_index);
1103+
let res = Res::Def(kind, def_id);
1104+
let vis = self.get_visibility(child_index);
1105+
let span = self.get_span(child_index, sess);
1106+
let macro_rules = match kind {
1107+
DefKind::Macro(..) => match self.kind(child_index) {
1108+
EntryKind::MacroDef(_, macro_rules) => macro_rules,
1109+
_ => unreachable!(),
1110+
},
1111+
_ => false,
1112+
};
1113+
1114+
callback(ModChild { ident, res, vis, span, macro_rules });
1115+
1116+
// For non-reexport variants add their fictive constructors to children.
1117+
// Braced variants, unlike structs, generate unusable names in value namespace,
1118+
// they are reserved for possible future use. It's ok to use the variant's id as
1119+
// a ctor id since an error will be reported on any use of such resolution anyway.
1120+
// Reexport lists automatically contain such constructors when necessary.
1121+
if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none()
1122+
{
1123+
let ctor_res =
1124+
Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id);
1125+
let mut vis = vis;
1126+
if vis.is_public() {
1127+
// For non-exhaustive variants lower the constructor visibility to
1128+
// within the crate. We only need this for fictive constructors,
1129+
// for other constructors correct visibilities
1130+
// were already encoded in metadata.
1131+
let mut attrs = self.get_item_attrs(def_id.index, sess);
1132+
if attrs.any(|item| item.has_name(sym::non_exhaustive)) {
1133+
vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX));
11561134
}
1157-
_ => {}
11581135
}
1136+
callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
11591137
}
11601138
}
11611139
}

compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 43 additions & 23 deletions
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,33 @@ 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+
hir::ItemKind::Struct(ref vdata, _) => {
1125+
yield item_id.def_id.local_def_index;
1126+
// Encode constructors which take a separate slot in value namespace.
1127+
if let Some(ctor_hir_id) = vdata.ctor_hir_id() {
1128+
yield tcx.hir().local_def_id(ctor_hir_id).local_def_index;
1129+
}
1130+
}
1131+
_ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => {
1132+
yield item_id.def_id.local_def_index;
1133+
}
1134+
_ => continue,
11191135
}
1120-
_ => None,
1121-
})
1122-
.flatten();
1123-
1124-
record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children));
1136+
}
1137+
}));
11251138
}
11261139
}
11271140

@@ -1493,12 +1506,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
14931506
record!(self.tables.kind[def_id] <- entry_kind);
14941507
// FIXME(eddyb) there should be a nicer way to do this.
14951508
match item.kind {
1496-
hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
1497-
self.tcx.adt_def(def_id).variants().iter().map(|v| {
1498-
assert!(v.def_id.is_local());
1499-
v.def_id.index
1500-
})
1501-
),
1509+
hir::ItemKind::Enum(..) => {
1510+
record!(self.tables.children[def_id] <- iter_from_generator(||
1511+
for variant in tcx.adt_def(def_id).variants() {
1512+
yield variant.def_id.index;
1513+
// Encode constructors which take a separate slot in value namespace.
1514+
if let Some(ctor_def_id) = variant.ctor_def_id {
1515+
yield ctor_def_id.index;
1516+
}
1517+
}
1518+
))
1519+
}
15021520
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
15031521
record!(self.tables.children[def_id] <-
15041522
self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
@@ -2011,8 +2029,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20112029
for (i, variant) in def.variants().iter_enumerated() {
20122030
self.encode_enum_variant_info(def, i);
20132031

2014-
if let Some(_ctor_def_id) = variant.ctor_def_id {
2032+
if let Some(ctor_def_id) = variant.ctor_def_id {
20152033
self.encode_enum_variant_ctor(def, i);
2034+
self.encode_ident_span(ctor_def_id, variant.ident(self.tcx));
20162035
}
20172036
}
20182037
}
@@ -2022,8 +2041,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
20222041

20232042
// If the struct has a constructor, encode it.
20242043
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
2025-
let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
2026-
self.encode_struct_ctor(def, ctor_def_id.to_def_id());
2044+
let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id).to_def_id();
2045+
self.encode_struct_ctor(def, ctor_def_id);
2046+
self.encode_ident_span(ctor_def_id, item.ident);
20272047
}
20282048
}
20292049
hir::ItemKind::Union(..) => {

0 commit comments

Comments
 (0)