From 233fa659f455e84cdf5ba74d8cda6e9fb3f6245b Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 10 Apr 2022 22:15:09 +0300 Subject: [PATCH] rustc_metadata: Do not encode unnecessary module children --- compiler/rustc_data_structures/src/lib.rs | 25 +++++ compiler/rustc_metadata/src/lib.rs | 1 + compiler/rustc_metadata/src/rmeta/decoder.rs | 103 +++++++++---------- compiler/rustc_metadata/src/rmeta/encoder.rs | 34 +++--- 4 files changed, 94 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 1a3fe652521..47d7d9a1c71 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -14,6 +14,8 @@ #![feature(control_flow_enum)] #![feature(core_intrinsics)] #![feature(extend_one)] +#![feature(generator_trait)] +#![feature(generators)] #![feature(let_else)] #![feature(hash_raw_entry)] #![feature(maybe_uninit_uninit_array)] @@ -113,6 +115,9 @@ pub mod unhash; pub use ena::undo_log; pub use ena::unify; +use std::ops::{Generator, GeneratorState}; +use std::pin::Pin; + pub struct OnDrop(pub F); impl OnDrop { @@ -131,6 +136,26 @@ impl Drop for OnDrop { } } +struct IterFromGenerator(G); + +impl + Unpin> Iterator for IterFromGenerator { + type Item = G::Yield; + + fn next(&mut self) -> Option { + match Pin::new(&mut self.0).resume(()) { + GeneratorState::Yielded(n) => Some(n), + GeneratorState::Complete(_) => None, + } + } +} + +/// An adapter for turning a generator closure into an iterator, similar to `iter::from_fn`. +pub fn iter_from_generator + Unpin>( + generator: G, +) -> impl Iterator { + IterFromGenerator(generator) +} + // See comments in src/librustc_middle/lib.rs #[doc(hidden)] pub fn __noop_fix_for_27438() {} diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index aebd293f6c2..dfed9dd15a7 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,6 +1,7 @@ #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] #![feature(crate_visibility_modifier)] #![feature(drain_filter)] +#![feature(generators)] #![feature(let_else)] #![feature(nll)] #![feature(once_cell)] diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 3933a0d19a4..c35054dab2a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1089,63 +1089,32 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { // Iterate over all children. if let Some(children) = self.root.tables.children.get(self, id) { for child_index in children.decode((self, sess)) { - if let Some(ident) = self.opt_item_ident(child_index, sess) { - let kind = self.def_kind(child_index); - let def_id = self.local_def_id(child_index); - let res = Res::Def(kind, def_id); - let vis = self.get_visibility(child_index); - let span = self.get_span(child_index, sess); - let macro_rules = match kind { - DefKind::Macro(..) => match self.kind(child_index) { - EntryKind::MacroDef(_, macro_rules) => macro_rules, - _ => unreachable!(), - }, - _ => false, - }; + let ident = self.item_ident(child_index, sess); + let kind = self.def_kind(child_index); + let def_id = self.local_def_id(child_index); + let res = Res::Def(kind, def_id); + let vis = self.get_visibility(child_index); + let span = self.get_span(child_index, sess); + let macro_rules = match kind { + DefKind::Macro(..) => match self.kind(child_index) { + EntryKind::MacroDef(_, macro_rules) => macro_rules, + _ => unreachable!(), + }, + _ => false, + }; - callback(ModChild { ident, res, vis, span, macro_rules }); + callback(ModChild { ident, res, vis, span, macro_rules }); - // For non-re-export structs and variants add their constructors to children. - // Re-export lists automatically contain constructors when necessary. - match kind { - DefKind::Struct => { - if let Some((ctor_def_id, ctor_kind)) = - self.get_ctor_def_id_and_kind(child_index) - { - let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); - let vis = self.get_visibility(ctor_def_id.index); - callback(ModChild { - ident, - res: ctor_res, - vis, - span, - macro_rules: false, - }); - } - } - DefKind::Variant => { - // Braced variants, unlike structs, generate unusable names in - // value namespace, they are reserved for possible future use. - // It's ok to use the variant's id as a ctor id since an - // error will be reported on any use of such resolution anyway. - let (ctor_def_id, ctor_kind) = self - .get_ctor_def_id_and_kind(child_index) - .unwrap_or((def_id, CtorKind::Fictive)); + // For non-re-export structs and variants add their constructors to children. + // Re-export lists automatically contain constructors when necessary. + match kind { + DefKind::Struct => { + if let Some((ctor_def_id, ctor_kind)) = + self.get_ctor_def_id_and_kind(child_index) + { let ctor_res = - Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); - let mut vis = self.get_visibility(ctor_def_id.index); - if ctor_def_id == def_id && vis.is_public() { - // For non-exhaustive variants lower the constructor visibility to - // within the crate. We only need this for fictive constructors, - // for other constructors correct visibilities - // were already encoded in metadata. - let mut attrs = self.get_item_attrs(def_id.index, sess); - if attrs.any(|item| item.has_name(sym::non_exhaustive)) { - let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); - vis = ty::Visibility::Restricted(crate_def_id); - } - } + Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id); + let vis = self.get_visibility(ctor_def_id.index); callback(ModChild { ident, res: ctor_res, @@ -1154,8 +1123,32 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { macro_rules: false, }); } - _ => {} } + DefKind::Variant => { + // Braced variants, unlike structs, generate unusable names in + // value namespace, they are reserved for possible future use. + // It's ok to use the variant's id as a ctor id since an + // error will be reported on any use of such resolution anyway. + let (ctor_def_id, ctor_kind) = self + .get_ctor_def_id_and_kind(child_index) + .unwrap_or((def_id, CtorKind::Fictive)); + let ctor_res = + Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id); + let mut vis = self.get_visibility(ctor_def_id.index); + if ctor_def_id == def_id && vis.is_public() { + // For non-exhaustive variants lower the constructor visibility to + // within the crate. We only need this for fictive constructors, + // for other constructors correct visibilities + // were already encoded in metadata. + let mut attrs = self.get_item_attrs(def_id.index, sess); + if attrs.any(|item| item.has_name(sym::non_exhaustive)) { + let crate_def_id = self.local_def_id(CRATE_DEF_INDEX); + vis = ty::Visibility::Restricted(crate_def_id); + } + } + callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false }); + } + _ => {} } } } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index e967750aebb..732e7ef8a23 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -4,6 +4,7 @@ use crate::rmeta::*; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::iter_from_generator; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::sync::{join, par_iter, Lrc, ParallelIterator}; use rustc_hir as hir; @@ -1107,21 +1108,26 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // 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 { - let direct_children = md.item_ids.iter().map(|item_id| item_id.def_id.local_def_index); - // Foreign items are planted into their parent modules from name resolution point of view. - let tcx = self.tcx; - let foreign_item_children = md - .item_ids - .iter() - .filter_map(|item_id| match tcx.hir().item(*item_id).kind { - hir::ItemKind::ForeignMod { items, .. } => { - Some(items.iter().map(|fi_ref| fi_ref.id.def_id.local_def_index)) + record!(self.tables.children[def_id] <- iter_from_generator(|| { + for item_id in md.item_ids { + match tcx.hir().item(*item_id).kind { + // Foreign items are planted into their parent modules + // from name resolution point of view. + hir::ItemKind::ForeignMod { items, .. } => { + for foreign_item in items { + yield foreign_item.id.def_id.local_def_index; + } + } + // Only encode named non-reexport children, reexports are encoded + // separately and unnamed items are not used by name resolution. + hir::ItemKind::ExternCrate(..) => continue, + _ if tcx.def_key(item_id.def_id.to_def_id()).get_opt_name().is_some() => { + yield item_id.def_id.local_def_index; + } + _ => continue, } - _ => None, - }) - .flatten(); - - record!(self.tables.children[def_id] <- direct_children.chain(foreign_item_children)); + } + })); } }