use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
-use crate::rmeta::table::{FixedSizeEncoding, TableBuilder};
+use crate::rmeta::table::TableBuilder;
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;
};
use rustc_hir::definitions::DefPathData;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::lang_items;
use rustc_hir::{AnonConst, GenericParamKind};
use rustc_index::bit_set::GrowableBitSet;
-use rustc_index::vec::Idx;
use rustc_middle::hir::nested_filter;
use rustc_middle::middle::dependency_format::Linkage;
use rustc_middle::middle::exported_symbols::{
metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
};
use rustc_middle::mir::interpret;
-use rustc_middle::thir;
use rustc_middle::traits::specialization_graph;
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_serialize::{opaque, Encodable, Encoder};
+use rustc_serialize::opaque::MemEncoder;
+use rustc_serialize::{Encodable, Encoder};
use rustc_session::config::CrateType;
use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
-use rustc_span::symbol::{sym, Ident, Symbol};
+use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
+use rustc_span::symbol::{sym, Symbol};
use rustc_span::{
self, DebuggerVisualizerFile, ExternalSource, FileName, SourceFile, Span, SyntaxContext,
};
-use rustc_span::{
- hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind},
- RealFileName,
-};
use rustc_target::abi::VariantIdx;
+use std::borrow::Borrow;
use std::hash::Hash;
+use std::iter;
use std::num::NonZeroUsize;
-use std::path::Path;
use tracing::{debug, trace};
pub(super) struct EncodeContext<'a, 'tcx> {
- opaque: opaque::Encoder,
+ opaque: MemEncoder,
tcx: TyCtxt<'tcx>,
feat: &'tcx rustc_feature::Features,
- tables: TableBuilders<'tcx>,
+ tables: TableBuilders,
lazy_state: LazyState,
type_shorthands: FxHashMap<Ty<'tcx>, usize>,
macro_rules! empty_proc_macro {
($self:ident) => {
if $self.is_proc_macro {
- return Lazy::empty();
+ return LazyArray::empty();
}
};
}
macro_rules! encoder_methods {
($($name:ident($ty:ty);)*) => {
- $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> {
+ $(fn $name(&mut self, value: $ty) {
self.opaque.$name(value)
})*
}
}
impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> {
- type Error = <opaque::Encoder as Encoder>::Error;
-
- #[inline]
- fn emit_unit(&mut self) -> Result<(), Self::Error> {
- Ok(())
- }
-
encoder_methods! {
emit_usize(usize);
emit_u128(u128);
}
}
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
- for Lazy<T>
-{
- fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- e.emit_lazy_distance(*self)
+impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyValue<T> {
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
+ e.emit_lazy_distance(self.position);
}
}
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> Encodable<EncodeContext<'a, 'tcx>>
- for Lazy<[T]>
-{
- fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- e.emit_usize(self.meta)?;
- if self.meta == 0 {
- return Ok(());
+impl<'a, 'tcx, T> Encodable<EncodeContext<'a, 'tcx>> for LazyArray<T> {
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
+ e.emit_usize(self.num_elems);
+ if self.num_elems > 0 {
+ e.emit_lazy_distance(self.position)
}
- e.emit_lazy_distance(*self)
}
}
-impl<'a, 'tcx, I: Idx, T> Encodable<EncodeContext<'a, 'tcx>> for Lazy<Table<I, T>>
-where
- Option<T>: FixedSizeEncoding,
-{
- fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- e.emit_usize(self.meta)?;
- e.emit_lazy_distance(*self)
+impl<'a, 'tcx, I, T> Encodable<EncodeContext<'a, 'tcx>> for LazyTable<I, T> {
+ fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) {
+ e.emit_usize(self.encoded_size);
+ e.emit_lazy_distance(self.position);
}
}
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for CrateNum {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
if *self != LOCAL_CRATE && s.is_proc_macro {
panic!("Attempted to encode non-local CrateNum {:?} for proc-macro crate", self);
}
- s.emit_u32(self.as_u32())
+ s.emit_u32(self.as_u32());
}
}
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for DefIndex {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- s.emit_u32(self.as_u32())
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+ s.emit_u32(self.as_u32());
}
}
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnIndex {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- s.emit_u32(self.as_u32())
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+ s.emit_u32(self.as_u32());
}
}
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for SyntaxContext {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s)
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+ rustc_span::hygiene::raw_encode_syntax_context(*self, &s.hygiene_ctxt, s);
}
}
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for ExpnId {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
if self.krate == LOCAL_CRATE {
// We will only write details for local expansions. Non-local expansions will fetch
// data from the corresponding crate's metadata.
// metadata from proc-macro crates.
s.hygiene_ctxt.schedule_expn_data_for_encoding(*self);
}
- self.krate.encode(s)?;
- self.local_id.encode(s)
+ self.krate.encode(s);
+ self.local_id.encode(s);
}
}
impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
+ fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
let span = self.data();
// Don't serialize any `SyntaxContext`s from a proc-macro crate,
// `rustc_span::hygiene::raw_encode_expn_id` to handle
// encoding `ExpnData` for proc-macro crates.
if s.is_proc_macro {
- SyntaxContext::root().encode(s)?;
+ SyntaxContext::root().encode(s);
} else {
- span.ctxt.encode(s)?;
+ span.ctxt.encode(s);
}
if self.is_dummy() {
(TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
};
- tag.encode(s)?;
- lo.encode(s)?;
+ tag.encode(s);
+ lo.encode(s);
// Encode length which is usually less than span.hi and profits more
// from the variable-length integer encoding that we use.
let len = hi - lo;
- len.encode(s)?;
+ len.encode(s);
if tag == TAG_VALID_SPAN_FOREIGN {
// This needs to be two lines to avoid holding the `s.source_file_cache`
// while calling `cnum.encode(s)`
let cnum = s.source_file_cache.0.cnum;
- cnum.encode(s)?;
+ cnum.encode(s);
}
-
- Ok(())
}
}
-impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> {
+impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
const CLEAR_CROSS_CRATE: bool = true;
+ type I = TyCtxt<'tcx>;
+
fn position(&self) -> usize {
self.opaque.position()
}
&mut self.predicate_shorthands
}
- fn encode_alloc_id(
- &mut self,
- alloc_id: &rustc_middle::mir::interpret::AllocId,
- ) -> Result<(), Self::Error> {
+ fn encode_alloc_id(&mut self, alloc_id: &rustc_middle::mir::interpret::AllocId) {
let (index, _) = self.interpret_allocs.insert_full(*alloc_id);
- index.encode(self)
+ index.encode(self);
}
}
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [thir::abstract_const::Node<'tcx>] {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- (**self).encode(s)
- }
-}
-
-impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for &'tcx [(ty::Predicate<'tcx>, Span)] {
- fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) -> opaque::EncodeResult {
- (**self).encode(s)
- }
-}
-
-/// Helper trait to allow overloading `EncodeContext::lazy` for iterators.
-trait EncodeContentsForLazy<'a, 'tcx, T: ?Sized + LazyMeta> {
- fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> T::Meta;
-}
-
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for &T {
- fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
- self.encode(ecx).unwrap()
- }
-}
-
-impl<'a, 'tcx, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, T> for T {
- fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) {
- self.encode(ecx).unwrap()
- }
-}
-
-impl<'a, 'tcx, I, T: Encodable<EncodeContext<'a, 'tcx>>> EncodeContentsForLazy<'a, 'tcx, [T]> for I
-where
- I: IntoIterator,
- I::Item: EncodeContentsForLazy<'a, 'tcx, T>,
-{
- fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'a, 'tcx>) -> usize {
- self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count()
- }
-}
-
-// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy($value))`, which would
+// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
// normally need extra variables to avoid errors about multiple mutable borrows.
macro_rules! record {
($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
}};
}
+// Shorthand for `$self.$tables.$table.set($def_id.index, $self.lazy_value($value))`, which would
+// normally need extra variables to avoid errors about multiple mutable borrows.
+macro_rules! record_array {
+ ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{
+ {
+ let value = $value;
+ let lazy = $self.lazy_array(value);
+ $self.$tables.$table.set($def_id.index, lazy);
+ }
+ }};
+}
+
impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
- fn emit_lazy_distance<T: ?Sized + LazyMeta>(
- &mut self,
- lazy: Lazy<T>,
- ) -> Result<(), <Self as Encoder>::Error> {
- let pos = lazy.position.get();
+ fn emit_lazy_distance(&mut self, position: NonZeroUsize) {
+ let pos = position.get();
let distance = match self.lazy_state {
LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"),
LazyState::NodeStart(start) => {
}
LazyState::Previous(last_pos) => {
assert!(
- last_pos <= lazy.position,
+ last_pos <= position,
"make sure that the calls to `lazy*` \
are in the same order as the metadata fields",
);
- lazy.position.get() - last_pos.get()
+ position.get() - last_pos.get()
}
};
self.lazy_state = LazyState::Previous(NonZeroUsize::new(pos).unwrap());
- self.emit_usize(distance)
+ self.emit_usize(distance);
}
- fn lazy<T: ?Sized + LazyMeta>(
+ fn lazy<T: ParameterizedOverTcx, B: Borrow<T::Value<'tcx>>>(&mut self, value: B) -> LazyValue<T>
+ where
+ T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
+ {
+ let pos = NonZeroUsize::new(self.position()).unwrap();
+
+ assert_eq!(self.lazy_state, LazyState::NoNode);
+ self.lazy_state = LazyState::NodeStart(pos);
+ value.borrow().encode(self);
+ self.lazy_state = LazyState::NoNode;
+
+ assert!(pos.get() <= self.position());
+
+ LazyValue::from_position(pos)
+ }
+
+ fn lazy_array<T: ParameterizedOverTcx, I: IntoIterator<Item = B>, B: Borrow<T::Value<'tcx>>>(
&mut self,
- value: impl EncodeContentsForLazy<'a, 'tcx, T>,
- ) -> Lazy<T> {
+ values: I,
+ ) -> LazyArray<T>
+ where
+ T::Value<'tcx>: Encodable<EncodeContext<'a, 'tcx>>,
+ {
let pos = NonZeroUsize::new(self.position()).unwrap();
assert_eq!(self.lazy_state, LazyState::NoNode);
self.lazy_state = LazyState::NodeStart(pos);
- let meta = value.encode_contents_for_lazy(self);
+ let len = values.into_iter().map(|value| value.borrow().encode(self)).count();
self.lazy_state = LazyState::NoNode;
assert!(pos.get() <= self.position());
- Lazy::from_position_and_meta(pos, meta)
+ LazyArray::from_position_and_num_elems(pos, len)
}
fn encode_info_for_items(&mut self) {
return;
}
- self.tcx.hir().visit_all_item_likes(&mut self.as_deep_visitor());
+ self.tcx.hir().deep_visit_all_item_likes(self);
}
fn encode_def_path_table(&mut self) {
- let table = self.tcx.resolutions(()).definitions.def_path_table();
+ let table = self.tcx.definitions_untracked().def_path_table();
if self.is_proc_macro {
for def_index in std::iter::once(CRATE_DEF_INDEX)
.chain(self.tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index))
}
}
- fn encode_def_path_hash_map(&mut self) -> Lazy<DefPathHashMapRef<'tcx>> {
+ fn encode_def_path_hash_map(&mut self) -> LazyValue<DefPathHashMapRef<'static>> {
self.lazy(DefPathHashMapRef::BorrowedFromTcx(
- self.tcx.resolutions(()).definitions.def_path_hash_to_def_index_map(),
+ self.tcx.definitions_untracked().def_path_hash_to_def_index_map(),
))
}
- fn encode_source_map(&mut self) -> Lazy<[rustc_span::SourceFile]> {
+ fn encode_source_map(&mut self) -> LazyArray<rustc_span::SourceFile> {
let source_map = self.tcx.sess.source_map();
let all_source_files = source_map.files();
// is done.
let required_source_files = self.required_source_files.take().unwrap();
+ let working_directory = &self.tcx.sess.opts.working_dir;
+
let adapted = all_source_files
.iter()
.enumerate()
(!source_file.is_imported() || self.is_proc_macro)
})
.map(|(_, source_file)| {
- let mut adapted = match source_file.name {
- FileName::Real(ref realname) => {
- let mut adapted = (**source_file).clone();
- adapted.name = FileName::Real(match realname {
- RealFileName::LocalPath(path_to_file) => {
- // Prepend path of working directory onto potentially
- // relative paths, because they could become relative
- // to a wrong directory.
- // We include `working_dir` as part of the crate hash,
- // so it's okay for us to use it as part of the encoded
- // metadata.
- let working_dir = &self.tcx.sess.opts.working_dir;
- match working_dir {
- RealFileName::LocalPath(absolute) => {
- // Although neither working_dir or the file name were subject
- // to path remapping, the concatenation between the two may
- // be. Hence we need to do a remapping here.
- let joined = Path::new(absolute).join(path_to_file);
- let (joined, remapped) =
- source_map.path_mapping().map_prefix(joined);
- if remapped {
- RealFileName::Remapped {
- local_path: None,
- virtual_name: joined,
- }
- } else {
- RealFileName::LocalPath(joined)
- }
- }
- RealFileName::Remapped { local_path: _, virtual_name } => {
- // If working_dir has been remapped, then we emit
- // Remapped variant as the expanded path won't be valid
- RealFileName::Remapped {
- local_path: None,
- virtual_name: Path::new(virtual_name)
- .join(path_to_file),
- }
- }
- }
- }
- RealFileName::Remapped { local_path: _, virtual_name } => {
- RealFileName::Remapped {
- // We do not want any local path to be exported into metadata
- local_path: None,
- virtual_name: virtual_name.clone(),
- }
- }
- });
- adapted.name_hash = {
- let mut hasher: StableHasher = StableHasher::new();
- adapted.name.hash(&mut hasher);
- hasher.finish::<u128>()
- };
- Lrc::new(adapted)
+ // At export time we expand all source file paths to absolute paths because
+ // downstream compilation sessions can have a different compiler working
+ // directory, so relative paths from this or any other upstream crate
+ // won't be valid anymore.
+ //
+ // At this point we also erase the actual on-disk path and only keep
+ // the remapped version -- as is necessary for reproducible builds.
+ match source_file.name {
+ FileName::Real(ref original_file_name) => {
+ let adapted_file_name =
+ source_map.path_mapping().to_embeddable_absolute_path(
+ original_file_name.clone(),
+ working_directory,
+ );
+
+ if adapted_file_name != *original_file_name {
+ let mut adapted: SourceFile = (**source_file).clone();
+ adapted.name = FileName::Real(adapted_file_name);
+ adapted.name_hash = {
+ let mut hasher: StableHasher = StableHasher::new();
+ adapted.name.hash(&mut hasher);
+ hasher.finish::<u128>()
+ };
+ Lrc::new(adapted)
+ } else {
+ // Nothing to adapt
+ source_file.clone()
+ }
}
-
// expanded code, not from a file
_ => source_file.clone(),
- };
-
+ }
+ })
+ .map(|mut source_file| {
// We're serializing this `SourceFile` into our crate metadata,
// so mark it as coming from this crate.
// This also ensures that we don't try to deserialize the
// dependencies aren't loaded when we deserialize a proc-macro,
// trying to remap the `CrateNum` would fail.
if self.is_proc_macro {
- Lrc::make_mut(&mut adapted).cnum = LOCAL_CRATE;
+ Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE;
}
- adapted
+ source_file
})
.collect::<Vec<_>>();
- self.lazy(adapted.iter().map(|rc| &**rc))
+ self.lazy_array(adapted.iter().map(|rc| &**rc))
}
- fn encode_crate_root(&mut self) -> Lazy<CrateRoot<'tcx>> {
+ fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
let tcx = self.tcx;
- let mut i = self.position();
+ 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;
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();
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 item_bytes = self.position() - i;
// Encode the allocation index
+ i = self.position();
let interpret_alloc_index = {
let mut interpret_alloc_index = Vec::new();
let mut n = 0;
let id = self.interpret_allocs[idx];
let pos = self.position() as u32;
interpret_alloc_index.push(pos);
- interpret::specialized_encode_alloc_id(self, tcx, id).unwrap();
+ interpret::specialized_encode_alloc_id(self, tcx, id);
}
n = new_n;
}
- self.lazy(interpret_alloc_index)
+ 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
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(),
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
+ + 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;
+ assert_eq!(total_bytes, computed_total_bytes);
+
if tcx.sess.meta_stats() {
let mut zero_bytes = 0;
for e in self.opaque.data.iter() {
}
}
- eprintln!("metadata stats:");
- eprintln!(" dep bytes: {}", dep_bytes);
- eprintln!(" lib feature bytes: {}", lib_feature_bytes);
- eprintln!(" lang item bytes: {}", lang_item_bytes);
- eprintln!(" diagnostic item bytes: {}", diagnostic_item_bytes);
- eprintln!(" native bytes: {}", native_lib_bytes);
- eprintln!(" debugger visualizers bytes: {}", debugger_visualizers_bytes);
- eprintln!(" source_map bytes: {}", source_map_bytes);
- eprintln!(" traits bytes: {}", traits_bytes);
- eprintln!(" impls bytes: {}", impls_bytes);
- eprintln!(" incoherent_impls bytes: {}", incoherent_impls_bytes);
- eprintln!(" exp. symbols bytes: {}", exported_symbols_bytes);
- eprintln!(" def-path table bytes: {}", def_path_table_bytes);
- eprintln!(" def-path hashes bytes: {}", def_path_hash_map_bytes);
- eprintln!(" proc-macro-data-bytes: {}", proc_macro_data_bytes);
- eprintln!(" mir bytes: {}", mir_bytes);
- eprintln!(" item bytes: {}", item_bytes);
- eprintln!(" table bytes: {}", tables_bytes);
- eprintln!(" hygiene bytes: {}", hygiene_bytes);
- eprintln!(" zero bytes: {}", zero_bytes);
- eprintln!(" total bytes: {}", total_bytes);
+ 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 bytes, of which {} bytes ({:.1}%) are zero",
+ total_bytes,
+ zero_bytes,
+ perc(zero_bytes)
+ );
+ p("preamble", preamble_bytes);
+ p("dep", dep_bytes);
+ p("lib feature", lib_feature_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!("");
}
root
let needs_inline = (generics.requires_monomorphization(tcx)
|| tcx.codegen_fn_attrs(def_id).requests_inline())
&& tcx.sess.opts.output_types.should_codegen();
- // The function has a `const` modifier or is annotated with `default_method_body_is_const`.
+ // The function has a `const` modifier or is in a `#[const_trait]`.
let is_const_fn = tcx.is_const_fn_raw(def_id.to_def_id())
- || tcx.has_attr(def_id.to_def_id(), sym::default_method_body_is_const);
+ || tcx.is_const_default_method(def_id.to_def_id());
let always_encode_mir = tcx.sess.opts.debugging_opts.always_encode_mir;
(is_const_fn, needs_inline || always_encode_mir)
}
.iter()
.filter(|attr| !rustc_feature::is_builtin_only_local(attr.name_or_empty()));
- record!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
+ record_array!(self.tables.attributes[def_id.to_def_id()] <- attrs.clone());
if attrs.any(|attr| attr.may_have_doc_links()) {
self.tables.may_have_doc_links.set(def_id.local_def_index, ());
}
record!(self.tables.def_span[def_id] <- tcx.def_span(def_id));
self.encode_attrs(local_id);
record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id));
+ if let Some(ident_span) = tcx.def_ident_span(def_id) {
+ record!(self.tables.def_ident_span[def_id] <- ident_span);
+ }
if def_kind.has_codegen_attrs() {
record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id));
}
}
if should_encode_variances(def_kind) {
let v = self.tcx.variances_of(def_id);
- record!(self.tables.variances_of[def_id] <- v);
+ record_array!(self.tables.variances_of[def_id] <- v);
}
if should_encode_generics(def_kind) {
let g = tcx.generics_of(def_id);
record!(self.tables.explicit_predicates_of[def_id] <- self.tcx.explicit_predicates_of(def_id));
let inferred_outlives = self.tcx.inferred_outlives_of(def_id);
if !inferred_outlives.is_empty() {
- record!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
+ record_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives);
}
}
if let DefKind::Trait | DefKind::TraitAlias = def_kind {
if implementations.is_empty() {
continue;
}
- record!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
+ record_array!(self.tables.inherent_impls[def_id.to_def_id()] <- implementations.iter().map(|&def_id| {
assert!(def_id.is_local());
def_id.index
}));
};
record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
- self.tables.impl_constness.set(def_id.index, hir::Constness::Const);
- record!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
+ self.tables.constness.set(def_id.index, hir::Constness::Const);
+ record_array!(self.tables.children[def_id] <- variant.fields.iter().map(|f| {
assert!(f.did.is_local());
f.did.index
}));
- self.encode_ident_span(def_id, variant.ident(tcx));
self.encode_item_type(def_id);
if variant.ctor_kind == CtorKind::Fn {
// FIXME(eddyb) encode signature only in `encode_enum_variant_ctor`.
};
record!(self.tables.kind[def_id] <- EntryKind::Variant(self.lazy(data)));
- self.tables.impl_constness.set(def_id.index, hir::Constness::Const);
+ self.tables.constness.set(def_id.index, hir::Constness::Const);
self.encode_item_type(def_id);
if variant.ctor_kind == CtorKind::Fn {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
// items - we encode information about proc-macros later on.
let reexports = if !self.is_proc_macro {
match tcx.module_reexports(local_def_id) {
- Some(exports) => self.lazy(exports),
- _ => Lazy::empty(),
+ Some(exports) => self.lazy_array(exports),
+ _ => LazyArray::empty(),
}
} else {
- Lazy::empty()
+ LazyArray::empty()
};
record!(self.tables.kind[def_id] <- EntryKind::Mod(reexports));
// 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 {
- record!(self.tables.children[def_id] <- iter_from_generator(|| {
+ record_array!(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
debug!("EncodeContext::encode_field({:?})", def_id);
record!(self.tables.kind[def_id] <- EntryKind::Field);
- self.encode_ident_span(def_id, field.ident(self.tcx));
self.encode_item_type(def_id);
}
};
record!(self.tables.repr_options[def_id] <- adt_def.repr());
- self.tables.impl_constness.set(def_id.index, hir::Constness::Const);
+ self.tables.constness.set(def_id.index, hir::Constness::Const);
record!(self.tables.kind[def_id] <- EntryKind::Struct(self.lazy(data)));
self.encode_item_type(def_id);
if variant.ctor_kind == CtorKind::Fn {
debug!("EncodeContext::encode_explicit_item_bounds({:?})", def_id);
let bounds = self.tcx.explicit_item_bounds(def_id);
if !bounds.is_empty() {
- record!(self.tables.explicit_item_bounds[def_id] <- bounds);
+ record_array!(self.tables.explicit_item_bounds[def_id] <- bounds);
}
}
let hir::TraitItemKind::Fn(m_sig, m) = &ast_item.kind else { bug!() };
match *m {
hir::TraitFn::Required(ref names) => {
- record!(self.tables.fn_arg_names[def_id] <- *names)
+ record_array!(self.tables.fn_arg_names[def_id] <- *names)
}
hir::TraitFn::Provided(body) => {
- record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
+ record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body))
}
};
self.tables.asyncness.set(def_id.index, m_sig.header.asyncness);
- self.tables.impl_constness.set(def_id.index, hir::Constness::NotConst);
+ self.tables.constness.set(def_id.index, hir::Constness::NotConst);
record!(self.tables.kind[def_id] <- EntryKind::AssocFn(self.lazy(AssocFnData {
container,
has_self: trait_item.fn_has_self_parameter,
record!(self.tables.kind[def_id] <- EntryKind::AssocType(container));
}
}
- self.encode_ident_span(def_id, ast_item.ident);
match trait_item.kind {
ty::AssocKind::Const | ty::AssocKind::Fn => {
self.encode_item_type(def_id);
ty::AssocKind::Fn => {
let hir::ImplItemKind::Fn(ref sig, body) = ast_item.kind else { bug!() };
self.tables.asyncness.set(def_id.index, sig.header.asyncness);
- record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
+ record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
// Can be inside `impl const Trait`, so using sig.header.constness is not reliable
let constness = if self.tcx.is_const_fn_raw(def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
- self.tables.impl_constness.set(def_id.index, constness);
+ self.tables.constness.set(def_id.index, constness);
record!(self.tables.kind[def_id] <- EntryKind::AssocFn(self.lazy(AssocFnData {
container,
has_self: impl_item.fn_has_self_parameter,
record!(self.tables.kind[def_id] <- EntryKind::AssocType(container));
}
}
- self.encode_ident_span(def_id, impl_item.ident(self.tcx));
self.encode_item_type(def_id);
if let Some(trait_item_def_id) = impl_item.trait_item_def_id {
self.tables.trait_item_def_id.set(def_id.index, trait_item_def_id.into());
}
if impl_item.kind == ty::AssocKind::Fn {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+ if tcx.is_intrinsic(def_id) {
+ self.tables.is_intrinsic.set(def_id.index, ());
+ }
}
}
debug!("EncodeContext::encode_info_for_item({:?})", def_id);
- self.encode_ident_span(def_id, item.ident);
-
let entry_kind = match item.kind {
hir::ItemKind::Static(..) => EntryKind::Static,
hir::ItemKind::Const(_, body_id) => {
}
hir::ItemKind::Fn(ref sig, .., body) => {
self.tables.asyncness.set(def_id.index, sig.header.asyncness);
- record!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
- self.tables.impl_constness.set(def_id.index, sig.header.constness);
+ record_array!(self.tables.fn_arg_names[def_id] <- self.tcx.hir().body_param_names(body));
+ self.tables.constness.set(def_id.index, sig.header.constness);
EntryKind::Fn
}
hir::ItemKind::Macro(ref macro_def, _) => {
hir::ItemKind::Struct(ref struct_def, _) => {
let adt_def = self.tcx.adt_def(def_id);
record!(self.tables.repr_options[def_id] <- adt_def.repr());
- self.tables.impl_constness.set(def_id.index, hir::Constness::Const);
+ self.tables.constness.set(def_id.index, hir::Constness::Const);
// Encode def_ids for each field and method
// for methods, write all the stuff get_trait_method
}
hir::ItemKind::Impl(hir::Impl { defaultness, constness, .. }) => {
self.tables.impl_defaultness.set(def_id.index, *defaultness);
- self.tables.impl_constness.set(def_id.index, *constness);
+ self.tables.constness.set(def_id.index, *constness);
let trait_ref = self.tcx.impl_trait_ref(def_id);
if let Some(trait_ref) = trait_ref {
record!(self.tables.kind[def_id] <- entry_kind);
// FIXME(eddyb) there should be a nicer way to do this.
match item.kind {
- hir::ItemKind::Enum(..) => record!(self.tables.children[def_id] <-
+ 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::Struct(..) | hir::ItemKind::Union(..) => {
- record!(self.tables.children[def_id] <-
+ record_array!(self.tables.children[def_id] <-
self.tcx.adt_def(def_id).non_enum_variant().fields.iter().map(|f| {
assert!(f.did.is_local());
f.did.index
}
hir::ItemKind::Impl { .. } | hir::ItemKind::Trait(..) => {
let associated_item_def_ids = self.tcx.associated_item_def_ids(def_id);
- record!(self.tables.children[def_id] <-
+ record_array!(self.tables.children[def_id] <-
associated_item_def_ids.iter().map(|&def_id| {
assert!(def_id.is_local());
def_id.index
}
if let hir::ItemKind::Fn(..) = item.kind {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+ if tcx.is_intrinsic(def_id) {
+ self.tables.is_intrinsic.set(def_id.index, ());
+ }
}
if let hir::ItemKind::Impl { .. } = item.kind {
if let Some(trait_ref) = self.tcx.impl_trait_ref(def_id) {
self.encode_item_type(def_id.to_def_id());
}
- fn encode_native_libraries(&mut self) -> Lazy<[NativeLib]> {
+ fn encode_native_libraries(&mut self) -> LazyArray<NativeLib> {
empty_proc_macro!(self);
let used_libraries = self.tcx.native_libraries(LOCAL_CRATE);
- self.lazy(used_libraries.iter())
+ self.lazy_array(used_libraries.iter())
}
- fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> {
+ fn encode_foreign_modules(&mut self) -> LazyArray<ForeignModule> {
empty_proc_macro!(self);
let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE);
- self.lazy(foreign_modules.iter().map(|(_, m)| m).cloned())
+ self.lazy_array(foreign_modules.iter().map(|(_, m)| m).cloned())
}
fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) {
let mut expn_data_table: TableBuilder<_, _> = Default::default();
let mut expn_hash_table: TableBuilder<_, _> = Default::default();
- let _: Result<(), !> = self.hygiene_ctxt.encode(
+ self.hygiene_ctxt.encode(
&mut (&mut *self, &mut syntax_contexts, &mut expn_data_table, &mut expn_hash_table),
|(this, syntax_contexts, _, _), index, ctxt_data| {
syntax_contexts.set(index, this.lazy(ctxt_data));
- Ok(())
},
|(this, _, expn_data_table, expn_hash_table), index, expn_data, hash| {
if let Some(index) = index.as_local() {
expn_data_table.set(index.as_raw(), this.lazy(expn_data));
expn_hash_table.set(index.as_raw(), this.lazy(hash));
}
- Ok(())
},
);
let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index;
let stability = tcx.lookup_stability(CRATE_DEF_ID);
let macros =
- self.lazy(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
+ self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index));
let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans();
for (i, span) in spans.into_iter().enumerate() {
let span = self.lazy(span);
}
}
- fn encode_debugger_visualizers(&mut self) -> Lazy<[DebuggerVisualizerFile]> {
+ fn encode_debugger_visualizers(&mut self) -> LazyArray<DebuggerVisualizerFile> {
empty_proc_macro!(self);
- self.lazy(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
+ self.lazy_array(self.tcx.debugger_visualizers(LOCAL_CRATE).iter())
}
- fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> {
+ fn encode_crate_deps(&mut self) -> LazyArray<CrateDep> {
empty_proc_macro!(self);
let deps = self
// the assumption that they are numbered 1 to n.
// FIXME (#2166): This is not nearly enough to support correct versioning
// but is enough to get transitive crate dependencies working.
- self.lazy(deps.iter().map(|&(_, ref dep)| dep))
+ self.lazy_array(deps.iter().map(|&(_, ref dep)| dep))
}
- fn encode_lib_features(&mut self) -> Lazy<[(Symbol, Option<Symbol>)]> {
+ fn encode_lib_features(&mut self) -> LazyArray<(Symbol, Option<Symbol>)> {
empty_proc_macro!(self);
let tcx = self.tcx;
let lib_features = tcx.lib_features(());
- self.lazy(lib_features.to_vec())
+ self.lazy_array(lib_features.to_vec())
}
- fn encode_diagnostic_items(&mut self) -> Lazy<[(Symbol, DefIndex)]> {
+ fn encode_diagnostic_items(&mut self) -> LazyArray<(Symbol, DefIndex)> {
empty_proc_macro!(self);
let tcx = self.tcx;
let diagnostic_items = &tcx.diagnostic_items(LOCAL_CRATE).name_to_id;
- self.lazy(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
+ self.lazy_array(diagnostic_items.iter().map(|(&name, def_id)| (name, def_id.index)))
}
- fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> {
+ fn encode_lang_items(&mut self) -> LazyArray<(DefIndex, usize)> {
empty_proc_macro!(self);
let tcx = self.tcx;
let lang_items = tcx.lang_items();
let lang_items = lang_items.items().iter();
- self.lazy(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
+ self.lazy_array(lang_items.enumerate().filter_map(|(i, &opt_def_id)| {
if let Some(def_id) = opt_def_id {
if def_id.is_local() {
return Some((def_id.index, i));
}))
}
- fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> {
+ fn encode_lang_items_missing(&mut self) -> LazyArray<lang_items::LangItem> {
empty_proc_macro!(self);
let tcx = self.tcx;
- self.lazy(&tcx.lang_items().missing)
+ self.lazy_array(&tcx.lang_items().missing)
}
- fn encode_traits(&mut self) -> Lazy<[DefIndex]> {
+ fn encode_traits(&mut self) -> LazyArray<DefIndex> {
empty_proc_macro!(self);
- self.lazy(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
+ self.lazy_array(self.tcx.traits_in_crate(LOCAL_CRATE).iter().map(|def_id| def_id.index))
}
/// Encodes an index, mapping each trait to its (local) implementations.
- fn encode_impls(&mut self) -> Lazy<[TraitImpls]> {
+ fn encode_impls(&mut self) -> LazyArray<TraitImpls> {
debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self);
let tcx = self.tcx;
let simplified_self_ty = fast_reject::simplify_type(
self.tcx,
trait_ref.self_ty(),
- TreatParams::AsPlaceholders,
+ TreatParams::AsInfer,
);
fx_hash_map
TraitImpls {
trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index),
- impls: self.lazy(&impls),
+ impls: self.lazy_array(&impls),
}
})
.collect();
- self.lazy(&all_impls)
+ self.lazy_array(&all_impls)
}
- fn encode_incoherent_impls(&mut self) -> Lazy<[IncoherentImpls]> {
+ fn encode_incoherent_impls(&mut self) -> LazyArray<IncoherentImpls> {
debug!("EncodeContext::encode_traits_and_impls()");
empty_proc_macro!(self);
let tcx = self.tcx;
tcx.hir().def_path_hash(LocalDefId { local_def_index })
});
- IncoherentImpls { self_ty: simp, impls: self.lazy(impls) }
+ IncoherentImpls { self_ty: simp, impls: self.lazy_array(impls) }
})
.collect();
- self.lazy(&all_impls)
+ self.lazy_array(&all_impls)
}
// Encodes all symbols exported from this crate into the metadata.
fn encode_exported_symbols(
&mut self,
exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportInfo)],
- ) -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportInfo)]> {
+ ) -> LazyArray<(ExportedSymbol<'static>, SymbolExportInfo)> {
empty_proc_macro!(self);
// The metadata symbol name is special. It should not show up in
// downstream crates.
let metadata_symbol_name = SymbolName::new(self.tcx, &metadata_symbol_name(self.tcx));
- self.lazy(
+ self.lazy_array(
exported_symbols
.iter()
.filter(|&&(ref exported_symbol, _)| match *exported_symbol {
)
}
- fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option<LinkagePreference>]> {
+ fn encode_dylib_dependency_formats(&mut self) -> LazyArray<Option<LinkagePreference>> {
empty_proc_macro!(self);
let formats = self.tcx.dependency_formats(());
for (ty, arr) in formats.iter() {
if *ty != CrateType::Dylib {
continue;
}
- return self.lazy(arr.iter().map(|slot| match *slot {
+ return self.lazy_array(arr.iter().map(|slot| match *slot {
Linkage::NotLinked | Linkage::IncludedFromDylib => None,
Linkage::Dynamic => Some(LinkagePreference::RequireDynamic),
Linkage::Static => Some(LinkagePreference::RequireStatic),
}));
}
- Lazy::empty()
+ LazyArray::empty()
}
fn encode_info_for_foreign_item(&mut self, def_id: DefId, nitem: &hir::ForeignItem<'_>) {
match nitem.kind {
hir::ForeignItemKind::Fn(_, ref names, _) => {
self.tables.asyncness.set(def_id.index, hir::IsAsync::NotAsync);
- record!(self.tables.fn_arg_names[def_id] <- *names);
+ record_array!(self.tables.fn_arg_names[def_id] <- *names);
let constness = if self.tcx.is_const_fn_raw(def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
- self.tables.impl_constness.set(def_id.index, constness);
+ self.tables.constness.set(def_id.index, constness);
record!(self.tables.kind[def_id] <- EntryKind::ForeignFn);
}
hir::ForeignItemKind::Static(..) => {
record!(self.tables.kind[def_id] <- EntryKind::ForeignType);
}
}
- self.encode_ident_span(def_id, nitem.ident);
self.encode_item_type(def_id);
if let hir::ForeignItemKind::Fn(..) = nitem.kind {
record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id));
+ if tcx.is_intrinsic(def_id) {
+ self.tables.is_intrinsic.set(def_id.index, ());
+ }
}
}
}
}
fn encode_info_for_expr(&mut self, expr: &hir::Expr<'_>) {
- if let hir::ExprKind::Closure(..) = expr.kind {
+ if let hir::ExprKind::Closure { .. } = expr.kind {
self.encode_info_for_closure(expr.hir_id);
}
}
- fn encode_ident_span(&mut self, def_id: DefId, ident: Ident) {
- record!(self.tables.def_ident_span[def_id] <- ident.span);
- }
-
/// In some cases, along with the item itself, we also
/// encode some sub-items. Usually we want some info from the item
/// so it's easier to do that here then to wait until we would encounter
}
fn encode_metadata_impl(tcx: TyCtxt<'_>) -> EncodedMetadata {
- let mut encoder = opaque::Encoder::new(vec![]);
- encoder.emit_raw_bytes(METADATA_HEADER).unwrap();
+ let mut encoder = MemEncoder::new();
+ encoder.emit_raw_bytes(METADATA_HEADER);
// Will be filled with the root position after encoding everything.
- encoder.emit_raw_bytes(&[0, 0, 0, 0]).unwrap();
+ encoder.emit_raw_bytes(&[0, 0, 0, 0]);
let source_map_files = tcx.sess.source_map().files();
let source_file_cache = (source_map_files[0].clone(), 0);
};
// Encode the rustc version string in a predictable location.
- rustc_version().encode(&mut ecx).unwrap();
+ rustc_version().encode(&mut ecx);
// Encode all the entries and extra information in the crate,
// culminating in the `CrateRoot` which points to all of it.
let root = ecx.encode_crate_root();
- let mut result = ecx.opaque.into_inner();
+ let mut result = ecx.opaque.finish();
// Encode the root position.
let header = METADATA_HEADER.len();
traits_in_crate: |tcx, cnum| {
assert_eq!(cnum, LOCAL_CRATE);
- #[derive(Default)]
- struct TraitsVisitor {
- traits: Vec<DefId>,
- }
- impl ItemLikeVisitor<'_> for TraitsVisitor {
- fn visit_item(&mut self, item: &hir::Item<'_>) {
- if let hir::ItemKind::Trait(..) | hir::ItemKind::TraitAlias(..) = item.kind {
- self.traits.push(item.def_id.to_def_id());
- }
+ 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())
}
- fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'_>) {}
- fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'_>) {}
- fn visit_foreign_item(&mut self, _foreign_item: &hir::ForeignItem<'_>) {}
}
- let mut visitor = TraitsVisitor::default();
- tcx.hir().visit_all_item_likes(&mut visitor);
// Bring everything into deterministic order.
- visitor.traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
- tcx.arena.alloc_slice(&visitor.traits)
+ traits.sort_by_cached_key(|&def_id| tcx.def_path_hash(def_id));
+ tcx.arena.alloc_slice(&traits)
},
..*providers