summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_metadata/src/rmeta/encoder.rs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs518
1 files changed, 279 insertions, 239 deletions
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())
}
}