summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_metadata/src/rmeta
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs79
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs27
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs518
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs10
4 files changed, 333 insertions, 301 deletions
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 830417eea..691e3d0f8 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -773,7 +773,15 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
}
fn opt_item_name(self, item_index: DefIndex) -> Option<Symbol> {
- self.def_key(item_index).disambiguated_data.data.get_opt_name()
+ let def_key = self.def_key(item_index);
+ def_key.disambiguated_data.data.get_opt_name().or_else(|| {
+ if def_key.disambiguated_data.data == DefPathData::Ctor {
+ let parent_index = def_key.parent.expect("no parent for a constructor");
+ self.def_key(parent_index).disambiguated_data.data.get_opt_name()
+ } else {
+ None
+ }
+ })
}
fn item_name(self, item_index: DefIndex) -> Symbol {
@@ -905,7 +913,13 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
.get(self, item_id)
.unwrap_or_else(LazyArray::empty)
.decode(self)
- .map(|index| self.get_variant(&self.def_kind(index), index, did))
+ .filter_map(|index| {
+ let kind = self.def_kind(index);
+ match kind {
+ DefKind::Ctor(..) => None,
+ _ => Some(self.get_variant(&kind, index, did)),
+ }
+ })
.collect()
} else {
std::iter::once(self.get_variant(&kind, item_id, did)).collect()
@@ -1029,50 +1043,27 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
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));
- 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);
- }
+ // For non-reexport variants add their fictive constructors to children.
+ // 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.
+ // Reexport lists automatically contain such constructors when necessary.
+ if kind == DefKind::Variant && self.get_ctor_def_id_and_kind(child_index).is_none()
+ {
+ let ctor_res =
+ Res::Def(DefKind::Ctor(CtorOf::Variant, CtorKind::Fictive), def_id);
+ let mut vis = vis;
+ if 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)) {
+ vis = ty::Visibility::Restricted(self.local_def_id(CRATE_DEF_INDEX));
}
- callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
}
- _ => {}
+ callback(ModChild { ident, res: ctor_res, vis, span, macro_rules: false });
}
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index dede1b212..a0a085525 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -15,7 +15,6 @@ use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::{ExternProviders, Providers};
use rustc_middle::ty::{self, TyCtxt, Visibility};
use rustc_session::cstore::{CrateSource, CrateStore};
-use rustc_session::utils::NativeLibKind;
use rustc_session::{Session, StableCrateId};
use rustc_span::hygiene::{ExpnHash, ExpnId};
use rustc_span::source_map::{Span, Spanned};
@@ -210,6 +209,7 @@ provide! { tcx, def_id, other, cdata,
lookup_const_stability => { table }
lookup_default_body_stability => { table }
lookup_deprecation_entry => { table }
+ params_in_repr => { table }
unused_generic_params => { table }
opt_def_kind => { table_direct }
impl_parent => { table }
@@ -223,6 +223,16 @@ provide! { tcx, def_id, other, cdata,
fn_arg_names => { table }
generator_kind => { table }
trait_def => { table }
+ deduced_param_attrs => { table }
+ collect_trait_impl_trait_tys => {
+ Ok(cdata
+ .root
+ .tables
+ .trait_impl_trait_tys
+ .get(cdata, def_id.index)
+ .map(|lazy| lazy.decode((cdata, tcx)))
+ .process_decoded(tcx, || panic!("{:?} does not have trait_impl_trait_tys", def_id)))
+ }
visibility => { cdata.get_visibility(def_id.index) }
adt_def => { cdata.get_adt_def(def_id.index, tcx) }
@@ -329,20 +339,10 @@ pub(in crate::rmeta) fn provide(providers: &mut Providers) {
// resolve! Does this work? Unsure! That's what the issue is about
*providers = Providers {
allocator_kind: |tcx, ()| CStore::from_tcx(tcx).allocator_kind(),
- is_dllimport_foreign_item: |tcx, id| match tcx.native_library_kind(id) {
- Some(
- NativeLibKind::Dylib { .. } | NativeLibKind::RawDylib | NativeLibKind::Unspecified,
- ) => true,
- _ => false,
- },
- is_statically_included_foreign_item: |tcx, id| {
- matches!(tcx.native_library_kind(id), Some(NativeLibKind::Static { .. }))
- },
is_private_dep: |_tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
false
},
- native_library_kind: |tcx, id| tcx.native_library(id).map(|l| l.kind),
native_library: |tcx, id| {
tcx.native_libraries(id.krate)
.iter()
@@ -587,11 +587,6 @@ impl CStore {
self.get_crate_data(cnum).get_proc_macro_quoted_span(id, sess)
}
- /// Decodes all traits in the crate (for rustdoc).
- pub fn traits_in_crate_untracked(&self, cnum: CrateNum) -> impl Iterator<Item = DefId> + '_ {
- self.get_crate_data(cnum).get_traits()
- }
-
/// Decodes all trait impls in the crate (for rustdoc).
pub fn trait_impls_in_crate_untracked(
&self,
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 5a60ea794..049514ec7 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -3,6 +3,7 @@ use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
use crate::rmeta::table::TableBuilder;
use crate::rmeta::*;
+use rustc_ast::Attribute;
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
use rustc_data_structures::memmap::{Mmap, MmapMut};
@@ -28,8 +29,9 @@ use rustc_middle::ty::codec::TyEncoder;
use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
+use rustc_middle::util::common::to_readable_str;
use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
-use rustc_session::config::CrateType;
+use rustc_session::config::{CrateType, OptLevel};
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
use rustc_span::symbol::{sym, Symbol};
@@ -261,10 +263,10 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
// This allows us to avoid loading the dependencies of proc-macro crates: all of
// the information we need to decode `Span`s is stored in the proc-macro crate.
let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
- // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
- // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
- // are relative to the source map information for the 'foreign' crate whose CrateNum
- // we write into the metadata. This allows `imported_source_files` to binary
+ // To simplify deserialization, we 'rebase' this span onto the crate it originally came
+ // from (the crate that 'owns' the file it references. These rebased 'lo' and 'hi'
+ // values are relative to the source map information for the 'foreign' crate whose
+ // CrateNum we write into the metadata. This allows `imported_source_files` to binary
// search through the 'foreign' crate's source map information, using the
// deserialized 'lo' and 'hi' values directly.
//
@@ -554,78 +556,56 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
let tcx = self.tcx;
- let mut i = 0;
- let preamble_bytes = self.position() - i;
-
- // Encode the crate deps
- i = self.position();
- let crate_deps = self.encode_crate_deps();
- let dylib_dependency_formats = self.encode_dylib_dependency_formats();
- let dep_bytes = self.position() - i;
-
- // Encode the lib features.
- i = self.position();
- let lib_features = self.encode_lib_features();
- let lib_feature_bytes = self.position() - i;
-
- // Encode the stability implications.
- i = self.position();
- let stability_implications = self.encode_stability_implications();
- let stability_implications_bytes = self.position() - i;
-
- // Encode the language items.
- i = self.position();
- let lang_items = self.encode_lang_items();
- let lang_items_missing = self.encode_lang_items_missing();
- let lang_item_bytes = self.position() - i;
-
- // Encode the diagnostic items.
- i = self.position();
- let diagnostic_items = self.encode_diagnostic_items();
- let diagnostic_item_bytes = self.position() - i;
-
- // Encode the native libraries used
- i = self.position();
- let native_libraries = self.encode_native_libraries();
- let native_lib_bytes = self.position() - i;
-
- i = self.position();
- let foreign_modules = self.encode_foreign_modules();
- let foreign_modules_bytes = self.position() - i;
-
- // Encode DefPathTable
- i = self.position();
- self.encode_def_path_table();
- let def_path_table_bytes = self.position() - i;
+ let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32);
+
+ macro_rules! stat {
+ ($label:literal, $f:expr) => {{
+ let orig_pos = self.position();
+ let res = $f();
+ stats.push(($label, self.position() - orig_pos));
+ res
+ }};
+ }
+
+ // We have already encoded some things. Get their combined size from the current position.
+ stats.push(("preamble", self.position()));
+
+ let (crate_deps, dylib_dependency_formats) =
+ stat!("dep", || (self.encode_crate_deps(), self.encode_dylib_dependency_formats()));
+
+ let lib_features = stat!("lib-features", || self.encode_lib_features());
+
+ let stability_implications =
+ stat!("stability-implications", || self.encode_stability_implications());
+
+ let (lang_items, lang_items_missing) = stat!("lang-items", || {
+ (self.encode_lang_items(), self.encode_lang_items_missing())
+ });
+
+ let diagnostic_items = stat!("diagnostic-items", || self.encode_diagnostic_items());
+
+ let native_libraries = stat!("native-libs", || self.encode_native_libraries());
+
+ let foreign_modules = stat!("foreign-modules", || self.encode_foreign_modules());
+
+ _ = stat!("def-path-table", || self.encode_def_path_table());
// Encode the def IDs of traits, for rustdoc and diagnostics.
- i = self.position();
- let traits = self.encode_traits();
- let traits_bytes = self.position() - i;
+ let traits = stat!("traits", || self.encode_traits());
// Encode the def IDs of impls, for coherence checking.
- i = self.position();
- let impls = self.encode_impls();
- let impls_bytes = self.position() - i;
-
- i = self.position();
- let incoherent_impls = self.encode_incoherent_impls();
- let incoherent_impls_bytes = self.position() - i;
-
- // Encode MIR.
- i = self.position();
- self.encode_mir();
- let mir_bytes = self.position() - i;
-
- // Encode the items.
- i = self.position();
- self.encode_def_ids();
- self.encode_info_for_items();
- let item_bytes = self.position() - i;
-
- // Encode the allocation index
- i = self.position();
- let interpret_alloc_index = {
+ let impls = stat!("impls", || self.encode_impls());
+
+ let incoherent_impls = stat!("incoherent-impls", || self.encode_incoherent_impls());
+
+ _ = stat!("mir", || self.encode_mir());
+
+ _ = stat!("items", || {
+ self.encode_def_ids();
+ self.encode_info_for_items();
+ });
+
+ let interpret_alloc_index = stat!("interpret-alloc-index", || {
let mut interpret_alloc_index = Vec::new();
let mut n = 0;
trace!("beginning to encode alloc ids");
@@ -646,126 +626,90 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
n = new_n;
}
self.lazy_array(interpret_alloc_index)
- };
- let interpret_alloc_index_bytes = self.position() - i;
+ });
- // Encode the proc macro data. This affects 'tables',
- // so we need to do this before we encode the tables.
- // This overwrites def_keys, so it must happen after encode_def_path_table.
- i = self.position();
- let proc_macro_data = self.encode_proc_macros();
- let proc_macro_data_bytes = self.position() - i;
+ // Encode the proc macro data. This affects `tables`, so we need to do this before we
+ // encode the tables. This overwrites def_keys, so it must happen after
+ // encode_def_path_table.
+ let proc_macro_data = stat!("proc-macro-data", || self.encode_proc_macros());
- i = self.position();
- let tables = self.tables.encode(&mut self.opaque);
- let tables_bytes = self.position() - i;
+ let tables = stat!("tables", || self.tables.encode(&mut self.opaque));
- i = self.position();
- let debugger_visualizers = self.encode_debugger_visualizers();
- let debugger_visualizers_bytes = self.position() - i;
+ let debugger_visualizers =
+ stat!("debugger-visualizers", || self.encode_debugger_visualizers());
// Encode exported symbols info. This is prefetched in `encode_metadata` so we encode
// this as late as possible to give the prefetching as much time as possible to complete.
- i = self.position();
- let exported_symbols = tcx.exported_symbols(LOCAL_CRATE);
- let exported_symbols = self.encode_exported_symbols(&exported_symbols);
- let exported_symbols_bytes = self.position() - i;
-
- // Encode the hygiene data,
- // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The process
- // of encoding other items (e.g. `optimized_mir`) may cause us to load
- // data from the incremental cache. If this causes us to deserialize a `Span`,
- // then we may load additional `SyntaxContext`s into the global `HygieneData`.
- // Therefore, we need to encode the hygiene data last to ensure that we encode
- // any `SyntaxContext`s that might be used.
- i = self.position();
- let (syntax_contexts, expn_data, expn_hashes) = self.encode_hygiene();
- let hygiene_bytes = self.position() - i;
-
- i = self.position();
- let def_path_hash_map = self.encode_def_path_hash_map();
- let def_path_hash_map_bytes = self.position() - i;
-
- // Encode source_map. This needs to be done last,
- // since encoding `Span`s tells us which `SourceFiles` we actually
- // need to encode.
- i = self.position();
- let source_map = self.encode_source_map();
- let source_map_bytes = self.position() - i;
-
- i = self.position();
- let attrs = tcx.hir().krate_attrs();
- let has_default_lib_allocator = tcx.sess.contains_name(&attrs, sym::default_lib_allocator);
- let root = self.lazy(CrateRoot {
- name: tcx.crate_name(LOCAL_CRATE),
- extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
- triple: tcx.sess.opts.target_triple.clone(),
- hash: tcx.crate_hash(LOCAL_CRATE),
- stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
- required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
- panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
- edition: tcx.sess.edition(),
- has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
- has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
- has_default_lib_allocator,
- proc_macro_data,
- debugger_visualizers,
- compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
- needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
- needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
- no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
- panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
- profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
- symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
-
- crate_deps,
- dylib_dependency_formats,
- lib_features,
- stability_implications,
- lang_items,
- diagnostic_items,
- lang_items_missing,
- native_libraries,
- foreign_modules,
- source_map,
- traits,
- impls,
- incoherent_impls,
- exported_symbols,
- interpret_alloc_index,
- tables,
- syntax_contexts,
- expn_data,
- expn_hashes,
- def_path_hash_map,
+ let exported_symbols = stat!("exported-symbols", || {
+ self.encode_exported_symbols(&tcx.exported_symbols(LOCAL_CRATE))
+ });
+
+ // Encode the hygiene data.
+ // IMPORTANT: this *must* be the last thing that we encode (other than `SourceMap`). The
+ // process of encoding other items (e.g. `optimized_mir`) may cause us to load data from
+ // the incremental cache. If this causes us to deserialize a `Span`, then we may load
+ // additional `SyntaxContext`s into the global `HygieneData`. Therefore, we need to encode
+ // the hygiene data last to ensure that we encode any `SyntaxContext`s that might be used.
+ let (syntax_contexts, expn_data, expn_hashes) = stat!("hygiene", || self.encode_hygiene());
+
+ let def_path_hash_map = stat!("def-path-hash-map", || self.encode_def_path_hash_map());
+
+ // Encode source_map. This needs to be done last, because encoding `Span`s tells us which
+ // `SourceFiles` we actually need to encode.
+ let source_map = stat!("source-map", || self.encode_source_map());
+
+ let root = stat!("final", || {
+ let attrs = tcx.hir().krate_attrs();
+ self.lazy(CrateRoot {
+ name: tcx.crate_name(LOCAL_CRATE),
+ extra_filename: tcx.sess.opts.cg.extra_filename.clone(),
+ triple: tcx.sess.opts.target_triple.clone(),
+ hash: tcx.crate_hash(LOCAL_CRATE),
+ stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(),
+ required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE),
+ panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop,
+ edition: tcx.sess.edition(),
+ has_global_allocator: tcx.has_global_allocator(LOCAL_CRATE),
+ has_panic_handler: tcx.has_panic_handler(LOCAL_CRATE),
+ has_default_lib_allocator: tcx
+ .sess
+ .contains_name(&attrs, sym::default_lib_allocator),
+ proc_macro_data,
+ debugger_visualizers,
+ compiler_builtins: tcx.sess.contains_name(&attrs, sym::compiler_builtins),
+ needs_allocator: tcx.sess.contains_name(&attrs, sym::needs_allocator),
+ needs_panic_runtime: tcx.sess.contains_name(&attrs, sym::needs_panic_runtime),
+ no_builtins: tcx.sess.contains_name(&attrs, sym::no_builtins),
+ panic_runtime: tcx.sess.contains_name(&attrs, sym::panic_runtime),
+ profiler_runtime: tcx.sess.contains_name(&attrs, sym::profiler_runtime),
+ symbol_mangling_version: tcx.sess.opts.get_symbol_mangling_version(),
+
+ crate_deps,
+ dylib_dependency_formats,
+ lib_features,
+ stability_implications,
+ lang_items,
+ diagnostic_items,
+ lang_items_missing,
+ native_libraries,
+ foreign_modules,
+ source_map,
+ traits,
+ impls,
+ incoherent_impls,
+ exported_symbols,
+ interpret_alloc_index,
+ tables,
+ syntax_contexts,
+ expn_data,
+ expn_hashes,
+ def_path_hash_map,
+ })
});
- let final_bytes = self.position() - i;
let total_bytes = self.position();
- let computed_total_bytes = preamble_bytes
- + dep_bytes
- + lib_feature_bytes
- + stability_implications_bytes
- + lang_item_bytes
- + diagnostic_item_bytes
- + native_lib_bytes
- + foreign_modules_bytes
- + def_path_table_bytes
- + traits_bytes
- + impls_bytes
- + incoherent_impls_bytes
- + mir_bytes
- + item_bytes
- + interpret_alloc_index_bytes
- + proc_macro_data_bytes
- + tables_bytes
- + debugger_visualizers_bytes
- + exported_symbols_bytes
- + hygiene_bytes
- + def_path_hash_map_bytes
- + source_map_bytes
- + final_bytes;
+ let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum();
assert_eq!(total_bytes, computed_total_bytes);
if tcx.sess.meta_stats() {
@@ -783,48 +727,77 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
assert_eq!(self.opaque.file().stream_position().unwrap(), pos_before_rewind);
+ stats.sort_by_key(|&(_, usize)| usize);
+
+ let prefix = "meta-stats";
let perc = |bytes| (bytes * 100) as f64 / total_bytes as f64;
- let p = |label, bytes| {
- eprintln!("{:>21}: {:>8} bytes ({:4.1}%)", label, bytes, perc(bytes));
- };
- eprintln!("");
+ eprintln!("{} METADATA STATS", prefix);
+ eprintln!("{} {:<23}{:>10}", prefix, "Section", "Size");
+ eprintln!(
+ "{} ----------------------------------------------------------------",
+ prefix
+ );
+ for (label, size) in stats {
+ eprintln!(
+ "{} {:<23}{:>10} ({:4.1}%)",
+ prefix,
+ label,
+ to_readable_str(size),
+ perc(size)
+ );
+ }
+ eprintln!(
+ "{} ----------------------------------------------------------------",
+ prefix
+ );
eprintln!(
- "{} metadata bytes, of which {} bytes ({:.1}%) are zero",
- total_bytes,
- zero_bytes,
+ "{} {:<23}{:>10} (of which {:.1}% are zero bytes)",
+ prefix,
+ "Total",
+ to_readable_str(total_bytes),
perc(zero_bytes)
);
- p("preamble", preamble_bytes);
- p("dep", dep_bytes);
- p("lib feature", lib_feature_bytes);
- p("stability_implications", stability_implications_bytes);
- p("lang item", lang_item_bytes);
- p("diagnostic item", diagnostic_item_bytes);
- p("native lib", native_lib_bytes);
- p("foreign modules", foreign_modules_bytes);
- p("def-path table", def_path_table_bytes);
- p("traits", traits_bytes);
- p("impls", impls_bytes);
- p("incoherent_impls", incoherent_impls_bytes);
- p("mir", mir_bytes);
- p("item", item_bytes);
- p("interpret_alloc_index", interpret_alloc_index_bytes);
- p("proc-macro-data", proc_macro_data_bytes);
- p("tables", tables_bytes);
- p("debugger visualizers", debugger_visualizers_bytes);
- p("exported symbols", exported_symbols_bytes);
- p("hygiene", hygiene_bytes);
- p("def-path hashes", def_path_hash_map_bytes);
- p("source_map", source_map_bytes);
- p("final", final_bytes);
- eprintln!("");
+ eprintln!("{}", prefix);
}
root
}
}
+/// Returns whether an attribute needs to be recorded in metadata, that is, if it's usable and
+/// useful in downstream crates. Local-only attributes are an obvious example, but some
+/// rustdoc-specific attributes can equally be of use while documenting the current crate only.
+///
+/// Removing these superfluous attributes speeds up compilation by making the metadata smaller.
+///
+/// Note: the `is_def_id_public` parameter is used to cache whether the given `DefId` has a public
+/// visibility: this is a piece of data that can be computed once per defid, and not once per
+/// attribute. Some attributes would only be usable downstream if they are public.
+#[inline]
+fn should_encode_attr(
+ tcx: TyCtxt<'_>,
+ attr: &Attribute,
+ def_id: LocalDefId,
+ is_def_id_public: &mut Option<bool>,
+) -> bool {
+ if rustc_feature::is_builtin_only_local(attr.name_or_empty()) {
+ // Attributes marked local-only don't need to be encoded for downstream crates.
+ false
+ } else if attr.doc_str().is_some() {
+ // We keep all public doc comments because they might be "imported" into downstream crates
+ // if they use `#[doc(inline)]` to copy an item's documentation into their own.
+ *is_def_id_public
+ .get_or_insert_with(|| tcx.effective_visibilities(()).effective_vis(def_id).is_some())
+ } else if attr.has_name(sym::doc) {
+ // If this is a `doc` attribute, and it's marked `inline` (as in `#[doc(inline)]`), we can
+ // remove it. It won't be inlinable in downstream crates.
+ attr.meta_item_list().map(|l| l.iter().any(|l| !l.has_name(sym::inline))).unwrap_or(false)
+ } else {
+ true
+ }
+}
+
fn should_encode_visibility(def_kind: DefKind) -> bool {
match def_kind {
DefKind::Mod
@@ -1120,14 +1093,44 @@ fn should_encode_const(def_kind: DefKind) -> bool {
}
}
+fn should_encode_trait_impl_trait_tys<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
+ if tcx.def_kind(def_id) != DefKind::AssocFn {
+ return false;
+ }
+
+ let Some(item) = tcx.opt_associated_item(def_id) else { return false; };
+ if item.container != ty::AssocItemContainer::ImplContainer {
+ return false;
+ }
+
+ let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
+
+ // FIXME(RPITIT): This does a somewhat manual walk through the signature
+ // of the trait fn to look for any RPITITs, but that's kinda doing a lot
+ // of work. We can probably remove this when we refactor RPITITs to be
+ // associated types.
+ tcx.fn_sig(trait_item_def_id).skip_binder().output().walk().any(|arg| {
+ if let ty::GenericArgKind::Type(ty) = arg.unpack()
+ && let ty::Projection(data) = ty.kind()
+ && tcx.def_kind(data.item_def_id) == DefKind::ImplTraitPlaceholder
+ {
+ true
+ } else {
+ false
+ }
+ })
+}
+
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fn encode_attrs(&mut self, def_id: LocalDefId) {
- let mut attrs = self
- .tcx
+ let tcx = self.tcx;
+ let mut is_public: Option<bool> = None;
+
+ let mut attrs = tcx
.hir()
- .attrs(self.tcx.hir().local_def_id_to_hir_id(def_id))
+ .attrs(tcx.hir().local_def_id_to_hir_id(def_id))
.iter()
- .filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty()));
+ .filter(move |attr| should_encode_attr(tcx, attr, def_id, &mut is_public));
record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
if attrs.any(|attr| attr.may_have_doc_links()) {
@@ -1189,6 +1192,15 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
record!(self.tables.super_predicates_of[def_id] <- self.tcx.super_predicates_of(def_id));
}
+ if let DefKind::Enum | DefKind::Struct | DefKind::Union = def_kind {
+ let params_in_repr = self.tcx.params_in_repr(def_id);
+ record!(self.tables.params_in_repr[def_id] <- params_in_repr);
+ }
+ if should_encode_trait_impl_trait_tys(tcx, def_id)
+ && let Ok(table) = self.tcx.collect_trait_impl_trait_tys(def_id)
+ {
+ record!(self.tables.trait_impl_trait_tys[def_id] <- table);
+ }
}
let inherent_impls = tcx.crate_inherent_impls(());
for (def_id, implementations) in inherent_impls.inherent_impls.iter() {
@@ -1278,14 +1290,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// from name resolution point of view.
hir::ItemKind::ForeignMod { items, .. } => {
for foreign_item in items {
- yield foreign_item.id.def_id.local_def_index;
+ yield foreign_item.id.owner_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;
+ hir::ItemKind::Struct(ref vdata, _) => {
+ yield item_id.owner_id.def_id.local_def_index;
+ // Encode constructors which take a separate slot in value namespace.
+ if let Some(ctor_hir_id) = vdata.ctor_hir_id() {
+ yield tcx.hir().local_def_id(ctor_hir_id).local_def_index;
+ }
+ }
+ _ if tcx.def_key(item_id.owner_id.to_def_id()).get_opt_name().is_some() => {
+ yield item_id.owner_id.def_id.local_def_index;
}
_ => continue,
}
@@ -1436,6 +1455,21 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused);
}
}
+
+ // Encode all the deduced parameter attributes for everything that has MIR, even for items
+ // that can't be inlined. But don't if we aren't optimizing in non-incremental mode, to
+ // save the query traffic.
+ if tcx.sess.opts.output_types.should_codegen()
+ && tcx.sess.opts.optimize != OptLevel::No
+ && tcx.sess.opts.incremental.is_none()
+ {
+ for &local_def_id in tcx.mir_keys(()) {
+ if let DefKind::AssocFn | DefKind::Fn = tcx.def_kind(local_def_id) {
+ record_array!(self.tables.deduced_param_attrs[local_def_id.to_def_id()] <-
+ self.tcx.deduced_param_attrs(local_def_id.to_def_id()));
+ }
+ }
+ }
}
fn encode_stability(&mut self, def_id: DefId) {
@@ -1507,7 +1541,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
record!(self.tables.macro_definition[def_id] <- &*macro_def.body);
}
hir::ItemKind::Mod(ref m) => {
- return self.encode_info_for_mod(item.def_id, m);
+ return self.encode_info_for_mod(item.owner_id.def_id, m);
}
hir::ItemKind::OpaqueTy(..) => {
self.encode_explicit_item_bounds(def_id);
@@ -1592,12 +1626,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
};
// FIXME(eddyb) there should be a nicer way to do this.
match item.kind {
- hir::ItemKind::Enum(..) => record_array!(self.tables.children[def_id] <-
- self.tcx.adt_def(def_id).variants().iter().map(|v| {
- assert!(v.def_id.is_local());
- v.def_id.index
- })
- ),
+ hir::ItemKind::Enum(..) => {
+ record_array!(self.tables.children[def_id] <- iter::from_generator(||
+ for variant in tcx.adt_def(def_id).variants() {
+ yield variant.def_id.index;
+ // Encode constructors which take a separate slot in value namespace.
+ if let Some(ctor_def_id) = variant.ctor_def_id {
+ yield ctor_def_id.index;
+ }
+ }
+ ))
+ }
hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => {
record_array!(self.tables.children[def_id] <-
self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
@@ -1634,7 +1673,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
// normally in the visitor walk.
match item.kind {
hir::ItemKind::Enum(..) => {
- let def = self.tcx.adt_def(item.def_id.to_def_id());
+ let def = self.tcx.adt_def(item.owner_id.to_def_id());
for (i, variant) in def.variants().iter_enumerated() {
self.encode_enum_variant_info(def, i);
@@ -1644,7 +1683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
}
hir::ItemKind::Struct(ref struct_def, _) => {
- let def = self.tcx.adt_def(item.def_id.to_def_id());
+ let def = self.tcx.adt_def(item.owner_id.to_def_id());
// If the struct has a constructor, encode it.
if let Some(ctor_hir_id) = struct_def.ctor_hir_id() {
let ctor_def_id = self.tcx.hir().local_def_id(ctor_hir_id);
@@ -1653,13 +1692,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
}
hir::ItemKind::Impl { .. } => {
for &trait_item_def_id in
- self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+ self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
{
self.encode_info_for_impl_item(trait_item_def_id);
}
}
hir::ItemKind::Trait(..) => {
- for &item_def_id in self.tcx.associated_item_def_ids(item.def_id.to_def_id()).iter()
+ for &item_def_id in
+ self.tcx.associated_item_def_ids(item.owner_id.to_def_id()).iter()
{
self.encode_info_for_trait_item(item_def_id);
}
@@ -1900,8 +1940,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
FxHashMap::default();
for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::Impl) {
- if let Some(trait_ref) = tcx.impl_trait_ref(id.def_id.to_def_id()) {
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Impl) {
+ if let Some(trait_ref) = tcx.impl_trait_ref(id.owner_id) {
let simplified_self_ty = fast_reject::simplify_type(
self.tcx,
trait_ref.self_ty(),
@@ -1911,7 +1951,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
fx_hash_map
.entry(trait_ref.def_id)
.or_default()
- .push((id.def_id.local_def_index, simplified_self_ty));
+ .push((id.owner_id.def_id.local_def_index, simplified_self_ty));
}
}
}
@@ -2052,12 +2092,12 @@ impl<'a, 'tcx> Visitor<'tcx> for EncodeContext<'a, 'tcx> {
intravisit::walk_item(self, item);
match item.kind {
hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these
- _ => self.encode_info_for_item(item.def_id.to_def_id(), item),
+ _ => self.encode_info_for_item(item.owner_id.to_def_id(), item),
}
}
fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem<'tcx>) {
intravisit::walk_foreign_item(self, ni);
- self.encode_info_for_foreign_item(ni.def_id.to_def_id(), ni);
+ self.encode_info_for_foreign_item(ni.owner_id.to_def_id(), ni);
}
fn visit_generics(&mut self, generics: &'tcx hir::Generics<'tcx>) {
intravisit::walk_generics(self, generics);
@@ -2276,8 +2316,8 @@ pub fn provide(providers: &mut Providers) {
let mut traits = Vec::new();
for id in tcx.hir().items() {
- if matches!(tcx.def_kind(id.def_id), DefKind::Trait | DefKind::TraitAlias) {
- traits.push(id.def_id.to_def_id())
+ if matches!(tcx.def_kind(id.owner_id), DefKind::Trait | DefKind::TraitAlias) {
+ traits.push(id.owner_id.to_def_id())
}
}
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 748b3afec..27dc8ff16 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -1,6 +1,7 @@
use crate::creader::CrateMetadataRef;
use decoder::Metadata;
use def_path_hash_map::DefPathHashMapRef;
+use rustc_data_structures::fx::FxHashMap;
use table::TableBuilder;
use rustc_ast as ast;
@@ -12,7 +13,8 @@ use rustc_hir::def::{CtorKind, DefKind};
use rustc_hir::def_id::{CrateNum, DefId, DefIndex, DefPathHash, StableCrateId};
use rustc_hir::definitions::DefKey;
use rustc_hir::lang_items;
-use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec};
+use rustc_index::bit_set::{BitSet, FiniteBitSet};
+use rustc_index::vec::IndexVec;
use rustc_middle::metadata::ModChild;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
@@ -21,7 +23,7 @@ use rustc_middle::mir;
use rustc_middle::ty::fast_reject::SimplifiedType;
use rustc_middle::ty::query::Providers;
use rustc_middle::ty::{self, ReprOptions, Ty};
-use rustc_middle::ty::{GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
+use rustc_middle::ty::{DeducedParamAttrs, GeneratorDiagnosticData, ParameterizedOverTcx, TyCtxt};
use rustc_serialize::opaque::FileEncoder;
use rustc_session::config::SymbolManglingVersion;
use rustc_session::cstore::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib};
@@ -382,6 +384,7 @@ define_tables! {
inherent_impls: Table<DefIndex, LazyArray<DefIndex>>,
expn_that_defined: Table<DefIndex, LazyValue<ExpnId>>,
unused_generic_params: Table<DefIndex, LazyValue<FiniteBitSet<u32>>>,
+ params_in_repr: Table<DefIndex, LazyValue<BitSet<u32>>>,
repr_options: Table<DefIndex, LazyValue<ReprOptions>>,
// `def_keys` and `def_path_hashes` represent a lazy version of a
// `DefPathTable`. This allows us to avoid deserializing an entire
@@ -399,6 +402,9 @@ define_tables! {
macro_definition: Table<DefIndex, LazyValue<ast::MacArgs>>,
proc_macro: Table<DefIndex, MacroKind>,
module_reexports: Table<DefIndex, LazyArray<ModChild>>,
+ deduced_param_attrs: Table<DefIndex, LazyArray<DeducedParamAttrs>>,
+
+ trait_impl_trait_tys: Table<DefIndex, LazyValue<FxHashMap<DefId, Ty<'static>>>>,
}
#[derive(TyEncodable, TyDecodable)]