From f51e6c708431f0f4de2a830c67be20d6242fdef9 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 20:05:36 +0300 Subject: [PATCH 01/14] rustc_metadata: more safely read/write the index positions. --- src/librustc_metadata/index.rs | 125 +++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 45 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 18f30383090cd..f9543a18c68a7 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -2,10 +2,71 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; use rustc_serialize::opaque::Encoder; -use std::slice; use std::u32; use log::debug; +/// Helper trait, for encoding to, and decoding from, a fixed number of bytes. +pub trait FixedSizeEncoding { + const BYTE_LEN: usize; + + // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, + // once that starts being allowed by the compiler (i.e. lazy normalization). + fn from_bytes(b: &[u8]) -> Self; + fn write_to_bytes(self, b: &mut [u8]); + + // FIXME(eddyb) make these generic functions, or at least defaults here. + // (same problem as above, needs `[u8; Self::BYTE_LEN]`) + // For now, a macro (`fixed_size_encoding_byte_len_and_defaults`) is used. + fn read_from_bytes_at(b: &[u8], i: usize) -> Self; + fn write_to_bytes_at(self, b: &mut [u8], i: usize); +} + +// HACK(eddyb) this shouldn't be needed (see comments on the methods above). +macro_rules! fixed_size_encoding_byte_len_and_defaults { + ($byte_len:expr) => { + const BYTE_LEN: usize = $byte_len; + fn read_from_bytes_at(b: &[u8], i: usize) -> Self { + const BYTE_LEN: usize = $byte_len; + // HACK(eddyb) ideally this would be done with fully safe code, + // but slicing `[u8]` with `i * N..` is optimized worse, due to the + // possibility of `i * N` overflowing, than indexing `[[u8; N]]`. + let b = unsafe { + std::slice::from_raw_parts( + b.as_ptr() as *const [u8; BYTE_LEN], + b.len() / BYTE_LEN, + ) + }; + Self::from_bytes(&b[i]) + } + fn write_to_bytes_at(self, b: &mut [u8], i: usize) { + const BYTE_LEN: usize = $byte_len; + // HACK(eddyb) ideally this would be done with fully safe code, + // see similar comment in `read_from_bytes_at` for why it can't yet. + let b = unsafe { + std::slice::from_raw_parts_mut( + b.as_mut_ptr() as *mut [u8; BYTE_LEN], + b.len() / BYTE_LEN, + ) + }; + self.write_to_bytes(&mut b[i]); + } + } +} + +impl FixedSizeEncoding for u32 { + fixed_size_encoding_byte_len_and_defaults!(4); + + fn from_bytes(b: &[u8]) -> Self { + let mut bytes = [0; Self::BYTE_LEN]; + bytes.copy_from_slice(&b[..Self::BYTE_LEN]); + Self::from_le_bytes(bytes) + } + + fn write_to_bytes(self, b: &mut [u8]) { + b[..Self::BYTE_LEN].copy_from_slice(&self.to_le_bytes()); + } +} + /// While we are generating the metadata, we also track the position /// of each DefIndex. It is not required that all definitions appear /// in the metadata, nor that they are serialized in order, and @@ -14,14 +75,14 @@ use log::debug; /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. pub struct Index { - positions: [Vec; 2] + positions: [Vec; 2] } impl Index { pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index { Index { - positions: [vec![u32::MAX; max_index_lo], - vec![u32::MAX; max_index_hi]], + positions: [vec![0xff; max_index_lo * 4], + vec![0xff; max_index_hi * 4]], } } @@ -36,26 +97,27 @@ impl Index { let space_index = item.address_space().index(); let array_index = item.as_array_index(); - assert!(self.positions[space_index][array_index] == u32::MAX, + let positions = &mut self.positions[space_index]; + assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX, "recorded position for item {:?} twice, first at {:?} and now at {:?}", item, - self.positions[space_index][array_index], + u32::read_from_bytes_at(positions, array_index), position); - self.positions[space_index][array_index] = position.to_le(); + position.write_to_bytes_at(positions, array_index) } pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { let pos = buf.position(); // First we write the length of the lower range ... - buf.emit_raw_bytes(words_to_bytes(&[(self.positions[0].len() as u32).to_le()])); + buf.emit_raw_bytes(&(self.positions[0].len() as u32 / 4).to_le_bytes()); // ... then the values in the lower range ... - buf.emit_raw_bytes(words_to_bytes(&self.positions[0][..])); + buf.emit_raw_bytes(&self.positions[0]); // ... then the values in the higher range. - buf.emit_raw_bytes(words_to_bytes(&self.positions[1][..])); + buf.emit_raw_bytes(&self.positions[1]); LazySeq::with_position_and_length(pos as usize, - self.positions[0].len() + self.positions[1].len() + 1) + (self.positions[0].len() + self.positions[1].len()) / 4 + 1) } } @@ -64,24 +126,21 @@ impl<'tcx> LazySeq { /// DefIndex (if any). #[inline(never)] pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { - let words = &bytes_to_words(&bytes[self.position..])[..self.len]; - - debug!("Index::lookup: index={:?} words.len={:?}", + let bytes = &bytes[self.position..]; + debug!("Index::lookup: index={:?} len={:?}", def_index, - words.len()); + self.len); - let positions = match def_index.address_space() { - DefIndexAddressSpace::Low => &words[1..], + let i = def_index.as_array_index() + match def_index.address_space() { + DefIndexAddressSpace::Low => 0, DefIndexAddressSpace::High => { // This is a DefIndex in the higher range, so find out where // that starts: - let lo_count = u32::from_le(words[0].get()) as usize; - &words[lo_count + 1 .. ] + u32::read_from_bytes_at(bytes, 0) as usize } }; - let array_index = def_index.as_array_index(); - let position = u32::from_le(positions[array_index].get()); + let position = u32::read_from_bytes_at(bytes, 1 + i); if position == u32::MAX { debug!("Index::lookup: position=u32::MAX"); None @@ -91,27 +150,3 @@ impl<'tcx> LazySeq { } } } - -#[repr(packed)] -#[derive(Copy)] -struct Unaligned(T); - -// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to -// the field to `T::clone`, but this reference may not be properly aligned. -impl Clone for Unaligned { - fn clone(&self) -> Self { - *self - } -} - -impl Unaligned { - fn get(self) -> T { self.0 } -} - -fn bytes_to_words(b: &[u8]) -> &[Unaligned] { - unsafe { slice::from_raw_parts(b.as_ptr() as *const Unaligned, b.len() / 4) } -} - -fn words_to_bytes(w: &[u32]) -> &[u8] { - unsafe { slice::from_raw_parts(w.as_ptr() as *const u8, w.len() * 4) } -} From 35d2f64e894f7b074fbd1718d1f16d844b658c1f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 10:22:02 +0300 Subject: [PATCH 02/14] rustc_metadata: parametrize schema::CrateRoot by 'tcx. --- src/librustc_metadata/creader.rs | 6 +++--- src/librustc_metadata/cstore.rs | 6 +++++- src/librustc_metadata/cstore_impl.rs | 7 +------ src/librustc_metadata/decoder.rs | 11 ++++------- src/librustc_metadata/encoder.rs | 17 ++++++----------- src/librustc_metadata/index.rs | 19 +++++++++++-------- src/librustc_metadata/index_builder.rs | 4 ++-- src/librustc_metadata/lib.rs | 1 + src/librustc_metadata/schema.rs | 13 ++++--------- 9 files changed, 37 insertions(+), 47 deletions(-) diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 160d4c30c0bad..aa8f0a499a73e 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -162,7 +162,7 @@ impl<'a> CrateLoader<'a> { fn verify_no_symbol_conflicts(&self, span: Span, - root: &CrateRoot) { + root: &CrateRoot<'_>) { // Check for (potential) conflicts with the local crate if self.local_crate_name == root.name && self.sess.local_crate_disambiguator() == root.disambiguator { @@ -476,7 +476,7 @@ impl<'a> CrateLoader<'a> { // Go through the crate metadata and load any crates that it references fn resolve_crate_deps(&mut self, root: &Option, - crate_root: &CrateRoot, + crate_root: &CrateRoot<'_>, metadata: &MetadataBlob, krate: CrateNum, span: Span, @@ -582,7 +582,7 @@ impl<'a> CrateLoader<'a> { /// implemented as dynamic libraries, but we have a possible future where /// custom derive (and other macro-1.1 style features) are implemented via /// executables and custom IPC. - fn load_derive_macros(&mut self, root: &CrateRoot, dylib: Option, span: Span) + fn load_derive_macros(&mut self, root: &CrateRoot<'_>, dylib: Option, span: Span) -> Vec<(ast::Name, Lrc)> { use std::{env, mem}; use crate::dynamic_lib::DynamicLibrary; diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 22a13f37722b8..5d8fabc7e69ae 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -64,7 +64,11 @@ pub struct CrateMetadata { /// Used for decoding interpret::AllocIds in a cached & thread-safe manner. pub alloc_decoding_state: AllocDecodingState, - pub root: schema::CrateRoot, + // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this + // lifetime is only used behind `Lazy` / `LazySeq`, and therefore + // acts like an universal (`for<'tcx>`), that is paired up with + // whichever `TyCtxt` is being used to decode those values. + pub root: schema::CrateRoot<'static>, /// For each public item in this crate, we encode a key. When the /// crate is loaded, we read all the keys and put them in this diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index 10a99e40c419c..3cd2db6bc3129 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -245,12 +245,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, used_crate_source => { Lrc::new(cdata.source.clone()) } - exported_symbols => { - let cnum = cdata.cnum; - assert!(cnum != LOCAL_CRATE); - - Arc::new(cdata.exported_symbols(tcx)) - } + exported_symbols => { Arc::new(cdata.exported_symbols(tcx)) } } pub fn provide<'tcx>(providers: &mut Providers<'tcx>) { diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 5dade8d943893..a042a14166522 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -366,7 +366,7 @@ for DecodeContext<'a, 'tcx> { implement_ty_decoder!( DecodeContext<'a, 'tcx> ); -impl<'a, 'tcx> MetadataBlob { +impl<'tcx> MetadataBlob { pub fn is_compatible(&self) -> bool { self.raw_bytes().starts_with(METADATA_HEADER) } @@ -375,7 +375,7 @@ impl<'a, 'tcx> MetadataBlob { Lazy::with_position(METADATA_HEADER.len() + 4).decode(self) } - pub fn get_root(&self) -> CrateRoot { + pub fn get_root(&self) -> CrateRoot<'tcx> { let slice = self.raw_bytes(); let offset = METADATA_HEADER.len(); let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | @@ -445,7 +445,7 @@ impl<'tcx> EntryKind<'tcx> { /// |- proc macro #0 (DefIndex 1:N) /// |- proc macro #1 (DefIndex 1:N+1) /// \- ... -crate fn proc_macro_def_path_table(crate_root: &CrateRoot, +crate fn proc_macro_def_path_table(crate_root: &CrateRoot<'_>, proc_macros: &[(ast::Name, Lrc)]) -> DefPathTable { @@ -1122,10 +1122,7 @@ impl<'a, 'tcx> CrateMetadata { // link those in so we skip those crates. vec![] } else { - let lazy_seq: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> = - LazySeq::with_position_and_length(self.root.exported_symbols.position, - self.root.exported_symbols.len); - lazy_seq.decode((self, tcx)).collect() + self.root.exported_symbols.decode((self, tcx)).collect() } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 796d2f6a18ba3..f30eaab73d704 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -309,7 +309,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { op(&mut IsolatedEncoder::new(self), data) } - fn encode_info_for_items(&mut self) -> Index { + fn encode_info_for_items(&mut self) -> Index<'tcx> { let krate = self.tcx.hir().krate(); let mut index = IndexBuilder::new(self); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; @@ -371,7 +371,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) } - fn encode_crate_root(&mut self) -> Lazy { + fn encode_crate_root(&mut self) -> Lazy> { let mut i = self.position(); let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ()); @@ -1590,13 +1590,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // symbol associated with them (they weren't translated) or if they're an FFI // definition (as that's not defined in this crate). fn encode_exported_symbols(&mut self, - exported_symbols: &[(ExportedSymbol<'_>, SymbolExportLevel)]) - -> EncodedExportedSymbols { + exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)]) + -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> { // The metadata symbol name is special. It should not show up in // downstream crates. let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); - let lazy_seq = self.lazy_seq(exported_symbols + self.lazy_seq(exported_symbols .iter() .filter(|&&(ref exported_symbol, _)| { match *exported_symbol { @@ -1606,12 +1606,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { _ => true, } }) - .cloned()); - - EncodedExportedSymbols { - len: lazy_seq.len, - position: lazy_seq.position, - } + .cloned()) } fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index f9543a18c68a7..702ed901b5cd3 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -2,6 +2,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; use rustc_serialize::opaque::Encoder; +use std::marker::PhantomData; use std::u32; use log::debug; @@ -74,24 +75,26 @@ impl FixedSizeEncoding for u32 { /// `u32::MAX`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -pub struct Index { - positions: [Vec; 2] +pub struct Index<'tcx> { + positions: [Vec; 2], + _marker: PhantomData<&'tcx ()>, } -impl Index { - pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Index { +impl Index<'tcx> { + pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { Index { positions: [vec![0xff; max_index_lo * 4], vec![0xff; max_index_hi * 4]], + _marker: PhantomData, } } - pub fn record(&mut self, def_id: DefId, entry: Lazy>) { + pub fn record(&mut self, def_id: DefId, entry: Lazy>) { assert!(def_id.is_local()); self.record_index(def_id.index, entry); } - pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { assert!(entry.position < (u32::MAX as usize)); let position = entry.position as u32; let space_index = item.address_space().index(); @@ -107,7 +110,7 @@ impl Index { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { + pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { let pos = buf.position(); // First we write the length of the lower range ... @@ -121,7 +124,7 @@ impl Index { } } -impl<'tcx> LazySeq { +impl LazySeq> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs index 8343171b99f4b..c52ad5e928226 100644 --- a/src/librustc_metadata/index_builder.rs +++ b/src/librustc_metadata/index_builder.rs @@ -60,7 +60,7 @@ use std::ops::{Deref, DerefMut}; /// Builder that can encode new items, adding them into the index. /// Item encoding cannot be nested. pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { - items: Index, + items: Index<'tcx>, pub ecx: &'a mut EncodeContext<'b, 'tcx>, } @@ -123,7 +123,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { }) } - pub fn into_items(self) -> Index { + pub fn into_items(self) -> Index<'tcx> { self.items } } diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 4078171733fc3..05ecb4cb1630d 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -2,6 +2,7 @@ #![feature(box_patterns)] #![feature(drain_filter)] +#![feature(in_band_lifetimes)] #![feature(libc)] #![feature(nll)] #![feature(proc_macro_internals)] diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 504c7da7d6b9e..b2f6fd65ed445 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -4,6 +4,7 @@ use rustc::hir; use rustc::hir::def::{self, CtorKind}; use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; use rustc::ich::StableHashingContext; +use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule}; use rustc::middle::lang_items; use rustc::mir; @@ -174,7 +175,7 @@ pub enum LazyState { } #[derive(RustcEncodable, RustcDecodable)] -pub struct CrateRoot { +pub struct CrateRoot<'tcx> { pub name: Symbol, pub triple: TargetTriple, pub extra_filename: String, @@ -199,10 +200,10 @@ pub struct CrateRoot { pub source_map: LazySeq, pub def_path_table: Lazy, pub impls: LazySeq, - pub exported_symbols: EncodedExportedSymbols, + pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, pub interpret_alloc_index: LazySeq, - pub index: LazySeq, + pub index: LazySeq>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -577,9 +578,3 @@ impl_stable_hash_for!(struct GeneratorData<'tcx> { layout }); // Tags used for encoding Spans: pub const TAG_VALID_SPAN: u8 = 0; pub const TAG_INVALID_SPAN: u8 = 1; - -#[derive(RustcEncodable, RustcDecodable)] -pub struct EncodedExportedSymbols { - pub position: usize, - pub len: usize, -} From 6ae65dded1c889ff504539167372e71d62835f48 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 11:54:27 +0300 Subject: [PATCH 03/14] rustc_metadata: rip out unused incremental infrastructure. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 274 ++++++++++------------ src/librustc_metadata/index_builder.rs | 224 ------------------ src/librustc_metadata/isolated_encoder.rs | 48 ---- src/librustc_metadata/lib.rs | 2 - src/librustc_metadata/schema.rs | 198 +--------------- 6 files changed, 125 insertions(+), 623 deletions(-) delete mode 100644 src/librustc_metadata/index_builder.rs delete mode 100644 src/librustc_metadata/isolated_encoder.rs diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a042a14166522..f51c7ed2ec6c9 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -477,7 +477,7 @@ impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { assert!(!self.is_proc_macro(item_id)); - self.root.index.lookup(self.blob.raw_bytes(), item_id) + self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f30eaab73d704..520bac41ba345 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,6 +1,4 @@ use crate::index::Index; -use crate::index_builder::{FromId, IndexBuilder, Untracked}; -use crate::isolated_encoder::IsolatedEncoder; use crate::schema::*; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, @@ -46,6 +44,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + entries_index: Index<'tcx>, + lazy_state: LazyState, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, @@ -300,28 +300,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) } - // Encodes something that corresponds to a single DepNode::GlobalMetaData - // and registers the Fingerprint in the `metadata_hashes` map. - pub fn tracked<'x, DATA, R>(&'x mut self, - op: fn(&mut IsolatedEncoder<'x, 'a, 'tcx>, DATA) -> R, - data: DATA) - -> R { - op(&mut IsolatedEncoder::new(self), data) + /// Emit the data for a `DefId` to the metadata. The function to + /// emit the data is `op`, and it will be given `data` as + /// arguments. This `record` function will call `op` to generate + /// the `Entry` (which may point to other encoded information) + /// and will then record the `Lazy` for use in the index. + // FIXME(eddyb) remove this. + pub fn record(&mut self, + id: DefId, + op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, + data: DATA) + { + assert!(id.is_local()); + + let entry = op(self, data); + let entry = self.lazy(&entry); + self.entries_index.record(id, entry); } - fn encode_info_for_items(&mut self) -> Index<'tcx> { + fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); - let mut index = IndexBuilder::new(self); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; - index.record(DefId::local(CRATE_DEF_INDEX), - IsolatedEncoder::encode_info_for_mod, - FromId(hir::CRATE_HIR_ID, (&krate.module, &krate.attrs, &vis))); - let mut visitor = EncodeVisitor { index }; - krate.visit_all_item_likes(&mut visitor.as_deep_visitor()); + self.record(DefId::local(CRATE_DEF_INDEX), + EncodeContext::encode_info_for_mod, + (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis)); + krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in &krate.exported_macros { - visitor.visit_macro_def(macro_def); + self.visit_macro_def(macro_def); } - visitor.index.into_items() } fn encode_def_path_table(&mut self) -> Lazy { @@ -374,35 +380,27 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_crate_root(&mut self) -> Lazy> { let mut i = self.position(); - let crate_deps = self.tracked(IsolatedEncoder::encode_crate_deps, ()); - let dylib_dependency_formats = self.tracked( - IsolatedEncoder::encode_dylib_dependency_formats, - ()); + 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.tracked(IsolatedEncoder::encode_lib_features, ()); + let lib_features = self.encode_lib_features(); let lib_feature_bytes = self.position() - i; // Encode the language items. i = self.position(); - let lang_items = self.tracked(IsolatedEncoder::encode_lang_items, ()); - let lang_items_missing = self.tracked( - IsolatedEncoder::encode_lang_items_missing, - ()); + 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 native libraries used i = self.position(); - let native_libraries = self.tracked( - IsolatedEncoder::encode_native_libraries, - ()); + let native_libraries = self.encode_native_libraries(); let native_lib_bytes = self.position() - i; - let foreign_modules = self.tracked( - IsolatedEncoder::encode_foreign_modules, - ()); + let foreign_modules = self.encode_foreign_modules(); // Encode source_map i = self.position(); @@ -416,22 +414,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // Encode the def IDs of impls, for coherence checking. i = self.position(); - let impls = self.tracked(IsolatedEncoder::encode_impls, ()); + let impls = self.encode_impls(); let impl_bytes = self.position() - i; // Encode exported symbols info. i = self.position(); let exported_symbols = self.tcx.exported_symbols(LOCAL_CRATE); - let exported_symbols = self.tracked( - IsolatedEncoder::encode_exported_symbols, - &exported_symbols); + let exported_symbols = self.encode_exported_symbols(&exported_symbols); let exported_symbols_bytes = self.position() - i; let tcx = self.tcx; // Encode the items. i = self.position(); - let items = self.encode_info_for_items(); + self.encode_info_for_items(); let item_bytes = self.position() - i; // Encode the allocation index @@ -462,10 +458,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy_seq(interpret_alloc_index) }; - // Index the items i = self.position(); - let index = items.write_index(&mut self.opaque); - let index_bytes = self.position() - i; + let entries_index = self.entries_index.write_index(&mut self.opaque); + let entries_index_bytes = self.position() - i; let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); @@ -516,7 +511,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impls, exported_symbols, interpret_alloc_index, - index, + entries_index, }); let total_bytes = self.position(); @@ -539,7 +534,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); - println!(" index bytes: {}", index_bytes); + println!(" entries index bytes: {}", entries_index_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -548,40 +543,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } -// These are methods for encoding various things. They are meant to be used with -// IndexBuilder::record() and EncodeContext::tracked(). They actually -// would not have to be methods of IsolatedEncoder (free standing functions -// taking IsolatedEncoder as first argument would be just fine) but by making -// them methods we don't have to repeat the lengthy `<'a, 'b: 'a, 'tcx: 'b>` -// clause again and again. -impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { +impl EncodeContext<'_, 'tcx> { fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq { - debug!("IsolatedEncoder::encode_variances_of({:?})", def_id); + debug!("EncodeContext::encode_variances_of({:?})", def_id); let tcx = self.tcx; - self.lazy_seq_from_slice(&tcx.variances_of(def_id)) + self.lazy_seq_ref(&tcx.variances_of(def_id)[..]) } fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { let tcx = self.tcx; let ty = tcx.type_of(def_id); - debug!("IsolatedEncoder::encode_item_type({:?}) => {:?}", def_id, ty); + debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); self.lazy(&ty) } - /// Encode data for the given variant of the given ADT. The - /// index of the variant is untracked: this is ok because we - /// will have to lookup the adt-def by its id, and that gives us - /// the right to access any information in the adt-def (including, - /// e.g., the length of the various vectors). fn encode_enum_variant_info( &mut self, - (enum_did, Untracked(index)): (DefId, Untracked), + (enum_did, index): (DefId, VariantIdx), ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.def_id; - debug!("IsolatedEncoder::encode_enum_variant_info({:?})", def_id); + debug!("EncodeContext::encode_enum_variant_info({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, @@ -620,17 +604,15 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - /// Encode the constructor for the given variant of the given ADT. See - /// `encode_enum_variant_info` for an explanation about why the index is untracked. fn encode_enum_variant_ctor( &mut self, - (enum_did, Untracked(index)): (DefId, Untracked), + (enum_did, index): (DefId, VariantIdx), ) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; let def_id = variant.ctor_def_id.unwrap(); - debug!("IsolatedEncoder::encode_enum_variant_ctor({:?})", def_id); + debug!("EncodeContext::encode_enum_variant_ctor({:?})", def_id); let data = VariantData { ctor_kind: variant.ctor_kind, @@ -676,18 +658,17 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - fn encode_info_for_mod(&mut self, - FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, - &[ast::Attribute], - &hir::Visibility)>) - -> Entry<'tcx> { + fn encode_info_for_mod( + &mut self, + (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility), + ) -> Entry<'tcx> { let tcx = self.tcx; let def_id = tcx.hir().local_def_id_from_hir_id(id); - debug!("IsolatedEncoder::encode_info_for_mod({:?})", def_id); + debug!("EncodeContext::encode_info_for_mod({:?})", def_id); let data = ModData { reexports: match tcx.module_exports(def_id) { - Some(ref exports) => self.lazy_seq_from_slice(exports.as_slice()), + Some(ref exports) => self.lazy_seq_ref(&exports[..]), _ => LazySeq::empty(), }, }; @@ -714,23 +695,16 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } - /// Encode data for the given field of the given variant of the - /// given ADT. The indices of the variant/field are untracked: - /// this is ok because we will have to lookup the adt-def by its - /// id, and that gives us the right to access any information in - /// the adt-def (including, e.g., the length of the various - /// vectors). - fn encode_field(&mut self, - (adt_def_id, Untracked((variant_index, field_index))): (DefId, - Untracked<(VariantIdx, - usize)>)) - -> Entry<'tcx> { + fn encode_field( + &mut self, + (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize), + ) -> Entry<'tcx> { let tcx = self.tcx; let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; let def_id = field.did; - debug!("IsolatedEncoder::encode_field({:?})", def_id); + debug!("EncodeContext::encode_field({:?})", def_id); let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); @@ -756,7 +730,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id); + debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let adt_def = tcx.adt_def(adt_def_id); let variant = adt_def.non_enum_variant(); @@ -816,25 +790,25 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_generics(&mut self, def_id: DefId) -> Lazy { - debug!("IsolatedEncoder::encode_generics({:?})", def_id); + debug!("EncodeContext::encode_generics({:?})", def_id); let tcx = self.tcx; self.lazy(tcx.generics_of(def_id)) } fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { - debug!("IsolatedEncoder::encode_predicates({:?})", def_id); + debug!("EncodeContext::encode_predicates({:?})", def_id); let tcx = self.tcx; self.lazy(&tcx.predicates_of(def_id)) } fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { - debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id); + debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); let tcx = self.tcx; self.lazy(&tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -944,7 +918,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -1059,7 +1033,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { - debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id); + debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); if implementations.is_empty() { LazySeq::empty() @@ -1072,12 +1046,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_stability(&mut self, def_id: DefId) -> Option> { - debug!("IsolatedEncoder::encode_stability({:?})", def_id); + debug!("EncodeContext::encode_stability({:?})", def_id); self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) } fn encode_deprecation(&mut self, def_id: DefId) -> Option> { - debug!("IsolatedEncoder::encode_deprecation({:?})", def_id); + debug!("EncodeContext::encode_deprecation({:?})", def_id); self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) } @@ -1091,7 +1065,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { let tcx = self.tcx; - debug!("IsolatedEncoder::encode_info_for_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_item({:?})", def_id); let kind = match item.node { hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, @@ -1113,7 +1087,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { EntryKind::Fn(self.lazy(&data)) } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(FromId(item.hir_id, (m, &item.attrs, &item.vis))); + return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); } hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, @@ -1386,9 +1360,9 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { fn encode_info_for_ty_param( &mut self, - (def_id, Untracked(encode_type)): (DefId, Untracked), + (def_id, encode_type): (DefId, bool), ) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_ty_param({:?})", def_id); + debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id); self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) } @@ -1396,12 +1370,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { &mut self, def_id: DefId, ) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id); + debug!("EncodeContext::encode_info_for_const_param({:?})", def_id); self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) } fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id); + debug!("EncodeContext::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; let tables = self.tcx.typeck_tables_of(def_id); @@ -1445,7 +1419,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_anon_const({:?})", def_id); + debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir().as_local_hir_id(def_id).unwrap(); let body_id = tcx.hir().body_owned_by(id); @@ -1473,23 +1447,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { - // NOTE: This must use lazy_seq_from_slice(), not lazy_seq() because - // we rely on the HashStable specialization for [Attribute] - // to properly filter things out. - self.lazy_seq_from_slice(attrs) + self.lazy_seq_ref(attrs) } - fn encode_native_libraries(&mut self, _: ()) -> LazySeq { + fn encode_native_libraries(&mut self) -> LazySeq { let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); self.lazy_seq(used_libraries.iter().cloned()) } - fn encode_foreign_modules(&mut self, _: ()) -> LazySeq { + fn encode_foreign_modules(&mut self) -> LazySeq { let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); self.lazy_seq(foreign_modules.iter().cloned()) } - fn encode_crate_deps(&mut self, _: ()) -> LazySeq { + fn encode_crate_deps(&mut self) -> LazySeq { let crates = self.tcx.crates(); let mut deps = crates @@ -1523,13 +1494,13 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { self.lazy_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) } - fn encode_lib_features(&mut self, _: ()) -> LazySeq<(ast::Name, Option)> { + fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option)> { let tcx = self.tcx; let lib_features = tcx.lib_features(); self.lazy_seq(lib_features.to_vec()) } - fn encode_lang_items(&mut self, _: ()) -> LazySeq<(DefIndex, usize)> { + fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> { let tcx = self.tcx; let lang_items = tcx.lang_items(); let lang_items = lang_items.items().iter(); @@ -1543,14 +1514,14 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { })) } - fn encode_lang_items_missing(&mut self, _: ()) -> LazySeq { + fn encode_lang_items_missing(&mut self) -> LazySeq { let tcx = self.tcx; self.lazy_seq_ref(&tcx.lang_items().missing) } /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self, _: ()) -> LazySeq { - debug!("IsolatedEncoder::encode_impls()"); + fn encode_impls(&mut self) -> LazySeq { + debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { tcx, @@ -1575,12 +1546,12 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { TraitImpls { trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy_seq_from_slice(&impls[..]), + impls: self.lazy_seq_ref(&impls), } }) .collect(); - self.lazy_seq_from_slice(&all_impls[..]) + self.lazy_seq_ref(&all_impls) } // Encodes all symbols exported from this crate into the metadata. @@ -1609,7 +1580,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { .cloned()) } - fn encode_dylib_dependency_formats(&mut self, _: ()) -> LazySeq> { + fn encode_dylib_dependency_formats(&mut self) -> LazySeq> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { Some(arr) => { self.lazy_seq(arr.iter().map(|slot| { @@ -1631,7 +1602,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { -> Entry<'tcx> { let tcx = self.tcx; - debug!("IsolatedEncoder::encode_info_for_foreign_item({:?})", def_id); + debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); let kind = match nitem.node { hir::ForeignItemKind::Fn(_, ref names, _) => { @@ -1671,33 +1642,29 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } } -struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { - index: IndexBuilder<'a, 'b, 'tcx>, -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { +impl Visitor<'tcx> for EncodeContext<'_, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::OnlyBodies(&self.index.tcx.hir()) + NestedVisitorMap::OnlyBodies(&self.tcx.hir()) } fn visit_expr(&mut self, ex: &'tcx hir::Expr) { intravisit::walk_expr(self, ex); - self.index.encode_info_for_expr(ex); + self.encode_info_for_expr(ex); } fn visit_item(&mut self, item: &'tcx hir::Item) { intravisit::walk_item(self, item); - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(item.hir_id); + let def_id = self.tcx.hir().local_def_id_from_hir_id(item.hir_id); match item.node { hir::ItemKind::ExternCrate(_) | - hir::ItemKind::Use(..) => (), // ignore these - _ => self.index.record(def_id, IsolatedEncoder::encode_info_for_item, (def_id, item)), + hir::ItemKind::Use(..) => {} // ignore these + _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), } - self.index.encode_addl_info_for_item(item); + self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(ni.hir_id); - self.index.record(def_id, - IsolatedEncoder::encode_info_for_foreign_item, + let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id); + self.record(def_id, + EncodeContext::encode_info_for_foreign_item, (def_id, ni)); } fn visit_variant(&mut self, @@ -1707,32 +1674,32 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { intravisit::walk_variant(self, v, g, id); if let Some(ref discr) = v.node.disr_expr { - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(discr.hir_id); - self.index.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); + let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id); + self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); } } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { intravisit::walk_generics(self, generics); - self.index.encode_info_for_generics(generics); + self.encode_info_for_generics(generics); } fn visit_ty(&mut self, ty: &'tcx hir::Ty) { intravisit::walk_ty(self, ty); - self.index.encode_info_for_ty(ty); + self.encode_info_for_ty(ty); } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.index.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); - self.index.record(def_id, IsolatedEncoder::encode_info_for_macro_def, macro_def); + let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); + self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); } } -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { +impl EncodeContext<'_, 'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter_enumerated() { for (field_index, field) in variant.fields.iter().enumerate() { self.record(field.did, - IsolatedEncoder::encode_field, - (adt_def_id, Untracked((variant_index, field_index)))); + EncodeContext::encode_field, + (adt_def_id, variant_index, field_index)); } } } @@ -1745,12 +1712,12 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { GenericParamKind::Type { ref default, .. } => { self.record( def_id, - IsolatedEncoder::encode_info_for_ty_param, - (def_id, Untracked(default.is_some())), + EncodeContext::encode_info_for_ty_param, + (def_id, default.is_some()), ); } GenericParamKind::Const { .. } => { - self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id); + self.record(def_id, EncodeContext::encode_info_for_const_param, def_id); } } } @@ -1760,7 +1727,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match ty.node { hir::TyKind::Array(_, ref length) => { let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id); - self.record(def_id, IsolatedEncoder::encode_info_for_anon_const, def_id); + self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); } _ => {} } @@ -1770,7 +1737,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match expr.node { hir::ExprKind::Closure(..) => { let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id); - self.record(def_id, IsolatedEncoder::encode_info_for_closure, def_id); + self.record(def_id, EncodeContext::encode_info_for_closure, def_id); } _ => {} } @@ -1802,13 +1769,13 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { self.record(variant.def_id, - IsolatedEncoder::encode_enum_variant_info, - (def_id, Untracked(i))); + EncodeContext::encode_enum_variant_info, + (def_id, i)); if let Some(ctor_def_id) = variant.ctor_def_id { self.record(ctor_def_id, - IsolatedEncoder::encode_enum_variant_ctor, - (def_id, Untracked(i))); + EncodeContext::encode_enum_variant_ctor, + (def_id, i)); } } } @@ -1819,7 +1786,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { if let Some(ctor_hir_id) = struct_def.ctor_hir_id() { let ctor_def_id = self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id); self.record(ctor_def_id, - IsolatedEncoder::encode_struct_ctor, + EncodeContext::encode_struct_ctor, (def_id, ctor_def_id)); } } @@ -1829,14 +1796,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { hir::ItemKind::Impl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.record(trait_item_def_id, - IsolatedEncoder::encode_info_for_impl_item, + EncodeContext::encode_info_for_impl_item, trait_item_def_id); } } hir::ItemKind::Trait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { self.record(item_def_id, - IsolatedEncoder::encode_info_for_trait_item, + EncodeContext::encode_info_for_trait_item, item_def_id); } } @@ -1901,10 +1868,13 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) // Will be filled with the root position after encoding everything. encoder.emit_raw_bytes(&[0, 0, 0, 0]); - let (root, mut result) = { + // Since encoding metadata is not in a query, and nothing is cached, + // there's no need to do dep-graph tracking for any of it. + let (root, mut result) = tcx.dep_graph.with_ignore(move || { let mut ecx = EncodeContext { opaque: encoder, tcx, + entries_index: Index::new(tcx.hir().definitions().def_index_counts_lo_hi()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), @@ -1920,7 +1890,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) // culminating in the `CrateRoot` which points to all of it. let root = ecx.encode_crate_root(); (root, ecx.opaque.into_inner()) - }; + }); // Encode the root position. let header = METADATA_HEADER.len(); diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs deleted file mode 100644 index c52ad5e928226..0000000000000 --- a/src/librustc_metadata/index_builder.rs +++ /dev/null @@ -1,224 +0,0 @@ -//! Builder types for generating the "item data" section of the -//! metadata. This section winds up looking like this: -//! -//! ``` -//! // big list of item-like things... -//! // ...for most `DefId`s, there is an entry. -//! -//! -//! ``` -//! -//! As we generate this listing, we collect the offset of each -//! `data_item` entry and store it in an index. Then, when we load the -//! metadata, we can skip right to the metadata for a particular item. -//! -//! In addition to the offset, we need to track the data that was used -//! to generate the contents of each `data_item`. This is so that we -//! can figure out which HIR nodes contributed to that data for -//! incremental compilation purposes. -//! -//! The `IndexBuilder` facilitates both of these. It is created -//! with an `EncodingContext` (`ecx`), which it encapsulates. -//! It has one main method, `record()`. You invoke `record` -//! like so to create a new `data_item` element in the list: -//! -//! ``` -//! index.record(some_def_id, callback_fn, data) -//! ``` -//! -//! What record will do is to (a) record the current offset, (b) emit -//! the `common::data_item` tag, and then call `callback_fn` with the -//! given data as well as the `EncodingContext`. Once `callback_fn` -//! returns, the `common::data_item` tag will be closed. -//! -//! `EncodingContext` does not offer the `record` method, so that we -//! can ensure that `common::data_item` elements are never nested. -//! -//! In addition, while the `callback_fn` is executing, we will push a -//! task `MetaData(some_def_id)`, which can then observe the -//! reads/writes that occur in the task. For this reason, the `data` -//! argument that is given to the `callback_fn` must implement the -//! trait `DepGraphRead`, which indicates how to register reads on the -//! data in this new task (note that many types of data, such as -//! `DefId`, do not currently require any reads to be registered, -//! since they are not derived from a HIR node). This is also why we -//! give a callback fn, rather than taking a closure: it allows us to -//! easily control precisely what data is given to that fn. - -use crate::encoder::EncodeContext; -use crate::index::Index; -use crate::schema::*; -use crate::isolated_encoder::IsolatedEncoder; - -use rustc::hir; -use rustc::hir::def_id::DefId; -use rustc::ty::TyCtxt; -use syntax::ast; - -use std::ops::{Deref, DerefMut}; - -/// Builder that can encode new items, adding them into the index. -/// Item encoding cannot be nested. -pub struct IndexBuilder<'a, 'b: 'a, 'tcx: 'b> { - items: Index<'tcx>, - pub ecx: &'a mut EncodeContext<'b, 'tcx>, -} - -impl<'a, 'b, 'tcx> Deref for IndexBuilder<'a, 'b, 'tcx> { - type Target = EncodeContext<'b, 'tcx>; - fn deref(&self) -> &Self::Target { - self.ecx - } -} - -impl<'a, 'b, 'tcx> DerefMut for IndexBuilder<'a, 'b, 'tcx> { - fn deref_mut(&mut self) -> &mut Self::Target { - self.ecx - } -} - -impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { - pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { - IndexBuilder { - items: Index::new(ecx.tcx.hir().definitions().def_index_counts_lo_hi()), - ecx, - } - } - - /// Emit the data for a `DefId` to the metadata. The function to - /// emit the data is `op`, and it will be given `data` as - /// arguments. This `record` function will call `op` to generate - /// the `Entry` (which may point to other encoded information) - /// and will then record the `Lazy` for use in the index. - /// - /// In addition, it will setup a dep-graph task to track what data - /// `op` accesses to generate the metadata, which is later used by - /// incremental compilation to compute a hash for the metadata and - /// track changes. - /// - /// The reason that `op` is a function pointer, and not a closure, - /// is that we want to be able to completely track all data it has - /// access to, so that we can be sure that `DATA: DepGraphRead` - /// holds, and that it is therefore not gaining "secret" access to - /// bits of HIR or other state that would not be trackd by the - /// content system. - pub fn record<'x, DATA>(&'x mut self, - id: DefId, - op: fn(&mut IsolatedEncoder<'x, 'b, 'tcx>, DATA) -> Entry<'tcx>, - data: DATA) - where DATA: DepGraphRead - { - assert!(id.is_local()); - - // We don't track this since we are explicitly computing the incr. comp. - // hashes anyway. In theory we could do some tracking here and use it to - // avoid rehashing things (and instead cache the hashes) but it's - // unclear whether that would be a win since hashing is cheap enough. - self.ecx.tcx.dep_graph.with_ignore(move || { - let mut entry_builder = IsolatedEncoder::new(self.ecx); - let entry = op(&mut entry_builder, data); - let entry = entry_builder.lazy(&entry); - - self.items.record(id, entry); - }) - } - - pub fn into_items(self) -> Index<'tcx> { - self.items - } -} - -/// Trait used for data that can be passed from outside a dep-graph -/// task. The data must either be of some safe type, such as a -/// `DefId` index, or implement the `read` method so that it can add -/// a read of whatever dep-graph nodes are appropriate. -pub trait DepGraphRead { - fn read(&self, tcx: TyCtxt<'_, '_, '_>); -} - -impl DepGraphRead for DefId { - fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {} -} - -impl DepGraphRead for ast::NodeId { - fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {} -} - -impl DepGraphRead for Option - where T: DepGraphRead -{ - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - match *self { - Some(ref v) => v.read(tcx), - None => (), - } - } -} - -impl DepGraphRead for [T] - where T: DepGraphRead -{ - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - for i in self { - i.read(tcx); - } - } -} - -macro_rules! read_tuple { - ($($name:ident),*) => { - impl<$($name),*> DepGraphRead for ($($name),*) - where $($name: DepGraphRead),* - { - #[allow(non_snake_case)] - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - let &($(ref $name),*) = self; - $($name.read(tcx);)* - } - } - } -} -read_tuple!(A, B); -read_tuple!(A, B, C); - -macro_rules! read_hir { - ($t:ty) => { - impl<'tcx> DepGraphRead for &'tcx $t { - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - tcx.hir().read_by_hir_id(self.hir_id); - } - } - } -} -read_hir!(hir::Item); -read_hir!(hir::ImplItem); -read_hir!(hir::TraitItem); -read_hir!(hir::ForeignItem); -read_hir!(hir::MacroDef); - -/// Leaks access to a value of type T without any tracking. This is -/// suitable for ambiguous types like `usize`, which *could* represent -/// tracked data (e.g., if you read it out of a HIR node) or might not -/// (e.g., if it's an index). Adding in an `Untracked` is an -/// assertion, essentially, that the data does not need to be tracked -/// (or that read edges will be added by some other way). -/// -/// A good idea is to add to each use of `Untracked` an explanation of -/// why this value is ok. -pub struct Untracked(pub T); - -impl DepGraphRead for Untracked { - fn read(&self, _tcx: TyCtxt<'_, '_, '_>) {} -} - -/// Newtype that can be used to package up misc data extracted from a -/// HIR node that doesn't carry its own ID. This will allow an -/// arbitrary `T` to be passed in, but register a read on the given -/// `NodeId`. -pub struct FromId(pub hir::HirId, pub T); - -impl DepGraphRead for FromId { - fn read(&self, tcx: TyCtxt<'_, '_, '_>) { - tcx.hir().read_by_hir_id(self.0); - } -} diff --git a/src/librustc_metadata/isolated_encoder.rs b/src/librustc_metadata/isolated_encoder.rs deleted file mode 100644 index e879a73e650bb..0000000000000 --- a/src/librustc_metadata/isolated_encoder.rs +++ /dev/null @@ -1,48 +0,0 @@ -use crate::encoder::EncodeContext; -use crate::schema::{Lazy, LazySeq}; -use rustc::ty::TyCtxt; -use rustc_serialize::Encodable; - -/// The IsolatedEncoder provides facilities to write to crate metadata while -/// making sure that anything going through it is also feed into an ICH hasher. -pub struct IsolatedEncoder<'a, 'b: 'a, 'tcx: 'b> { - pub tcx: TyCtxt<'b, 'tcx, 'tcx>, - ecx: &'a mut EncodeContext<'b, 'tcx>, -} - -impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { - - pub fn new(ecx: &'a mut EncodeContext<'b, 'tcx>) -> Self { - let tcx = ecx.tcx; - IsolatedEncoder { - tcx, - ecx, - } - } - - pub fn lazy(&mut self, value: &T) -> Lazy - where T: Encodable - { - self.ecx.lazy(value) - } - - pub fn lazy_seq(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: Encodable - { - self.ecx.lazy_seq(iter) - } - - pub fn lazy_seq_ref<'x, I, T>(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: 'x + Encodable - { - self.ecx.lazy_seq_ref(iter) - } - - pub fn lazy_seq_from_slice(&mut self, slice: &[T]) -> LazySeq - where T: Encodable - { - self.ecx.lazy_seq_ref(slice.iter()) - } -} diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 05ecb4cb1630d..47a9c97d40a4b 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -29,12 +29,10 @@ extern crate rustc_data_structures; mod diagnostics; -mod index_builder; mod index; mod encoder; mod decoder; mod cstore_impl; -mod isolated_encoder; mod schema; mod native_libs; mod link_args; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index b2f6fd65ed445..0ad3251540716 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -2,8 +2,7 @@ use crate::index; use rustc::hir; use rustc::hir::def::{self, CtorKind}; -use rustc::hir::def_id::{DefIndex, DefId, CrateNum}; -use rustc::ich::StableHashingContext; +use rustc::hir::def_id::{DefIndex, DefId}; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel}; use rustc::middle::cstore::{DepKind, LinkagePreference, NativeLibrary, ForeignModule}; use rustc::middle::lang_items; @@ -20,10 +19,6 @@ use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; -use std::mem; - -use rustc_data_structures::stable_hasher::{StableHasher, HashStable, - StableHasherResult}; pub fn rustc_version() -> String { format!("rustc {}", @@ -92,15 +87,6 @@ impl Clone for Lazy { impl serialize::UseSpecializedEncodable for Lazy {} impl serialize::UseSpecializedDecodable for Lazy {} -impl HashStable for Lazy { - fn hash_stable(&self, - _: &mut CTX, - _: &mut StableHasher) { - // There's nothing to do. Whatever got encoded within this Lazy<> - // wrapper has already been hashed. - } -} - /// A sequence of type T referred to by its absolute position /// in the metadata and length, and which can be decoded lazily. /// The sequence is a single node for the purposes of `Lazy`. @@ -149,15 +135,6 @@ impl Clone for LazySeq { impl serialize::UseSpecializedEncodable for LazySeq {} impl serialize::UseSpecializedDecodable for LazySeq {} -impl HashStable for LazySeq { - fn hash_stable(&self, - _: &mut CTX, - _: &mut StableHasher) { - // There's nothing to do. Whatever got encoded within this Lazy<> - // wrapper has already been hashed. - } -} - /// Encoding / decoding state for `Lazy` and `LazySeq`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum LazyState { @@ -203,7 +180,7 @@ pub struct CrateRoot<'tcx> { pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, pub interpret_alloc_index: LazySeq, - pub index: LazySeq>, + pub entries_index: LazySeq>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -222,36 +199,12 @@ pub struct CrateDep { pub extra_filename: String, } -impl_stable_hash_for!(struct CrateDep { - name, - hash, - kind, - extra_filename -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitImpls { pub trait_id: (u32, DefIndex), pub impls: LazySeq, } -impl<'a, 'gcx> HashStable> for TraitImpls { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - let TraitImpls { - trait_id: (krate, def_index), - ref impls, - } = *self; - - DefId { - krate: CrateNum::from_u32(krate), - index: def_index - }.hash_stable(hcx, hasher); - impls.hash_stable(hcx, hasher); - } -} - #[derive(RustcEncodable, RustcDecodable)] pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, @@ -272,23 +225,6 @@ pub struct Entry<'tcx> { pub mir: Option>>, } -impl_stable_hash_for!(struct Entry<'tcx> { - kind, - visibility, - span, - attributes, - children, - stability, - deprecation, - ty, - inherent_impls, - variances, - generics, - predicates, - predicates_defined_on, - mir -}); - #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] pub enum EntryKind<'tcx> { Const(ConstQualif, Lazy), @@ -323,82 +259,6 @@ pub enum EntryKind<'tcx> { TraitAlias(Lazy>), } -impl<'a, 'gcx> HashStable> for EntryKind<'gcx> { - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - mem::discriminant(self).hash_stable(hcx, hasher); - match *self { - EntryKind::ImmStatic | - EntryKind::MutStatic | - EntryKind::ForeignImmStatic | - EntryKind::ForeignMutStatic | - EntryKind::ForeignMod | - EntryKind::GlobalAsm | - EntryKind::ForeignType | - EntryKind::Field | - EntryKind::Existential | - EntryKind::Type | - EntryKind::TypeParam | - EntryKind::ConstParam => { - // Nothing else to hash here. - } - EntryKind::Const(qualif, ref const_data) => { - qualif.hash_stable(hcx, hasher); - const_data.hash_stable(hcx, hasher); - } - EntryKind::Enum(ref repr_options) => { - repr_options.hash_stable(hcx, hasher); - } - EntryKind::Variant(ref variant_data) => { - variant_data.hash_stable(hcx, hasher); - } - EntryKind::Struct(ref variant_data, ref repr_options) | - EntryKind::Union(ref variant_data, ref repr_options) => { - variant_data.hash_stable(hcx, hasher); - repr_options.hash_stable(hcx, hasher); - } - EntryKind::Fn(ref fn_data) | - EntryKind::ForeignFn(ref fn_data) => { - fn_data.hash_stable(hcx, hasher); - } - EntryKind::Mod(ref mod_data) => { - mod_data.hash_stable(hcx, hasher); - } - EntryKind::MacroDef(ref macro_def) => { - macro_def.hash_stable(hcx, hasher); - } - EntryKind::Generator(data) => { - data.hash_stable(hcx, hasher); - } - EntryKind::Closure(closure_data) => { - closure_data.hash_stable(hcx, hasher); - } - EntryKind::Trait(ref trait_data) => { - trait_data.hash_stable(hcx, hasher); - } - EntryKind::TraitAlias(ref trait_alias_data) => { - trait_alias_data.hash_stable(hcx, hasher); - } - EntryKind::Impl(ref impl_data) => { - impl_data.hash_stable(hcx, hasher); - } - EntryKind::Method(ref method_data) => { - method_data.hash_stable(hcx, hasher); - } - EntryKind::AssociatedExistential(associated_container) | - EntryKind::AssociatedType(associated_container) => { - associated_container.hash_stable(hcx, hasher); - } - EntryKind::AssociatedConst(associated_container, qualif, ref const_data) => { - associated_container.hash_stable(hcx, hasher); - qualif.hash_stable(hcx, hasher); - const_data.hash_stable(hcx, hasher); - } - } - } -} - /// Additional data for EntryKind::Const and EntryKind::AssociatedConst #[derive(Clone, Copy, RustcEncodable, RustcDecodable)] pub struct ConstQualif { @@ -406,37 +266,22 @@ pub struct ConstQualif { pub ast_promotable: bool, } -impl_stable_hash_for!(struct ConstQualif { mir, ast_promotable }); - /// Contains a constant which has been rendered to a String. /// Used by rustdoc. #[derive(RustcEncodable, RustcDecodable)] pub struct RenderedConst(pub String); -impl<'a> HashStable> for RenderedConst { - #[inline] - fn hash_stable(&self, - hcx: &mut StableHashingContext<'a>, - hasher: &mut StableHasher) { - self.0.hash_stable(hcx, hasher); - } -} - #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { pub reexports: LazySeq>, } -impl_stable_hash_for!(struct ModData { reexports }); - #[derive(RustcEncodable, RustcDecodable)] pub struct MacroDef { pub body: String, pub legacy: bool, } -impl_stable_hash_for!(struct MacroDef { body, legacy }); - #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { pub constness: hir::Constness, @@ -444,8 +289,6 @@ pub struct FnData<'tcx> { pub sig: Lazy>, } -impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); - #[derive(RustcEncodable, RustcDecodable)] pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, @@ -457,13 +300,6 @@ pub struct VariantData<'tcx> { pub ctor_sig: Option>>, } -impl_stable_hash_for!(struct VariantData<'tcx> { - ctor_kind, - discr, - ctor, - ctor_sig -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitData<'tcx> { pub unsafety: hir::Unsafety, @@ -473,23 +309,11 @@ pub struct TraitData<'tcx> { pub super_predicates: Lazy>, } -impl_stable_hash_for!(struct TraitData<'tcx> { - unsafety, - paren_sugar, - has_auto_impl, - is_marker, - super_predicates -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitAliasData<'tcx> { pub super_predicates: Lazy>, } -impl_stable_hash_for!(struct TraitAliasData<'tcx> { - super_predicates -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct ImplData<'tcx> { pub polarity: hir::ImplPolarity, @@ -501,14 +325,6 @@ pub struct ImplData<'tcx> { pub trait_ref: Option>>, } -impl_stable_hash_for!(struct ImplData<'tcx> { - polarity, - defaultness, - parent_impl, - coerce_unsized_info, - trait_ref -}); - /// Describes whether the container of an associated item /// is a trait or an impl and whether, in a trait, it has @@ -521,13 +337,6 @@ pub enum AssociatedContainer { ImplFinal, } -impl_stable_hash_for!(enum crate::schema::AssociatedContainer { - TraitRequired, - TraitWithDefault, - ImplDefault, - ImplFinal -}); - impl AssociatedContainer { pub fn with_def_id(&self, def_id: DefId) -> ty::AssociatedItemContainer { match *self { @@ -561,19 +370,16 @@ pub struct MethodData<'tcx> { pub container: AssociatedContainer, pub has_self: bool, } -impl_stable_hash_for!(struct MethodData<'tcx> { fn_data, container, has_self }); #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { pub sig: Lazy>, } -impl_stable_hash_for!(struct ClosureData<'tcx> { sig }); #[derive(RustcEncodable, RustcDecodable)] pub struct GeneratorData<'tcx> { pub layout: mir::GeneratorLayout<'tcx>, } -impl_stable_hash_for!(struct GeneratorData<'tcx> { layout }); // Tags used for encoding Spans: pub const TAG_VALID_SPAN: u8 = 0; From 66c87636b27f1ae53453d3b7ddc8693c6baadf8f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 14:25:38 +0300 Subject: [PATCH 04/14] rustc_metadata: replace LazySeq with Lazy<[T]>. --- src/librustc_metadata/cstore.rs | 8 +- src/librustc_metadata/decoder.rs | 35 +-- src/librustc_metadata/encoder.rs | 381 +++++++++++++++---------------- src/librustc_metadata/index.rs | 14 +- src/librustc_metadata/schema.rs | 151 ++++++------ 5 files changed, 298 insertions(+), 291 deletions(-) diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 5d8fabc7e69ae..ce4fe1572fe92 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -65,9 +65,9 @@ pub struct CrateMetadata { pub alloc_decoding_state: AllocDecodingState, // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this - // lifetime is only used behind `Lazy` / `LazySeq`, and therefore - // acts like an universal (`for<'tcx>`), that is paired up with - // whichever `TyCtxt` is being used to decode those values. + // lifetime is only used behind `Lazy`, and therefore acts like an + // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt` + // is being used to decode those values. pub root: schema::CrateRoot<'static>, /// For each public item in this crate, we encode a key. When the @@ -77,7 +77,7 @@ pub struct CrateMetadata { /// compilation support. pub def_path_table: Lrc, - pub trait_impls: FxHashMap<(u32, DefIndex), schema::LazySeq>, + pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>, pub dep_kind: Lock, pub source: CrateSource, diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index f51c7ed2ec6c9..a78f2b7eeac1b 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -135,14 +135,14 @@ impl<'a, 'tcx: 'a, T: Decodable> Lazy { } } -impl<'a, 'tcx: 'a, T: Decodable> LazySeq { +impl<'a, 'tcx: 'a, T: Decodable> Lazy<[T]> { pub fn decode>( self, meta: M, ) -> impl Iterator + Captures<'tcx> + 'a { let mut dcx = meta.decoder(self.position); dcx.lazy_state = LazyState::NodeStart(self.position); - (0..self.len).map(move |_| T::decode(&mut dcx).unwrap()) + (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } } @@ -155,10 +155,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { self.cdata.expect("missing CrateMetadata in DecodeContext") } - fn read_lazy_distance(&mut self, min_size: usize) -> Result::Error> { + fn read_lazy_with_meta( + &mut self, + meta: T::Meta, + ) -> Result, ::Error> { + let min_size = T::min_size(meta); let distance = self.read_usize()?; let position = match self.lazy_state { - LazyState::NoNode => bug!("read_lazy_distance: outside of a metadata node"), + LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { assert!(distance + min_size <= start); start - distance - min_size @@ -166,7 +170,7 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { LazyState::Previous(last_min_end) => last_min_end + distance, }; self.lazy_state = LazyState::Previous(position + min_size); - Ok(position) + Ok(Lazy::from_position_and_meta(position, meta)) } } @@ -232,19 +236,18 @@ impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> { impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { - Ok(Lazy::with_position(self.read_lazy_distance(Lazy::::min_size())?)) + self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { - fn specialized_decode(&mut self) -> Result, Self::Error> { +impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { + fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; - let position = if len == 0 { - 0 + if len == 0 { + Ok(Lazy::empty()) } else { - self.read_lazy_distance(LazySeq::::min_size(len))? - }; - Ok(LazySeq::with_position_and_length(position, len)) + self.read_lazy_with_meta(len) + } } } @@ -372,7 +375,7 @@ impl<'tcx> MetadataBlob { } pub fn get_rustc_version(&self) -> String { - Lazy::with_position(METADATA_HEADER.len() + 4).decode(self) + Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) } pub fn get_root(&self) -> CrateRoot<'tcx> { @@ -381,7 +384,7 @@ impl<'tcx> MetadataBlob { let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::with_position(pos).decode(self) + Lazy::>::from_position(pos).decode(self) } pub fn list_crate_metadata(&self, @@ -1109,7 +1112,7 @@ impl<'a, 'tcx> CrateMetadata { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).arg_names, EntryKind::Method(data) => data.decode(self).fn_data.arg_names, - _ => LazySeq::empty(), + _ => Lazy::empty(), }; arg_names.decode(self).collect() } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 520bac41ba345..1864f2e9992ef 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -97,17 +97,17 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { - self.emit_lazy_distance(lazy.position, Lazy::::min_size()) + self.emit_lazy_distance(*lazy) } } -impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { - fn specialized_encode(&mut self, seq: &LazySeq) -> Result<(), Self::Error> { - self.emit_usize(seq.len)?; - if seq.len == 0 { +impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { + fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { + self.emit_usize(lazy.meta)?; + if lazy.meta == 0 { return Ok(()); } - self.emit_lazy_distance(seq.position, LazySeq::::min_size(seq.len)) + self.emit_lazy_distance(*lazy) } } @@ -232,22 +232,38 @@ impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> { } } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { +/// Helper trait to allow overloading `EncodeContext::lazy` for iterators. +trait EncodeContentsForLazy { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'_, 'tcx>) -> T::Meta; +} - fn emit_node R, R>(&mut self, f: F) -> R { - assert_eq!(self.lazy_state, LazyState::NoNode); - let pos = self.position(); - self.lazy_state = LazyState::NodeStart(pos); - let r = f(self, pos); - self.lazy_state = LazyState::NoNode; - r +impl EncodeContentsForLazy for &T { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'_, 'tcx>) { + self.encode(ecx).unwrap() } +} - fn emit_lazy_distance(&mut self, - position: usize, - min_size: usize) - -> Result<(), ::Error> { - let min_end = position + min_size; +impl EncodeContentsForLazy for T { + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'_, 'tcx>) { + self.encode(ecx).unwrap() + } +} + +impl EncodeContentsForLazy<[T]> for I + where I: IntoIterator, + I::Item: EncodeContentsForLazy, +{ + fn encode_contents_for_lazy(self, ecx: &mut EncodeContext<'_, 'tcx>) -> usize { + self.into_iter().map(|value| value.encode_contents_for_lazy(ecx)).count() + } +} + +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn emit_lazy_distance( + &mut self, + lazy: Lazy, + ) -> Result<(), ::Error> { + let min_end = lazy.position + T::min_size(lazy.meta); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { @@ -256,48 +272,31 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } LazyState::Previous(last_min_end) => { assert!( - last_min_end <= position, + last_min_end <= lazy.position, "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - position - last_min_end + lazy.position - last_min_end } }; self.lazy_state = LazyState::Previous(min_end); self.emit_usize(distance) } - pub fn lazy(&mut self, value: &T) -> Lazy { - self.emit_node(|ecx, pos| { - value.encode(ecx).unwrap(); - - assert!(pos + Lazy::::min_size() <= ecx.position()); - Lazy::with_position(pos) - }) - } - - pub fn lazy_seq(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: Encodable - { - self.emit_node(|ecx, pos| { - let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + fn lazy( + &mut self, + value: impl EncodeContentsForLazy, + ) -> Lazy { + let pos = self.position(); - assert!(pos + LazySeq::::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) - } + assert_eq!(self.lazy_state, LazyState::NoNode); + self.lazy_state = LazyState::NodeStart(pos); + let meta = value.encode_contents_for_lazy(self); + self.lazy_state = LazyState::NoNode; - pub fn lazy_seq_ref<'b, I, T>(&mut self, iter: I) -> LazySeq - where I: IntoIterator, - T: 'b + Encodable - { - self.emit_node(|ecx, pos| { - let len = iter.into_iter().map(|value| value.encode(ecx).unwrap()).count(); + assert!(pos + ::min_size(meta) <= self.position()); - assert!(pos + LazySeq::::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) + Lazy::from_position_and_meta(pos, meta) } /// Emit the data for a `DefId` to the metadata. The function to @@ -314,7 +313,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { assert!(id.is_local()); let entry = op(self, data); - let entry = self.lazy(&entry); + let entry = self.lazy(entry); self.entries_index.record(id, entry); } @@ -335,7 +334,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(definitions.def_path_table()) } - fn encode_source_map(&mut self) -> LazySeq { + fn encode_source_map(&mut self) -> Lazy<[syntax_pos::SourceFile]> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -374,7 +373,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) .collect::>(); - self.lazy_seq_ref(adapted.iter().map(|rc| &**rc)) + self.lazy(adapted.iter().map(|rc| &**rc)) } fn encode_crate_root(&mut self) -> Lazy> { @@ -455,7 +454,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } n = new_n; } - self.lazy_seq(interpret_alloc_index) + self.lazy(interpret_alloc_index) }; i = self.position(); @@ -468,7 +467,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let has_global_allocator = *tcx.sess.has_global_allocator.get(); let has_panic_handler = *tcx.sess.has_panic_handler.try_get().unwrap_or(&false); - let root = self.lazy(&CrateRoot { + 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(), @@ -544,17 +543,17 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } impl EncodeContext<'_, 'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq { + fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { debug!("EncodeContext::encode_variances_of({:?})", def_id); let tcx = self.tcx; - self.lazy_seq_ref(&tcx.variances_of(def_id)[..]) + self.lazy(&tcx.variances_of(def_id)[..]) } fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { let tcx = self.tcx; let ty = tcx.type_of(def_id); debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); - self.lazy(&ty) + self.lazy(ty) } fn encode_enum_variant_info( @@ -578,11 +577,11 @@ impl EncodeContext<'_, 'tcx> { let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis; Entry { - kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(&tcx.def_span(def_id)), + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy_seq(variant.fields.iter().map(|f| { + children: self.lazy(variant.fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })), @@ -590,11 +589,11 @@ impl EncodeContext<'_, 'tcx> { deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -619,7 +618,7 @@ impl EncodeContext<'_, 'tcx> { discr: variant.discr, ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) + Some(self.lazy(tcx.fn_sig(def_id))) } else { None } @@ -635,20 +634,20 @@ impl EncodeContext<'_, 'tcx> { } Entry { - kind: EntryKind::Variant(self.lazy(&data)), - visibility: self.lazy(&ctor_vis), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -668,25 +667,25 @@ impl EncodeContext<'_, 'tcx> { let data = ModData { reexports: match tcx.module_exports(def_id) { - Some(ref exports) => self.lazy_seq_ref(&exports[..]), - _ => LazySeq::empty(), + Some(ref exports) => self.lazy(&exports[..]), + _ => Lazy::empty(), }, }; Entry { - kind: EntryKind::Mod(self.lazy(&data)), - visibility: self.lazy(&ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(&tcx.def_span(def_id)), + kind: EntryKind::Mod(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(attrs), - children: self.lazy_seq(md.item_ids.iter().map(|item_id| { + children: self.lazy(md.item_ids.iter().map(|item_id| { tcx.hir().local_def_id_from_hir_id(item_id.id).index })), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, @@ -711,16 +710,16 @@ impl EncodeContext<'_, 'tcx> { Entry { kind: EntryKind::Field, - visibility: self.lazy(&field.vis), - span: self.lazy(&tcx.def_span(def_id)), + visibility: self.lazy(field.vis), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, @@ -740,7 +739,7 @@ impl EncodeContext<'_, 'tcx> { discr: variant.discr, ctor: Some(def_id.index), ctor_sig: if variant.ctor_kind == CtorKind::Fn { - Some(self.lazy(&tcx.fn_sig(def_id))) + Some(self.lazy(tcx.fn_sig(def_id))) } else { None } @@ -766,20 +765,20 @@ impl EncodeContext<'_, 'tcx> { let repr_options = get_repr_options(&tcx, adt_def_id); Entry { - kind: EntryKind::Struct(self.lazy(&data), repr_options), - visibility: self.lazy(&ctor_vis), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + kind: EntryKind::Struct(self.lazy(data), repr_options), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if variant.ctor_kind == CtorKind::Fn { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -798,13 +797,13 @@ impl EncodeContext<'_, 'tcx> { fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { debug!("EncodeContext::encode_predicates({:?})", def_id); let tcx = self.tcx; - self.lazy(&tcx.predicates_of(def_id)) + self.lazy(&*tcx.predicates_of(def_id)) } fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); let tcx = self.tcx; - self.lazy(&tcx.predicates_defined_on(def_id)) + self.lazy(&*tcx.predicates_defined_on(def_id)) } fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { @@ -835,7 +834,7 @@ impl EncodeContext<'_, 'tcx> { let rendered = hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); - let rendered_const = self.lazy(&RenderedConst(rendered)); + let rendered_const = self.lazy(RenderedConst(rendered)); EntryKind::AssociatedConst(container, const_qualif, rendered_const) } @@ -852,12 +851,12 @@ impl EncodeContext<'_, 'tcx> { FnData { constness: hir::Constness::NotConst, arg_names, - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() }; - EntryKind::Method(self.lazy(&MethodData { + EntryKind::Method(self.lazy(MethodData { fn_data, container, has_self: trait_item.method_has_self_argument, @@ -870,10 +869,10 @@ impl EncodeContext<'_, 'tcx> { Entry { kind, - visibility: self.lazy(&trait_item.vis), - span: self.lazy(&ast_item.span), + visibility: self.lazy(trait_item.vis), + span: self.lazy(ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -891,11 +890,11 @@ impl EncodeContext<'_, 'tcx> { } ty::AssociatedKind::Existential => unreachable!(), }, - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if trait_item.kind == ty::AssociatedKind::Method { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -949,12 +948,12 @@ impl EncodeContext<'_, 'tcx> { FnData { constness: sig.header.constness, arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), } } else { bug!() }; - EntryKind::Method(self.lazy(&MethodData { + EntryKind::Method(self.lazy(MethodData { fn_data, container, has_self: impl_item.method_has_self_argument, @@ -982,19 +981,19 @@ impl EncodeContext<'_, 'tcx> { Entry { kind, - visibility: self.lazy(&impl_item.vis), - span: self.lazy(&ast_item.span), + visibility: self.lazy(impl_item.vis), + span: self.lazy(ast_item.span), attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: if impl_item.kind == ty::AssociatedKind::Method { self.encode_variances_of(def_id) } else { - LazySeq::empty() + Lazy::empty() }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), @@ -1005,10 +1004,10 @@ impl EncodeContext<'_, 'tcx> { } fn encode_fn_arg_names_for_body(&mut self, body_id: hir::BodyId) - -> LazySeq { + -> Lazy<[ast::Name]> { self.tcx.dep_graph.with_ignore(|| { let body = self.tcx.hir().body(body_id); - self.lazy_seq(body.arguments.iter().map(|arg| { + self.lazy(body.arguments.iter().map(|arg| { match arg.pat.node { PatKind::Binding(_, _, ident, _) => ident.name, _ => keywords::Invalid.name(), @@ -1017,28 +1016,28 @@ impl EncodeContext<'_, 'tcx> { }) } - fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> LazySeq { - self.lazy_seq(param_names.iter().map(|ident| ident.name)) + fn encode_fn_arg_names(&mut self, param_names: &[ast::Ident]) -> Lazy<[ast::Name]> { + self.lazy(param_names.iter().map(|ident| ident.name)) } fn encode_optimized_mir(&mut self, def_id: DefId) -> Option>> { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let mir = self.tcx.optimized_mir(def_id); - Some(self.lazy(&mir)) + Some(self.lazy(mir)) } else { None } } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) -> LazySeq { + fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); if implementations.is_empty() { - LazySeq::empty() + Lazy::empty() } else { - self.lazy_seq(implementations.iter().map(|&def_id| { + self.lazy(implementations.iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) @@ -1052,7 +1051,7 @@ impl EncodeContext<'_, 'tcx> { fn encode_deprecation(&mut self, def_id: DefId) -> Option> { debug!("EncodeContext::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) + self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(depr)) } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy { @@ -1081,10 +1080,10 @@ impl EncodeContext<'_, 'tcx> { let data = FnData { constness: header.constness, arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), }; - EntryKind::Fn(self.lazy(&data)) + EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); @@ -1105,7 +1104,7 @@ impl EncodeContext<'_, 'tcx> { let repr_options = get_repr_options(&tcx, def_id); - EntryKind::Struct(self.lazy(&VariantData { + EntryKind::Struct(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor, @@ -1116,7 +1115,7 @@ impl EncodeContext<'_, 'tcx> { let variant = tcx.adt_def(def_id).non_enum_variant(); let repr_options = get_repr_options(&tcx, def_id); - EntryKind::Union(self.lazy(&VariantData { + EntryKind::Union(self.lazy(VariantData { ctor_kind: variant.ctor_kind, discr: variant.discr, ctor: None, @@ -1153,10 +1152,10 @@ impl EncodeContext<'_, 'tcx> { defaultness, parent_impl: parent, coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)), + trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), }; - EntryKind::Impl(self.lazy(&data)) + EntryKind::Impl(self.lazy(data)) } hir::ItemKind::Trait(..) => { let trait_def = tcx.trait_def(def_id); @@ -1165,17 +1164,17 @@ impl EncodeContext<'_, 'tcx> { paren_sugar: trait_def.paren_sugar, has_auto_impl: tcx.trait_is_auto(def_id), is_marker: trait_def.is_marker, - super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; - EntryKind::Trait(self.lazy(&data)) + EntryKind::Trait(self.lazy(data)) } hir::ItemKind::TraitAlias(..) => { let data = TraitAliasData { - super_predicates: self.lazy(&tcx.super_predicates_of(def_id)), + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), }; - EntryKind::TraitAlias(self.lazy(&data)) + EntryKind::TraitAlias(self.lazy(data)) } hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), @@ -1183,19 +1182,19 @@ impl EncodeContext<'_, 'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(&item.span), + visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), + span: self.lazy(item.span), attributes: self.encode_attributes(&item.attrs), children: match item.node { hir::ItemKind::ForeignMod(ref fm) => { - self.lazy_seq(fm.items + self.lazy(fm.items .iter() .map(|foreign_item| tcx.hir().local_def_id_from_hir_id( foreign_item.hir_id).index)) } hir::ItemKind::Enum(..) => { let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.variants.iter().map(|v| { + self.lazy(def.variants.iter().map(|v| { assert!(v.def_id.is_local()); v.def_id.index })) @@ -1203,19 +1202,19 @@ impl EncodeContext<'_, 'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) => { let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.non_enum_variant().fields.iter().map(|f| { + self.lazy(def.non_enum_variant().fields.iter().map(|f| { assert!(f.did.is_local()); f.did.index })) } hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => { - self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { + self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { assert!(def_id.is_local()); def_id.index })) } - _ => LazySeq::empty(), + _ => Lazy::empty(), }, stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), @@ -1238,7 +1237,7 @@ impl EncodeContext<'_, 'tcx> { hir::ItemKind::Struct(..) | hir::ItemKind::Union(..) | hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + _ => Lazy::empty(), }, generics: match item.node { hir::ItemKind::Static(..) | @@ -1311,20 +1310,20 @@ impl EncodeContext<'_, 'tcx> { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); Entry { - kind: EntryKind::MacroDef(self.lazy(&MacroDef { + kind: EntryKind::MacroDef(self.lazy(MacroDef { body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), legacy: macro_def.legacy, })), - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(¯o_def.span), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(macro_def.span), attributes: self.encode_attributes(¯o_def.attrs), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), - children: LazySeq::empty(), + children: Lazy::empty(), ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, @@ -1341,15 +1340,15 @@ impl EncodeContext<'_, 'tcx> { let tcx = self.tcx; Entry { kind: entry_kind, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: None, predicates: None, predicates_defined_on: None, @@ -1386,13 +1385,13 @@ impl EncodeContext<'_, 'tcx> { let data = GeneratorData { layout: layout.clone(), }; - EntryKind::Generator(self.lazy(&data)) + EntryKind::Generator(self.lazy(data)) } ty::Closure(def_id, substs) => { let sig = substs.closure_sig(def_id, self.tcx); - let data = ClosureData { sig: self.lazy(&sig) }; - EntryKind::Closure(self.lazy(&data)) + let data = ClosureData { sig: self.lazy(sig) }; + EntryKind::Closure(self.lazy(data)) } _ => bug!("closure that is neither generator nor closure") @@ -1400,16 +1399,16 @@ impl EncodeContext<'_, 'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: LazySeq::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: None, predicates_defined_on: None, @@ -1428,16 +1427,16 @@ impl EncodeContext<'_, 'tcx> { Entry { kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), - visibility: self.lazy(&ty::Visibility::Public), - span: self.lazy(&tcx.def_span(def_id)), - attributes: LazySeq::empty(), - children: LazySeq::empty(), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), stability: None, deprecation: None, ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), predicates_defined_on: None, @@ -1446,21 +1445,21 @@ impl EncodeContext<'_, 'tcx> { } } - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> LazySeq { - self.lazy_seq_ref(attrs) + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { + self.lazy(attrs) } - fn encode_native_libraries(&mut self) -> LazySeq { + fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { let used_libraries = self.tcx.native_libraries(LOCAL_CRATE); - self.lazy_seq(used_libraries.iter().cloned()) + self.lazy(used_libraries.iter().cloned()) } - fn encode_foreign_modules(&mut self) -> LazySeq { + fn encode_foreign_modules(&mut self) -> Lazy<[ForeignModule]> { let foreign_modules = self.tcx.foreign_modules(LOCAL_CRATE); - self.lazy_seq(foreign_modules.iter().cloned()) + self.lazy(foreign_modules.iter().cloned()) } - fn encode_crate_deps(&mut self) -> LazySeq { + fn encode_crate_deps(&mut self) -> Lazy<[CrateDep]> { let crates = self.tcx.crates(); let mut deps = crates @@ -1491,20 +1490,20 @@ impl EncodeContext<'_, 'tcx> { // 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_seq_ref(deps.iter().map(|&(_, ref dep)| dep)) + self.lazy(deps.iter().map(|&(_, ref dep)| dep)) } - fn encode_lib_features(&mut self) -> LazySeq<(ast::Name, Option)> { + fn encode_lib_features(&mut self) -> Lazy<[(ast::Name, Option)]> { let tcx = self.tcx; let lib_features = tcx.lib_features(); - self.lazy_seq(lib_features.to_vec()) + self.lazy(lib_features.to_vec()) } - fn encode_lang_items(&mut self) -> LazySeq<(DefIndex, usize)> { + fn encode_lang_items(&mut self) -> Lazy<[(DefIndex, usize)]> { let tcx = self.tcx; let lang_items = tcx.lang_items(); let lang_items = lang_items.items().iter(); - self.lazy_seq(lang_items.enumerate().filter_map(|(i, &opt_def_id)| { + self.lazy(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)); @@ -1514,13 +1513,13 @@ impl EncodeContext<'_, 'tcx> { })) } - fn encode_lang_items_missing(&mut self) -> LazySeq { + fn encode_lang_items_missing(&mut self) -> Lazy<[lang_items::LangItem]> { let tcx = self.tcx; - self.lazy_seq_ref(&tcx.lang_items().missing) + self.lazy(&tcx.lang_items().missing) } /// Encodes an index, mapping each trait to its (local) implementations. - fn encode_impls(&mut self) -> LazySeq { + fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { @@ -1546,12 +1545,12 @@ impl EncodeContext<'_, 'tcx> { TraitImpls { trait_id: (trait_def_id.krate.as_u32(), trait_def_id.index), - impls: self.lazy_seq_ref(&impls), + impls: self.lazy(&impls), } }) .collect(); - self.lazy_seq_ref(&all_impls) + self.lazy(&all_impls) } // Encodes all symbols exported from this crate into the metadata. @@ -1562,12 +1561,12 @@ impl EncodeContext<'_, 'tcx> { // definition (as that's not defined in this crate). fn encode_exported_symbols(&mut self, exported_symbols: &[(ExportedSymbol<'tcx>, SymbolExportLevel)]) - -> LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)> { + -> Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]> { // The metadata symbol name is special. It should not show up in // downstream crates. let metadata_symbol_name = SymbolName::new(&metadata_symbol_name(self.tcx)); - self.lazy_seq(exported_symbols + self.lazy(exported_symbols .iter() .filter(|&&(ref exported_symbol, _)| { match *exported_symbol { @@ -1580,10 +1579,10 @@ impl EncodeContext<'_, 'tcx> { .cloned()) } - fn encode_dylib_dependency_formats(&mut self) -> LazySeq> { + fn encode_dylib_dependency_formats(&mut self) -> Lazy<[Option]> { match self.tcx.sess.dependency_formats.borrow().get(&config::CrateType::Dylib) { Some(arr) => { - self.lazy_seq(arr.iter().map(|slot| { + self.lazy(arr.iter().map(|slot| { match *slot { Linkage::NotLinked | Linkage::IncludedFromDylib => None, @@ -1593,7 +1592,7 @@ impl EncodeContext<'_, 'tcx> { } })) } - None => LazySeq::empty(), + None => Lazy::empty(), } } @@ -1609,9 +1608,9 @@ impl EncodeContext<'_, 'tcx> { let data = FnData { constness: hir::Constness::NotConst, arg_names: self.encode_fn_arg_names(names), - sig: self.lazy(&tcx.fn_sig(def_id)), + sig: self.lazy(tcx.fn_sig(def_id)), }; - EntryKind::ForeignFn(self.lazy(&data)) + EntryKind::ForeignFn(self.lazy(data)) } hir::ForeignItemKind::Static(_, true) => EntryKind::ForeignMutStatic, hir::ForeignItemKind::Static(_, false) => EntryKind::ForeignImmStatic, @@ -1620,18 +1619,18 @@ impl EncodeContext<'_, 'tcx> { Entry { kind, - visibility: self.lazy(&ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(&nitem.span), + visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), + span: self.lazy(nitem.span), attributes: self.encode_attributes(&nitem.attrs), - children: LazySeq::empty(), + children: Lazy::empty(), stability: self.encode_stability(def_id), deprecation: self.encode_deprecation(def_id), ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), + inherent_impls: Lazy::empty(), variances: match nitem.node { hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + _ => Lazy::empty(), }, generics: Some(self.encode_generics(def_id)), predicates: Some(self.encode_predicates(def_id)), diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 702ed901b5cd3..85c3810c059f6 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -110,7 +110,7 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> LazySeq { + pub fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); // First we write the length of the lower range ... @@ -119,12 +119,14 @@ impl Index<'tcx> { buf.emit_raw_bytes(&self.positions[0]); // ... then the values in the higher range. buf.emit_raw_bytes(&self.positions[1]); - LazySeq::with_position_and_length(pos as usize, - (self.positions[0].len() + self.positions[1].len()) / 4 + 1) + Lazy::from_position_and_meta( + pos as usize, + (self.positions[0].len() + self.positions[1].len()) / 4 + 1, + ) } } -impl LazySeq> { +impl Lazy<[Index<'tcx>]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] @@ -132,7 +134,7 @@ impl LazySeq> { let bytes = &bytes[self.position..]; debug!("Index::lookup: index={:?} len={:?}", def_index, - self.len); + self.meta); let i = def_index.as_array_index() + match def_index.address_space() { DefIndexAddressSpace::Low => 0, @@ -149,7 +151,7 @@ impl LazySeq> { None } else { debug!("Index::lookup: position={:?}", position); - Some(Lazy::with_position(position as usize)) + Some(Lazy::from_position(position as usize)) } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 0ad3251540716..d2a35b8635c4b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -41,6 +41,33 @@ pub const METADATA_VERSION: u8 = 4; pub const METADATA_HEADER: &[u8; 12] = &[0, 0, 0, 0, b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; +/// Additional metadata for a `Lazy` where `T` may not be `Sized`, +/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values). +pub trait LazyMeta { + type Meta: Copy + 'static; + + /// Returns the minimum encoded size. + // FIXME(eddyb) Give better estimates for certain types. + fn min_size(meta: Self::Meta) -> usize; +} + +impl LazyMeta for T { + type Meta = (); + + fn min_size(_: ()) -> usize { + assert_ne!(std::mem::size_of::(), 0); + 1 + } +} + +impl LazyMeta for [T] { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len * T::min_size(()) + } +} + /// A value of type T referred to by its absolute position /// in the metadata, and which can be decoded lazily. /// @@ -56,40 +83,8 @@ pub const METADATA_HEADER: &[u8; 12] = /// Distances start at 1, as 0-byte nodes are invalid. /// Also invalid are nodes being referred in a different /// order than they were encoded in. -#[must_use] -pub struct Lazy { - pub position: usize, - _marker: PhantomData, -} - -impl Lazy { - pub fn with_position(position: usize) -> Lazy { - Lazy { - position, - _marker: PhantomData, - } - } - - /// Returns the minimum encoded size of a value of type `T`. - // FIXME(eddyb) Give better estimates for certain types. - pub fn min_size() -> usize { - 1 - } -} - -impl Copy for Lazy {} -impl Clone for Lazy { - fn clone(&self) -> Self { - *self - } -} - -impl serialize::UseSpecializedEncodable for Lazy {} -impl serialize::UseSpecializedDecodable for Lazy {} - -/// A sequence of type T referred to by its absolute position -/// in the metadata and length, and which can be decoded lazily. -/// The sequence is a single node for the purposes of `Lazy`. +/// +/// # Sequences (`Lazy<[T]>`) /// /// Unlike `Lazy>`, the length is encoded next to the /// position, not at the position, which means that the length @@ -100,54 +95,62 @@ impl serialize::UseSpecializedDecodable for Lazy {} /// the minimal distance the length of the sequence, i.e. /// it's assumed there's no 0-byte element in the sequence. #[must_use] -pub struct LazySeq { - pub len: usize, +// FIXME(#59875) the `Meta` parameter only exists to dodge +// invariance wrt `T` (coming from the `meta: T::Meta` field). +pub struct Lazy::Meta> + where T: ?Sized + LazyMeta, + Meta: 'static + Copy, +{ pub position: usize, + pub meta: Meta, _marker: PhantomData, } -impl LazySeq { - pub fn empty() -> LazySeq { - LazySeq::with_position_and_length(0, 0) - } - - pub fn with_position_and_length(position: usize, len: usize) -> LazySeq { - LazySeq { - len, +impl Lazy { + pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { + Lazy { position, + meta, _marker: PhantomData, } } +} + +impl Lazy { + pub fn from_position(position: usize) -> Lazy { + Lazy::from_position_and_meta(position, ()) + } +} - /// Returns the minimum encoded size of `length` values of type `T`. - pub fn min_size(length: usize) -> usize { - length +impl Lazy<[T]> { + pub fn empty() -> Lazy<[T]> { + Lazy::from_position_and_meta(0, 0) } } -impl Copy for LazySeq {} -impl Clone for LazySeq { +impl Copy for Lazy {} +impl Clone for Lazy { fn clone(&self) -> Self { *self } } -impl serialize::UseSpecializedEncodable for LazySeq {} -impl serialize::UseSpecializedDecodable for LazySeq {} +impl serialize::UseSpecializedEncodable for Lazy {} +impl serialize::UseSpecializedDecodable for Lazy {} -/// Encoding / decoding state for `Lazy` and `LazySeq`. +/// Encoding / decoding state for `Lazy`. #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub enum LazyState { /// Outside of a metadata node. NoNode, - /// Inside a metadata node, and before any `Lazy` or `LazySeq`. + /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. NodeStart(usize), - /// Inside a metadata node, with a previous `Lazy` or `LazySeq`. + /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that - /// previous `Lazy` / `LazySeq` would end (see their comments). + /// previous `Lazy` would end (see their comments). Previous(usize), } @@ -167,20 +170,20 @@ pub struct CrateRoot<'tcx> { pub proc_macro_decls_static: Option, pub proc_macro_stability: Option, - pub crate_deps: LazySeq, - pub dylib_dependency_formats: LazySeq>, - pub lib_features: LazySeq<(Symbol, Option)>, - pub lang_items: LazySeq<(DefIndex, usize)>, - pub lang_items_missing: LazySeq, - pub native_libraries: LazySeq, - pub foreign_modules: LazySeq, - pub source_map: LazySeq, + pub crate_deps: Lazy<[CrateDep]>, + pub dylib_dependency_formats: Lazy<[Option]>, + pub lib_features: Lazy<[(Symbol, Option)]>, + pub lang_items: Lazy<[(DefIndex, usize)]>, + pub lang_items_missing: Lazy<[lang_items::LangItem]>, + pub native_libraries: Lazy<[NativeLibrary]>, + pub foreign_modules: Lazy<[ForeignModule]>, + pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy, - pub impls: LazySeq, - pub exported_symbols: LazySeq<(ExportedSymbol<'tcx>, SymbolExportLevel)>, - pub interpret_alloc_index: LazySeq, + pub impls: Lazy<[TraitImpls]>, + pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, + pub interpret_alloc_index: Lazy<[u32]>, - pub entries_index: LazySeq>, + pub entries_index: Lazy<[index::Index<'tcx>]>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -202,7 +205,7 @@ pub struct CrateDep { #[derive(RustcEncodable, RustcDecodable)] pub struct TraitImpls { pub trait_id: (u32, DefIndex), - pub impls: LazySeq, + pub impls: Lazy<[DefIndex]>, } #[derive(RustcEncodable, RustcDecodable)] @@ -210,14 +213,14 @@ pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, pub visibility: Lazy, pub span: Lazy, - pub attributes: LazySeq, - pub children: LazySeq, + pub attributes: Lazy<[ast::Attribute]>, + pub children: Lazy<[DefIndex]>, pub stability: Option>, pub deprecation: Option>, pub ty: Option>>, - pub inherent_impls: LazySeq, - pub variances: LazySeq, + pub inherent_impls: Lazy<[DefIndex]>, + pub variances: Lazy<[ty::Variance]>, pub generics: Option>, pub predicates: Option>>, pub predicates_defined_on: Option>>, @@ -273,7 +276,7 @@ pub struct RenderedConst(pub String); #[derive(RustcEncodable, RustcDecodable)] pub struct ModData { - pub reexports: LazySeq>, + pub reexports: Lazy<[def::Export]>, } #[derive(RustcEncodable, RustcDecodable)] @@ -285,7 +288,7 @@ pub struct MacroDef { #[derive(RustcEncodable, RustcDecodable)] pub struct FnData<'tcx> { pub constness: hir::Constness, - pub arg_names: LazySeq, + pub arg_names: Lazy<[ast::Name]>, pub sig: Lazy>, } From 78fa21dc34921e7db9a6b6931e50a1a78a881f53 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 18:24:38 +0300 Subject: [PATCH 05/14] rustc_metadata: use NonZeroUsize for the position of a Lazy. --- src/librustc_metadata/decoder.rs | 20 +++++++++++++------- src/librustc_metadata/encoder.rs | 16 +++++++++------- src/librustc_metadata/index.rs | 11 ++++++----- src/librustc_metadata/schema.rs | 13 +++++++------ 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index a78f2b7eeac1b..7d8421c85e216 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -24,6 +24,7 @@ use rustc::util::captures::Captures; use std::io; use std::mem; +use std::num::NonZeroUsize; use std::u32; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; @@ -129,7 +130,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx> impl<'a, 'tcx: 'a, T: Decodable> Lazy { pub fn decode>(self, meta: M) -> T { - let mut dcx = meta.decoder(self.position); + let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } @@ -140,7 +141,7 @@ impl<'a, 'tcx: 'a, T: Decodable> Lazy<[T]> { self, meta: M, ) -> impl Iterator + Captures<'tcx> + 'a { - let mut dcx = meta.decoder(self.position); + let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } @@ -164,13 +165,14 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { let position = match self.lazy_state { LazyState::NoNode => bug!("read_lazy_with_meta: outside of a metadata node"), LazyState::NodeStart(start) => { + let start = start.get(); assert!(distance + min_size <= start); start - distance - min_size } - LazyState::Previous(last_min_end) => last_min_end + distance, + LazyState::Previous(last_min_end) => last_min_end.get() + distance, }; - self.lazy_state = LazyState::Previous(position + min_size); - Ok(Lazy::from_position_and_meta(position, meta)) + self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); + Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) } } @@ -375,7 +377,9 @@ impl<'tcx> MetadataBlob { } pub fn get_rustc_version(&self) -> String { - Lazy::::from_position(METADATA_HEADER.len() + 4).decode(self) + Lazy::::from_position( + NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap(), + ).decode(self) } pub fn get_root(&self) -> CrateRoot<'tcx> { @@ -384,7 +388,9 @@ impl<'tcx> MetadataBlob { let pos = (((slice[offset + 0] as u32) << 24) | ((slice[offset + 1] as u32) << 16) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::>::from_position(pos).decode(self) + Lazy::>::from_position( + NonZeroUsize::new(pos).unwrap(), + ).decode(self) } pub fn list_crate_metadata(&self, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 1864f2e9992ef..c71dd155891c4 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -22,11 +22,12 @@ use rustc::session::config::{self, CrateType}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; +use rustc_data_structures::sync::Lrc; use rustc_serialize::{Encodable, Encoder, SpecializedEncoder, opaque}; use std::hash::Hash; +use std::num::NonZeroUsize; use std::path::Path; -use rustc_data_structures::sync::Lrc; use std::u32; use syntax::ast; use syntax::attr; @@ -263,10 +264,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { &mut self, lazy: Lazy, ) -> Result<(), ::Error> { - let min_end = lazy.position + T::min_size(lazy.meta); + let min_end = lazy.position.get() + T::min_size(lazy.meta); let distance = match self.lazy_state { LazyState::NoNode => bug!("emit_lazy_distance: outside of a metadata node"), LazyState::NodeStart(start) => { + let start = start.get(); assert!(min_end <= start); start - min_end } @@ -276,10 +278,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { "make sure that the calls to `lazy*` \ are in the same order as the metadata fields", ); - lazy.position - last_min_end + lazy.position.get() - last_min_end.get() } }; - self.lazy_state = LazyState::Previous(min_end); + self.lazy_state = LazyState::Previous(NonZeroUsize::new(min_end).unwrap()); self.emit_usize(distance) } @@ -287,14 +289,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { &mut self, value: impl EncodeContentsForLazy, ) -> Lazy { - let pos = self.position(); + 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); self.lazy_state = LazyState::NoNode; - assert!(pos + ::min_size(meta) <= self.position()); + assert!(pos.get() + ::min_size(meta) <= self.position()); Lazy::from_position_and_meta(pos, meta) } @@ -1893,7 +1895,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) // Encode the root position. let header = METADATA_HEADER.len(); - let pos = root.position; + let pos = root.position.get(); result[header + 0] = (pos >> 24) as u8; result[header + 1] = (pos >> 16) as u8; result[header + 2] = (pos >> 8) as u8; diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 85c3810c059f6..58ffa03a10fc0 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -3,6 +3,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; use rustc_serialize::opaque::Encoder; use std::marker::PhantomData; +use std::num::NonZeroUsize; use std::u32; use log::debug; @@ -95,8 +96,8 @@ impl Index<'tcx> { } pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { - assert!(entry.position < (u32::MAX as usize)); - let position = entry.position as u32; + assert!(entry.position.get() < (u32::MAX as usize)); + let position = entry.position.get() as u32; let space_index = item.address_space().index(); let array_index = item.as_array_index(); @@ -120,7 +121,7 @@ impl Index<'tcx> { // ... then the values in the higher range. buf.emit_raw_bytes(&self.positions[1]); Lazy::from_position_and_meta( - pos as usize, + NonZeroUsize::new(pos as usize).unwrap(), (self.positions[0].len() + self.positions[1].len()) / 4 + 1, ) } @@ -131,7 +132,7 @@ impl Lazy<[Index<'tcx>]> { /// DefIndex (if any). #[inline(never)] pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { - let bytes = &bytes[self.position..]; + let bytes = &bytes[self.position.get()..]; debug!("Index::lookup: index={:?} len={:?}", def_index, self.meta); @@ -151,7 +152,7 @@ impl Lazy<[Index<'tcx>]> { None } else { debug!("Index::lookup: position={:?}", position); - Some(Lazy::from_position(position as usize)) + Some(Lazy::from_position(NonZeroUsize::new(position as usize).unwrap())) } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index d2a35b8635c4b..881eddba389e2 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -19,6 +19,7 @@ use syntax::symbol::Symbol; use syntax_pos::{self, Span}; use std::marker::PhantomData; +use std::num::NonZeroUsize; pub fn rustc_version() -> String { format!("rustc {}", @@ -101,13 +102,13 @@ pub struct Lazy::Meta> where T: ?Sized + LazyMeta, Meta: 'static + Copy, { - pub position: usize, + pub position: NonZeroUsize, pub meta: Meta, _marker: PhantomData, } impl Lazy { - pub fn from_position_and_meta(position: usize, meta: T::Meta) -> Lazy { + pub fn from_position_and_meta(position: NonZeroUsize, meta: T::Meta) -> Lazy { Lazy { position, meta, @@ -117,14 +118,14 @@ impl Lazy { } impl Lazy { - pub fn from_position(position: usize) -> Lazy { + pub fn from_position(position: NonZeroUsize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } impl Lazy<[T]> { pub fn empty() -> Lazy<[T]> { - Lazy::from_position_and_meta(0, 0) + Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } } @@ -146,12 +147,12 @@ pub enum LazyState { /// Inside a metadata node, and before any `Lazy`. /// The position is that of the node itself. - NodeStart(usize), + NodeStart(NonZeroUsize), /// Inside a metadata node, with a previous `Lazy`. /// The position is a conservative estimate of where that /// previous `Lazy` would end (see their comments). - Previous(usize), + Previous(NonZeroUsize), } #[derive(RustcEncodable, RustcDecodable)] From 51c5e5f022a8b3f0ac621e6cfd656294ce88998a Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 19:56:59 +0300 Subject: [PATCH 06/14] rustc_metadata: use 0 in index::Index to indicate missing entries. --- src/librustc_metadata/index.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/index.rs index 58ffa03a10fc0..afe61048971a9 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/index.rs @@ -4,7 +4,6 @@ use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; use rustc_serialize::opaque::Encoder; use std::marker::PhantomData; use std::num::NonZeroUsize; -use std::u32; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. @@ -73,7 +72,7 @@ impl FixedSizeEncoding for u32 { /// of each DefIndex. It is not required that all definitions appear /// in the metadata, nor that they are serialized in order, and /// therefore we first allocate the vector here and fill it with -/// `u32::MAX`. Whenever an index is visited, we fill in the +/// `0`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. pub struct Index<'tcx> { @@ -84,8 +83,8 @@ pub struct Index<'tcx> { impl Index<'tcx> { pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { Index { - positions: [vec![0xff; max_index_lo * 4], - vec![0xff; max_index_hi * 4]], + positions: [vec![0; max_index_lo * 4], + vec![0; max_index_hi * 4]], _marker: PhantomData, } } @@ -96,13 +95,13 @@ impl Index<'tcx> { } pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { - assert!(entry.position.get() < (u32::MAX as usize)); let position = entry.position.get() as u32; + assert_eq!(position as usize, entry.position.get()); let space_index = item.address_space().index(); let array_index = item.as_array_index(); let positions = &mut self.positions[space_index]; - assert!(u32::read_from_bytes_at(positions, array_index) == u32::MAX, + assert!(u32::read_from_bytes_at(positions, array_index) == 0, "recorded position for item {:?} twice, first at {:?} and now at {:?}", item, u32::read_from_bytes_at(positions, array_index), @@ -147,12 +146,7 @@ impl Lazy<[Index<'tcx>]> { }; let position = u32::read_from_bytes_at(bytes, 1 + i); - if position == u32::MAX { - debug!("Index::lookup: position=u32::MAX"); - None - } else { - debug!("Index::lookup: position={:?}", position); - Some(Lazy::from_position(NonZeroUsize::new(position as usize).unwrap())) - } + debug!("Index::lookup: position={:?}", position); + NonZeroUsize::new(position as usize).map(Lazy::from_position) } } From 98e04bae899ea1b823dfb6b99aa618581acaaf2e Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 20:11:36 +0300 Subject: [PATCH 07/14] rustc_metadata: rename index::Index to table::Table. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 16 ++++++++-------- src/librustc_metadata/lib.rs | 8 ++++---- src/librustc_metadata/schema.rs | 4 ++-- src/librustc_metadata/{index.rs => table.rs} | 14 +++++++------- 5 files changed, 22 insertions(+), 22 deletions(-) rename src/librustc_metadata/{index.rs => table.rs} (95%) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 7d8421c85e216..acce731af0ce5 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -486,7 +486,7 @@ impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { assert!(!self.is_proc_macro(item_id)); - self.root.entries_index.lookup(self.blob.raw_bytes(), item_id) + self.root.entries_table.lookup(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c71dd155891c4..f43d3f78c0a9c 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ -use crate::index::Index; use crate::schema::*; +use crate::table::Table; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -45,7 +45,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - entries_index: Index<'tcx>, + entries_table: Table<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -316,7 +316,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let entry = op(self, data); let entry = self.lazy(entry); - self.entries_index.record(id, entry); + self.entries_table.record(id, entry); } fn encode_info_for_items(&mut self) { @@ -460,8 +460,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; i = self.position(); - let entries_index = self.entries_index.write_index(&mut self.opaque); - let entries_index_bytes = self.position() - i; + let entries_table = self.entries_table.encode(&mut self.opaque); + let entries_table_bytes = self.position() - i; let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); @@ -512,7 +512,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impls, exported_symbols, interpret_alloc_index, - entries_index, + entries_table, }); let total_bytes = self.position(); @@ -535,7 +535,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); - println!(" entries index bytes: {}", entries_index_bytes); + println!(" entries table bytes: {}", entries_table_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -1875,7 +1875,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_index: Index::new(tcx.hir().definitions().def_index_counts_lo_hi()), + entries_table: Table::new(tcx.hir().definitions().def_index_counts_lo_hi()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs index 47a9c97d40a4b..f7f361522799b 100644 --- a/src/librustc_metadata/lib.rs +++ b/src/librustc_metadata/lib.rs @@ -29,14 +29,14 @@ extern crate rustc_data_structures; mod diagnostics; -mod index; mod encoder; mod decoder; mod cstore_impl; -mod schema; -mod native_libs; -mod link_args; mod foreign_modules; +mod link_args; +mod native_libs; +mod schema; +mod table; pub mod creader; pub mod cstore; diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 881eddba389e2..e0adbf5b0e5a0 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::index; +use crate::table::Table; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -184,7 +184,7 @@ pub struct CrateRoot<'tcx> { pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, pub interpret_alloc_index: Lazy<[u32]>, - pub entries_index: Lazy<[index::Index<'tcx>]>, + pub entries_table: Lazy<[Table<'tcx>]>, pub compiler_builtins: bool, pub needs_allocator: bool, diff --git a/src/librustc_metadata/index.rs b/src/librustc_metadata/table.rs similarity index 95% rename from src/librustc_metadata/index.rs rename to src/librustc_metadata/table.rs index afe61048971a9..0a6e963a265dd 100644 --- a/src/librustc_metadata/index.rs +++ b/src/librustc_metadata/table.rs @@ -75,14 +75,14 @@ impl FixedSizeEncoding for u32 { /// `0`. Whenever an index is visited, we fill in the /// appropriate spot by calling `record_position`. We should never /// visit the same index twice. -pub struct Index<'tcx> { +pub struct Table<'tcx> { positions: [Vec; 2], _marker: PhantomData<&'tcx ()>, } -impl Index<'tcx> { +impl Table<'tcx> { pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { - Index { + Table { positions: [vec![0; max_index_lo * 4], vec![0; max_index_hi * 4]], _marker: PhantomData, @@ -110,7 +110,7 @@ impl Index<'tcx> { position.write_to_bytes_at(positions, array_index) } - pub fn write_index(&self, buf: &mut Encoder) -> Lazy<[Self]> { + pub fn encode(&self, buf: &mut Encoder) -> Lazy<[Self]> { let pos = buf.position(); // First we write the length of the lower range ... @@ -126,13 +126,13 @@ impl Index<'tcx> { } } -impl Lazy<[Index<'tcx>]> { +impl Lazy<[Table<'tcx>]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { let bytes = &bytes[self.position.get()..]; - debug!("Index::lookup: index={:?} len={:?}", + debug!("Table::lookup: index={:?} len={:?}", def_index, self.meta); @@ -146,7 +146,7 @@ impl Lazy<[Index<'tcx>]> { }; let position = u32::read_from_bytes_at(bytes, 1 + i); - debug!("Index::lookup: position={:?}", position); + debug!("Table::lookup: position={:?}", position); NonZeroUsize::new(position as usize).map(Lazy::from_position) } } From 2212aa4398076115d2d3133afe45492a64619417 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 22:52:12 +0300 Subject: [PATCH 08/14] rustc_metadata: parametrize Table by element type. --- src/librustc_metadata/encoder.rs | 2 +- src/librustc_metadata/schema.rs | 54 ++++++++++++++++++-------------- src/librustc_metadata/table.rs | 25 +++++++-------- 3 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f43d3f78c0a9c..8f9c9381f479c 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -45,7 +45,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - entries_table: Table<'tcx>, + entries_table: Table>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index e0adbf5b0e5a0..ecbcc66aacdfb 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -155,6 +155,14 @@ pub enum LazyState { Previous(NonZeroUsize), } +// FIXME(#59875) `Lazy!(T)` replaces `Lazy`, passing the `Meta` parameter +// manually, instead of relying on the default, to get the correct variance. +// Only needed when `T` itself contains a parameter (e.g. `'tcx`). +macro_rules! Lazy { + ([$T:ty]) => {Lazy<[$T], usize>}; + ($T:ty) => {Lazy<$T, ()>}; +} + #[derive(RustcEncodable, RustcDecodable)] pub struct CrateRoot<'tcx> { pub name: Symbol, @@ -181,10 +189,10 @@ pub struct CrateRoot<'tcx> { pub source_map: Lazy<[syntax_pos::SourceFile]>, pub def_path_table: Lazy, pub impls: Lazy<[TraitImpls]>, - pub exported_symbols: Lazy<[(ExportedSymbol<'tcx>, SymbolExportLevel)]>, + pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy<[Table<'tcx>]>, + pub entries_table: Lazy!([Table>]), pub compiler_builtins: bool, pub needs_allocator: bool, @@ -219,14 +227,14 @@ pub struct Entry<'tcx> { pub stability: Option>, pub deprecation: Option>, - pub ty: Option>>, + pub ty: Option)>, pub inherent_impls: Lazy<[DefIndex]>, pub variances: Lazy<[ty::Variance]>, pub generics: Option>, - pub predicates: Option>>, - pub predicates_defined_on: Option>>, + pub predicates: Option)>, + pub predicates_defined_on: Option)>, - pub mir: Option>>, + pub mir: Option)>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] @@ -245,22 +253,22 @@ pub enum EntryKind<'tcx> { Existential, Enum(ReprOptions), Field, - Variant(Lazy>), - Struct(Lazy>, ReprOptions), - Union(Lazy>, ReprOptions), - Fn(Lazy>), - ForeignFn(Lazy>), + Variant(Lazy!(VariantData<'tcx>)), + Struct(Lazy!(VariantData<'tcx>), ReprOptions), + Union(Lazy!(VariantData<'tcx>), ReprOptions), + Fn(Lazy!(FnData<'tcx>)), + ForeignFn(Lazy!(FnData<'tcx>)), Mod(Lazy), MacroDef(Lazy), - Closure(Lazy>), - Generator(Lazy>), - Trait(Lazy>), - Impl(Lazy>), - Method(Lazy>), + Closure(Lazy!(ClosureData<'tcx>)), + Generator(Lazy!(GeneratorData<'tcx>)), + Trait(Lazy!(TraitData<'tcx>)), + Impl(Lazy!(ImplData<'tcx>)), + Method(Lazy!(MethodData<'tcx>)), AssociatedType(AssociatedContainer), AssociatedExistential(AssociatedContainer), AssociatedConst(AssociatedContainer, ConstQualif, Lazy), - TraitAlias(Lazy>), + TraitAlias(Lazy!(TraitAliasData<'tcx>)), } /// Additional data for EntryKind::Const and EntryKind::AssociatedConst @@ -290,7 +298,7 @@ pub struct MacroDef { pub struct FnData<'tcx> { pub constness: hir::Constness, pub arg_names: Lazy<[ast::Name]>, - pub sig: Lazy>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] @@ -301,7 +309,7 @@ pub struct VariantData<'tcx> { pub ctor: Option, /// If this is a tuple struct or variant /// ctor, this is its "function" signature. - pub ctor_sig: Option>>, + pub ctor_sig: Option)>, } #[derive(RustcEncodable, RustcDecodable)] @@ -310,12 +318,12 @@ pub struct TraitData<'tcx> { pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] pub struct TraitAliasData<'tcx> { - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] @@ -326,7 +334,7 @@ pub struct ImplData<'tcx> { /// This is `Some` only for impls of `CoerceUnsized`. pub coerce_unsized_info: Option, - pub trait_ref: Option>>, + pub trait_ref: Option)>, } @@ -377,7 +385,7 @@ pub struct MethodData<'tcx> { #[derive(RustcEncodable, RustcDecodable)] pub struct ClosureData<'tcx> { - pub sig: Lazy>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 0a6e963a265dd..44848d89fb7fb 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -68,19 +68,16 @@ impl FixedSizeEncoding for u32 { } } -/// While we are generating the metadata, we also track the position -/// of each DefIndex. It is not required that all definitions appear -/// in the metadata, nor that they are serialized in order, and -/// therefore we first allocate the vector here and fill it with -/// `0`. Whenever an index is visited, we fill in the -/// appropriate spot by calling `record_position`. We should never -/// visit the same index twice. -pub struct Table<'tcx> { +/// Random-access position table, allowing encoding in an arbitrary order +/// (e.g. while visiting the definitions of a crate), and on-demand decoding +/// of specific indices (e.g. queries for per-definition data). +/// Similar to `Vec>`, but with zero-copy decoding. +pub struct Table { positions: [Vec; 2], - _marker: PhantomData<&'tcx ()>, + _marker: PhantomData, } -impl Table<'tcx> { +impl Table { pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { Table { positions: [vec![0; max_index_lo * 4], @@ -89,12 +86,12 @@ impl Table<'tcx> { } } - pub fn record(&mut self, def_id: DefId, entry: Lazy>) { + pub fn record(&mut self, def_id: DefId, entry: Lazy) { assert!(def_id.is_local()); self.record_index(def_id.index, entry); } - pub fn record_index(&mut self, item: DefIndex, entry: Lazy>) { + pub fn record_index(&mut self, item: DefIndex, entry: Lazy) { let position = entry.position.get() as u32; assert_eq!(position as usize, entry.position.get()); let space_index = item.address_space().index(); @@ -126,11 +123,11 @@ impl Table<'tcx> { } } -impl Lazy<[Table<'tcx>]> { +impl Lazy<[Table]> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] - pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option>> { + pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { let bytes = &bytes[self.position.get()..]; debug!("Table::lookup: index={:?} len={:?}", def_index, From 538f8828de07e3a6ac2c8b99d1b3d92551fe02b8 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 11 Apr 2019 23:36:00 +0300 Subject: [PATCH 09/14] rustc_metadata: replace Lazy<[Table]> with Lazy>. --- src/librustc_metadata/decoder.rs | 19 ++++++++++++++----- src/librustc_metadata/encoder.rs | 15 ++++++++++++--- src/librustc_metadata/schema.rs | 13 +++++++------ src/librustc_metadata/table.rs | 18 +++++++++++++----- 4 files changed, 46 insertions(+), 19 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index acce731af0ce5..9a346ad3524da 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,6 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use crate::schema::*; +use crate::table::Table; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; @@ -27,7 +28,7 @@ use std::mem; use std::num::NonZeroUsize; use std::u32; -use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; +use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map; @@ -128,7 +129,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx> } } -impl<'a, 'tcx: 'a, T: Decodable> Lazy { +impl<'a, 'tcx: 'a, T: Encodable + Decodable> Lazy { pub fn decode>(self, meta: M) -> T { let mut dcx = meta.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); @@ -136,7 +137,7 @@ impl<'a, 'tcx: 'a, T: Decodable> Lazy { } } -impl<'a, 'tcx: 'a, T: Decodable> Lazy<[T]> { +impl<'a, 'tcx: 'a, T: Encodable + Decodable> Lazy<[T]> { pub fn decode>( self, meta: M, @@ -236,13 +237,13 @@ impl<'a, 'tcx: 'a> TyDecoder<'a, 'tcx> for DecodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { self.read_lazy_with_meta(()) } } -impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, 'tcx> { fn specialized_decode(&mut self) -> Result, Self::Error> { let len = self.read_usize()?; if len == 0 { @@ -253,6 +254,14 @@ impl<'a, 'tcx, T> SpecializedDecoder> for DecodeContext<'a, 'tcx> { } } +impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> + where T: LazyMeta, +{ + fn specialized_decode(&mut self) -> Result>, Self::Error> { + let len = self.read_usize()?; + self.read_lazy_with_meta(len) + } +} impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 8f9c9381f479c..d8fee4ffc1f5d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -96,13 +96,13 @@ impl<'a, 'tcx> Encoder for EncodeContext<'a, 'tcx> { } } -impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, lazy: &Lazy) -> Result<(), Self::Error> { self.emit_lazy_distance(*lazy) } } -impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { +impl<'a, 'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'a, 'tcx> { fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta)?; if lazy.meta == 0 { @@ -112,6 +112,15 @@ impl<'a, 'tcx, T> SpecializedEncoder> for EncodeContext<'a, 'tcx> { } } +impl<'a, 'tcx, T> SpecializedEncoder>> for EncodeContext<'a, 'tcx> + where T: LazyMeta, +{ + fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { + self.emit_usize(lazy.meta)?; + self.emit_lazy_distance(*lazy) + } +} + impl<'a, 'tcx> SpecializedEncoder for EncodeContext<'a, 'tcx> { #[inline] fn specialized_encode(&mut self, cnum: &CrateNum) -> Result<(), Self::Error> { @@ -250,7 +259,7 @@ impl EncodeContentsForLazy for T { } } -impl EncodeContentsForLazy<[T]> for I +impl EncodeContentsForLazy<[T]> for I where I: IntoIterator, I::Item: EncodeContentsForLazy, { diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index ecbcc66aacdfb..0d5efbcc70c31 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -12,7 +12,7 @@ use rustc::ty::{self, Ty, ReprOptions}; use rustc_target::spec::{PanicStrategy, TargetTriple}; use rustc_data_structures::svh::Svh; -use rustc_serialize as serialize; +use rustc_serialize::{self as serialize, Encodable}; use syntax::{ast, attr}; use syntax::edition::Edition; use syntax::symbol::Symbol; @@ -52,7 +52,7 @@ pub trait LazyMeta { fn min_size(meta: Self::Meta) -> usize; } -impl LazyMeta for T { +impl LazyMeta for T { type Meta = (); fn min_size(_: ()) -> usize { @@ -61,7 +61,7 @@ impl LazyMeta for T { } } -impl LazyMeta for [T] { +impl LazyMeta for [T] { type Meta = usize; fn min_size(len: usize) -> usize { @@ -117,13 +117,13 @@ impl Lazy { } } -impl Lazy { +impl Lazy { pub fn from_position(position: NonZeroUsize) -> Lazy { Lazy::from_position_and_meta(position, ()) } } -impl Lazy<[T]> { +impl Lazy<[T]> { pub fn empty() -> Lazy<[T]> { Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } @@ -159,6 +159,7 @@ pub enum LazyState { // manually, instead of relying on the default, to get the correct variance. // Only needed when `T` itself contains a parameter (e.g. `'tcx`). macro_rules! Lazy { + (Table<$T:ty>) => {Lazy, usize>}; ([$T:ty]) => {Lazy<[$T], usize>}; ($T:ty) => {Lazy<$T, ()>}; } @@ -192,7 +193,7 @@ pub struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!([Table>]), + pub entries_table: Lazy!(Table>), pub compiler_builtins: bool, pub needs_allocator: bool, diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 44848d89fb7fb..303c4ccabf141 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -1,7 +1,7 @@ use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; -use rustc_serialize::opaque::Encoder; +use rustc_serialize::{Encodable, opaque::Encoder}; use std::marker::PhantomData; use std::num::NonZeroUsize; use log::debug; @@ -72,12 +72,12 @@ impl FixedSizeEncoding for u32 { /// (e.g. while visiting the definitions of a crate), and on-demand decoding /// of specific indices (e.g. queries for per-definition data). /// Similar to `Vec>`, but with zero-copy decoding. -pub struct Table { +pub struct Table> { positions: [Vec; 2], _marker: PhantomData, } -impl Table { +impl> Table { pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { Table { positions: [vec![0; max_index_lo * 4], @@ -107,7 +107,7 @@ impl Table { position.write_to_bytes_at(positions, array_index) } - pub fn encode(&self, buf: &mut Encoder) -> Lazy<[Self]> { + pub fn encode(&self, buf: &mut Encoder) -> Lazy { let pos = buf.position(); // First we write the length of the lower range ... @@ -123,7 +123,15 @@ impl Table { } } -impl Lazy<[Table]> { +impl> LazyMeta for Table { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len * 4 + } +} + +impl Lazy> { /// Given the metadata, extract out the offset of a particular /// DefIndex (if any). #[inline(never)] From 47dfc2f6d19ee34e948a60d6d6fd1c80a80258bc Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 19:18:12 +0300 Subject: [PATCH 10/14] rustc_metadata: split tables into an usize-keyed Table and a DefIndex-keyed PerDefTable. --- src/librustc_metadata/decoder.rs | 13 +-- src/librustc_metadata/encoder.rs | 13 +-- src/librustc_metadata/schema.rs | 6 +- src/librustc_metadata/table.rs | 131 ++++++++++++++++++++----------- 4 files changed, 103 insertions(+), 60 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 9a346ad3524da..d723e8d0574b7 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,7 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use crate::schema::*; -use crate::table::Table; +use crate::table::PerDefTable; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; @@ -254,12 +254,15 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, } } -impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> +impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> where T: LazyMeta, { - fn specialized_decode(&mut self) -> Result>, Self::Error> { - let len = self.read_usize()?; - self.read_lazy_with_meta(len) + fn specialized_decode(&mut self) -> Result>, Self::Error> { + let lo_hi = [ + self.read_usize()?, + self.read_usize()?, + ]; + self.read_lazy_with_meta(lo_hi) } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index d8fee4ffc1f5d..2b8c56e5b2e67 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ use crate::schema::*; -use crate::table::Table; +use crate::table::PerDefTable; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -45,7 +45,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - entries_table: Table>, + entries_table: PerDefTable>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -112,11 +112,12 @@ impl<'a, 'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'a, } } -impl<'a, 'tcx, T> SpecializedEncoder>> for EncodeContext<'a, 'tcx> +impl<'a, 'tcx, T> SpecializedEncoder>> for EncodeContext<'a, 'tcx> where T: LazyMeta, { - fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { - self.emit_usize(lazy.meta)?; + fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { + self.emit_usize(lazy.meta[0])?; + self.emit_usize(lazy.meta[1])?; self.emit_lazy_distance(*lazy) } } @@ -1884,7 +1885,7 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_table: Table::new(tcx.hir().definitions().def_index_counts_lo_hi()), + entries_table: PerDefTable::new(tcx.hir().definitions().def_index_counts_lo_hi()), lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 0d5efbcc70c31..f5d1393630f9b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,4 +1,4 @@ -use crate::table::Table; +use crate::table::PerDefTable; use rustc::hir; use rustc::hir::def::{self, CtorKind}; @@ -159,7 +159,7 @@ pub enum LazyState { // manually, instead of relying on the default, to get the correct variance. // Only needed when `T` itself contains a parameter (e.g. `'tcx`). macro_rules! Lazy { - (Table<$T:ty>) => {Lazy, usize>}; + (PerDefTable<$T:ty>) => {Lazy, [usize; 2]>}; ([$T:ty]) => {Lazy<[$T], usize>}; ($T:ty) => {Lazy<$T, ()>}; } @@ -193,7 +193,7 @@ pub struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!(Table>), + pub entries_table: Lazy!(PerDefTable>), pub compiler_builtins: bool, pub needs_allocator: bool, diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 303c4ccabf141..6e461a11919a7 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -72,53 +72,42 @@ impl FixedSizeEncoding for u32 { /// (e.g. while visiting the definitions of a crate), and on-demand decoding /// of specific indices (e.g. queries for per-definition data). /// Similar to `Vec>`, but with zero-copy decoding. +// FIXME(eddyb) newtype `[u8]` here, such that `Box>` would be used +// when building it, and `Lazy>` or `&Table` when reading it. +// Sadly, that doesn't work for `DefPerTable`, which is `(Table, Table)`, +// and so would need two lengths in its metadata, which is not supported yet. pub struct Table> { - positions: [Vec; 2], + bytes: Vec, _marker: PhantomData, } impl> Table { - pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { + pub fn new(len: usize) -> Self { Table { - positions: [vec![0; max_index_lo * 4], - vec![0; max_index_hi * 4]], + bytes: vec![0; len * 4], _marker: PhantomData, } } - pub fn record(&mut self, def_id: DefId, entry: Lazy) { - assert!(def_id.is_local()); - self.record_index(def_id.index, entry); - } - - pub fn record_index(&mut self, item: DefIndex, entry: Lazy) { + pub fn record(&mut self, i: usize, entry: Lazy) { let position = entry.position.get() as u32; assert_eq!(position as usize, entry.position.get()); - let space_index = item.address_space().index(); - let array_index = item.as_array_index(); - - let positions = &mut self.positions[space_index]; - assert!(u32::read_from_bytes_at(positions, array_index) == 0, - "recorded position for item {:?} twice, first at {:?} and now at {:?}", - item, - u32::read_from_bytes_at(positions, array_index), + + assert!(u32::read_from_bytes_at(&self.bytes, i) == 0, + "recorded position for index {:?} twice, first at {:?} and now at {:?}", + i, + u32::read_from_bytes_at(&self.bytes, i), position); - position.write_to_bytes_at(positions, array_index) + position.write_to_bytes_at(&mut self.bytes, i) } pub fn encode(&self, buf: &mut Encoder) -> Lazy { let pos = buf.position(); - - // First we write the length of the lower range ... - buf.emit_raw_bytes(&(self.positions[0].len() as u32 / 4).to_le_bytes()); - // ... then the values in the lower range ... - buf.emit_raw_bytes(&self.positions[0]); - // ... then the values in the higher range. - buf.emit_raw_bytes(&self.positions[1]); + buf.emit_raw_bytes(&self.bytes); Lazy::from_position_and_meta( NonZeroUsize::new(pos as usize).unwrap(), - (self.positions[0].len() + self.positions[1].len()) / 4 + 1, + self.bytes.len(), ) } } @@ -127,31 +116,81 @@ impl> LazyMeta for Table { type Meta = usize; fn min_size(len: usize) -> usize { - len * 4 + len } } impl Lazy> { - /// Given the metadata, extract out the offset of a particular - /// DefIndex (if any). + /// Given the metadata, extract out the offset of a particular index (if any). #[inline(never)] - pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { - let bytes = &bytes[self.position.get()..]; - debug!("Table::lookup: index={:?} len={:?}", - def_index, - self.meta); - - let i = def_index.as_array_index() + match def_index.address_space() { - DefIndexAddressSpace::Low => 0, - DefIndexAddressSpace::High => { - // This is a DefIndex in the higher range, so find out where - // that starts: - u32::read_from_bytes_at(bytes, 0) as usize - } - }; - - let position = u32::read_from_bytes_at(bytes, 1 + i); + pub fn lookup(&self, bytes: &[u8], i: usize) -> Option> { + debug!("Table::lookup: index={:?} len={:?}", i, self.meta); + + let bytes = &bytes[self.position.get()..][..self.meta]; + let position = u32::read_from_bytes_at(bytes, i); debug!("Table::lookup: position={:?}", position); + NonZeroUsize::new(position as usize).map(Lazy::from_position) } } + + +/// Per-definition table, similar to `Table` but keyed on `DefIndex`. +/// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in. +pub struct PerDefTable> { + lo: Table, + hi: Table, +} + +impl> PerDefTable { + pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { + PerDefTable { + lo: Table::new(max_index_lo), + hi: Table::new(max_index_hi), + } + } + + pub fn record(&mut self, def_id: DefId, entry: Lazy) { + assert!(def_id.is_local()); + let space_index = def_id.index.address_space().index(); + let array_index = def_id.index.as_array_index(); + [&mut self.lo, &mut self.hi][space_index].record(array_index, entry); + } + + pub fn encode(&self, buf: &mut Encoder) -> Lazy { + let lo = self.lo.encode(buf); + let hi = self.hi.encode(buf); + assert_eq!(lo.position.get() + lo.meta, hi.position.get()); + + Lazy::from_position_and_meta( + lo.position, + [lo.meta, hi.meta], + ) + } +} + +impl> LazyMeta for PerDefTable { + type Meta = [ as LazyMeta>::Meta; 2]; + + fn min_size([lo, hi]: Self::Meta) -> usize { + Table::::min_size(lo) + Table::::min_size(hi) + } +} + +impl Lazy> { + fn table_for_space(&self, space: DefIndexAddressSpace) -> Lazy> { + let space_index = space.index(); + let offset = space_index.checked_sub(1).map_or(0, |i| self.meta[i]); + Lazy::from_position_and_meta( + NonZeroUsize::new(self.position.get() + offset).unwrap(), + self.meta[space_index] + ) + } + + /// Given the metadata, extract out the offset of a particular DefIndex (if any). + #[inline(never)] + pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { + self.table_for_space(def_index.address_space()) + .lookup(bytes, def_index.as_array_index()) + } +} From 010958c8bb0cd2044e4527550cfd8ddec02a97ef Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 21:52:18 +0300 Subject: [PATCH 11/14] rustc_metadata: add a helper macro for recording into PerDefTable's. --- src/librustc_metadata/decoder.rs | 2 +- src/librustc_metadata/encoder.rs | 943 ++++++++++++++++--------------- src/librustc_metadata/schema.rs | 7 +- 3 files changed, 498 insertions(+), 454 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index d723e8d0574b7..b4062bef4fe28 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -498,7 +498,7 @@ impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { assert!(!self.is_proc_macro(item_id)); - self.root.entries_table.lookup(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.lookup(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 2b8c56e5b2e67..0ca6badabe506 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -45,7 +45,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, - entries_table: PerDefTable>, + per_def: PerDefTables<'tcx>, lazy_state: LazyState, type_shorthands: FxHashMap, usize>, @@ -58,6 +58,10 @@ pub struct EncodeContext<'a, 'tcx: 'a> { source_file_cache: Lrc, } +struct PerDefTables<'tcx> { + entry: PerDefTable>, +} + macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { @@ -269,6 +273,18 @@ impl EncodeContentsForLazy<[T]> for I } } +// Shorthand for `$self.$tables.$table.record($key, $self.lazy($value))`, which would +// normally need extra variables to avoid errors about multiple mutable borrows. +macro_rules! record { + ($self:ident.$tables:ident[$key:expr]: $($table:ident => $value:expr,)+) => {{ + $({ + let value = $value; + let lazy = $self.lazy(value); + $self.$tables.$table.record($key, lazy); + })+ + }} +} + impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn emit_lazy_distance( &mut self, @@ -311,30 +327,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { Lazy::from_position_and_meta(pos, meta) } - /// Emit the data for a `DefId` to the metadata. The function to - /// emit the data is `op`, and it will be given `data` as - /// arguments. This `record` function will call `op` to generate - /// the `Entry` (which may point to other encoded information) - /// and will then record the `Lazy` for use in the index. - // FIXME(eddyb) remove this. - pub fn record(&mut self, - id: DefId, - op: impl FnOnce(&mut Self, DATA) -> Entry<'tcx>, - data: DATA) - { - assert!(id.is_local()); - - let entry = op(self, data); - let entry = self.lazy(entry); - self.entries_table.record(id, entry); - } - fn encode_info_for_items(&mut self) { let krate = self.tcx.hir().krate(); let vis = Spanned { span: syntax_pos::DUMMY_SP, node: hir::VisibilityKind::Public }; - self.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, - (hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis)); + self.encode_info_for_mod(hir::CRATE_HIR_ID, &krate.module, &krate.attrs, &vis); krate.visit_all_item_likes(&mut self.as_deep_visitor()); for macro_def in &krate.exported_macros { self.visit_macro_def(macro_def); @@ -470,8 +466,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }; i = self.position(); - let entries_table = self.entries_table.encode(&mut self.opaque); - let entries_table_bytes = self.position() - i; + let per_def = LazyPerDefTables { + entry: self.per_def.entry.encode(&mut self.opaque), + }; + let per_def_bytes = self.position() - i; let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); @@ -522,7 +520,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impls, exported_symbols, interpret_alloc_index, - entries_table, + per_def, }); let total_bytes = self.position(); @@ -545,7 +543,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { println!(" exp. symbols bytes: {}", exported_symbols_bytes); println!(" def-path table bytes: {}", def_path_table_bytes); println!(" item bytes: {}", item_bytes); - println!(" entries table bytes: {}", entries_table_bytes); + println!(" per-def table bytes: {}", per_def_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -570,8 +568,9 @@ impl EncodeContext<'_, 'tcx> { fn encode_enum_variant_info( &mut self, - (enum_did, index): (DefId, VariantIdx), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -588,37 +587,42 @@ impl EncodeContext<'_, 'tcx> { let enum_id = tcx.hir().as_local_hir_id(enum_did).unwrap(); let enum_vis = &tcx.hir().expect_item_by_hir_id(enum_id).vis; - Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy(variant.fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), + span: self.lazy(tcx.def_span(def_id)), + attributes: self.encode_attributes(&tcx.get_attrs(def_id)), + children: self.lazy(variant.fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + Lazy::empty() + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, - mir: self.encode_optimized_mir(def_id), + mir: self.encode_optimized_mir(def_id), + }, } } fn encode_enum_variant_ctor( &mut self, - (enum_did, index): (DefId, VariantIdx), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { let tcx = self.tcx; let def = tcx.adt_def(enum_did); let variant = &def.variants[index]; @@ -645,34 +649,41 @@ impl EncodeContext<'_, 'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::Variant(self.lazy(data)), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + Lazy::empty() + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, - mir: self.encode_optimized_mir(def_id), + mir: self.encode_optimized_mir(def_id), + }, } } fn encode_info_for_mod( &mut self, - (id, md, attrs, vis): (hir::HirId, &hir::Mod, &[ast::Attribute], &hir::Visibility), - ) -> Entry<'tcx> { + id: hir::HirId, + md: &hir::Mod, + attrs: &[ast::Attribute], + vis: &hir::Visibility, + ) { let tcx = self.tcx; let def_id = tcx.hir().local_def_id_from_hir_id(id); debug!("EncodeContext::encode_info_for_mod({:?})", def_id); @@ -684,32 +695,38 @@ impl EncodeContext<'_, 'tcx> { }, }; - Entry { - kind: EntryKind::Mod(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(attrs), - children: self.lazy(md.item_ids.iter().map(|item_id| { - tcx.hir().local_def_id_from_hir_id(item_id.id).index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::Mod(self.lazy(data)), + visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), + span: self.lazy(tcx.def_span(def_id)), + attributes: self.encode_attributes(attrs), + children: self.lazy(md.item_ids.iter().map(|item_id| { + tcx.hir().local_def_id_from_hir_id(item_id.id).index + })), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: None, + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + + mir: None + }, } } fn encode_field( &mut self, - (adt_def_id, variant_index, field_index): (DefId, VariantIdx, usize), - ) -> Entry<'tcx> { + adt_def_id: DefId, + variant_index: VariantIdx, + field_index: usize, + ) { let tcx = self.tcx; let variant = &tcx.adt_def(adt_def_id).variants[variant_index]; let field = &variant.fields[field_index]; @@ -720,27 +737,31 @@ impl EncodeContext<'_, 'tcx> { let variant_id = tcx.hir().as_local_hir_id(variant.def_id).unwrap(); let variant_data = tcx.hir().expect_variant_data(variant_id); - Entry { - kind: EntryKind::Field, - visibility: self.lazy(field.vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::Field, + visibility: self.lazy(field.vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, + + mir: None, + }, } } - fn encode_struct_ctor(&mut self, (adt_def_id, def_id): (DefId, DefId)) -> Entry<'tcx> { + fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { debug!("EncodeContext::encode_struct_ctor({:?})", def_id); let tcx = self.tcx; let adt_def = tcx.adt_def(adt_def_id); @@ -776,27 +797,31 @@ impl EncodeContext<'_, 'tcx> { let repr_options = get_repr_options(&tcx, adt_def_id); - Entry { - kind: EntryKind::Struct(self.lazy(data), repr_options), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::Struct(self.lazy(data), repr_options), + visibility: self.lazy(ctor_vis), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id) + } else { + Lazy::empty() + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, - mir: self.encode_optimized_mir(def_id), + mir: self.encode_optimized_mir(def_id), + }, } } @@ -818,7 +843,7 @@ impl EncodeContext<'_, 'tcx> { self.lazy(&*tcx.predicates_defined_on(def_id)) } - fn encode_info_for_trait_item(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_trait_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_trait_item({:?})", def_id); let tcx = self.tcx; @@ -879,40 +904,44 @@ impl EncodeContext<'_, 'tcx> { span_bug!(ast_item.span, "existential type in trait"), }; - Entry { - kind, - visibility: self.lazy(trait_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match trait_item.kind { - ty::AssociatedKind::Const | - ty::AssociatedKind::Method => { - Some(self.encode_item_type(def_id)) - } - ty::AssociatedKind::Type => { - if trait_item.defaultness.has_value() { + record! { + self.per_def[def_id]: + + entry => Entry { + kind, + visibility: self.lazy(trait_item.vis), + span: self.lazy(ast_item.span), + attributes: self.encode_attributes(&ast_item.attrs), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match trait_item.kind { + ty::AssociatedKind::Const | + ty::AssociatedKind::Method => { Some(self.encode_item_type(def_id)) - } else { - None } - } - ty::AssociatedKind::Existential => unreachable!(), - }, - inherent_impls: Lazy::empty(), - variances: if trait_item.kind == ty::AssociatedKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, + ty::AssociatedKind::Type => { + if trait_item.defaultness.has_value() { + Some(self.encode_item_type(def_id)) + } else { + None + } + } + ty::AssociatedKind::Existential => unreachable!(), + }, + inherent_impls: Lazy::empty(), + variances: if trait_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + Lazy::empty() + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, - mir: self.encode_optimized_mir(def_id), + mir: self.encode_optimized_mir(def_id), + }, } } @@ -928,7 +957,7 @@ impl EncodeContext<'_, 'tcx> { ConstQualif { mir, ast_promotable } } - fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_impl_item(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_impl_item({:?})", def_id); let tcx = self.tcx; @@ -991,27 +1020,31 @@ impl EncodeContext<'_, 'tcx> { hir::ImplItemKind::Type(..) => false, }; - Entry { - kind, - visibility: self.lazy(impl_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if impl_item.kind == ty::AssociatedKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind, + visibility: self.lazy(impl_item.vis), + span: self.lazy(ast_item.span), + attributes: self.encode_attributes(&ast_item.attrs), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: if impl_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id) + } else { + Lazy::empty() + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, - mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + }, } } @@ -1073,7 +1106,7 @@ impl EncodeContext<'_, 'tcx> { self.lazy(rendered_const) } - fn encode_info_for_item(&mut self, (def_id, item): (DefId, &'tcx hir::Item)) -> Entry<'tcx> { + fn encode_info_for_item(&mut self, def_id: DefId, item: &'tcx hir::Item) { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_item({:?})", def_id); @@ -1098,7 +1131,7 @@ impl EncodeContext<'_, 'tcx> { EntryKind::Fn(self.lazy(data)) } hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod((item.hir_id, m, &item.attrs, &item.vis)); + return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis); } hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, @@ -1192,154 +1225,164 @@ impl EncodeContext<'_, 'tcx> { hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }; - Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(item.span), - attributes: self.encode_attributes(&item.attrs), - children: match item.node { - hir::ItemKind::ForeignMod(ref fm) => { - self.lazy(fm.items - .iter() - .map(|foreign_item| tcx.hir().local_def_id_from_hir_id( - foreign_item.hir_id).index)) - } - hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.variants.iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - })) - } - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.non_enum_variant().fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })) - } - hir::ItemKind::Impl(..) | - hir::ItemKind::Trait(..) => { - self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - })) - } - _ => Lazy::empty(), - }, - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match item.node { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), - _ => None, - }, - inherent_impls: self.encode_inherent_implementations(def_id), - variances: match item.node { - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: match item.node { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), - hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), - _ => None, - }, - predicates: match item.node { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), - _ => None, - }, + record! { + self.per_def[def_id]: + + entry => Entry { + kind, + visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), + span: self.lazy(item.span), + attributes: self.encode_attributes(&item.attrs), + children: match item.node { + hir::ItemKind::ForeignMod(ref fm) => { + self.lazy(fm.items + .iter() + .map(|foreign_item| tcx.hir().local_def_id_from_hir_id( + foreign_item.hir_id).index)) + } + hir::ItemKind::Enum(..) => { + let def = self.tcx.adt_def(def_id); + self.lazy(def.variants.iter().map(|v| { + assert!(v.def_id.is_local()); + v.def_id.index + })) + } + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) => { + let def = self.tcx.adt_def(def_id); + self.lazy(def.non_enum_variant().fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + })) + } + hir::ItemKind::Impl(..) | + hir::ItemKind::Trait(..) => { + self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + })) + } + _ => Lazy::empty(), + }, + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: match item.node { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::Ty(..) | + hir::ItemKind::Existential(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), + _ => None, + }, + inherent_impls: self.encode_inherent_implementations(def_id), + variances: match item.node { + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => Lazy::empty(), + }, + generics: match item.node { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::Ty(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::Existential(..) | + hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), + hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), + _ => None, + }, + predicates: match item.node { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::Ty(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::Existential(..) | + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), + _ => None, + }, - // The only time that `predicates_defined_on` is used (on - // an external item) is for traits, during chalk lowering, - // so only encode it in that case as an efficiency - // hack. (No reason not to expand it in the future if - // necessary.) - predicates_defined_on: match item.node { - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates_defined_on(def_id)), - _ => None, // not *wrong* for other kinds of items, but not needed - }, + // The only time that `predicates_defined_on` is used (on + // an external item) is for traits, during chalk lowering, + // so only encode it in that case as an efficiency + // hack. (No reason not to expand it in the future if + // necessary.) + predicates_defined_on: match item.node { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + Some(self.encode_predicates_defined_on(def_id)) + } + _ => None, // not *wrong* for other kinds of items, but not needed + }, - mir: match item.node { - hir::ItemKind::Static(..) => { - self.encode_optimized_mir(def_id) - } - hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), - hir::ItemKind::Fn(_, header, ..) => { - let generics = tcx.generics_of(def_id); - let needs_inline = - (generics.requires_monomorphization(tcx) || - tcx.codegen_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - if needs_inline - || header.constness == hir::Constness::Const - || always_encode_mir - { + mir: match item.node { + hir::ItemKind::Static(..) => { self.encode_optimized_mir(def_id) - } else { - None } - } - _ => None, + hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), + hir::ItemKind::Fn(_, header, ..) => { + let generics = tcx.generics_of(def_id); + let needs_inline = + (generics.requires_monomorphization(tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && + !self.metadata_output_only(); + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + if needs_inline + || header.constness == hir::Constness::Const + || always_encode_mir + { + self.encode_optimized_mir(def_id) + } else { + None + } + } + _ => None, + }, }, } } /// Serialize the text of exported macros - fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) -> Entry<'tcx> { + fn encode_info_for_macro_def(&mut self, macro_def: &hir::MacroDef) { use syntax::print::pprust; let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); - Entry { - kind: EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), - legacy: macro_def.legacy, - })), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(macro_def.span), - attributes: self.encode_attributes(¯o_def.attrs), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - children: Lazy::empty(), - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - mir: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::MacroDef(self.lazy(MacroDef { + body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), + legacy: macro_def.legacy, + })), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(macro_def.span), + attributes: self.encode_attributes(¯o_def.attrs), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + children: Lazy::empty(), + ty: None, + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + mir: None, + }, } } @@ -1348,44 +1391,32 @@ impl EncodeContext<'_, 'tcx> { def_id: DefId, entry_kind: EntryKind<'tcx>, encode_type: bool, - ) -> Entry<'tcx> { + ) { let tcx = self.tcx; - Entry { - kind: entry_kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind: entry_kind, + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), + stability: None, + deprecation: None, + ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: None, + predicates: None, + predicates_defined_on: None, + + mir: None, + }, } } - fn encode_info_for_ty_param( - &mut self, - (def_id, encode_type): (DefId, bool), - ) -> Entry<'tcx> { - debug!("EncodeContext::encode_info_for_ty_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::TypeParam, encode_type) - } - - fn encode_info_for_const_param( - &mut self, - def_id: DefId, - ) -> Entry<'tcx> { - debug!("EncodeContext::encode_info_for_const_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) - } - - fn encode_info_for_closure(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); let tcx = self.tcx; @@ -1409,27 +1440,31 @@ impl EncodeContext<'_, 'tcx> { _ => bug!("closure that is neither generator nor closure") }; - Entry { - kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: None, - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), + record! { + self.per_def[def_id]: + + entry => Entry { + kind, + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: self.encode_attributes(&tcx.get_attrs(def_id)), + children: Lazy::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: None, + predicates_defined_on: None, + + mir: self.encode_optimized_mir(def_id), + }, } } - fn encode_info_for_anon_const(&mut self, def_id: DefId) -> Entry<'tcx> { + fn encode_info_for_anon_const(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); let tcx = self.tcx; let id = tcx.hir().as_local_hir_id(def_id).unwrap(); @@ -1437,23 +1472,27 @@ impl EncodeContext<'_, 'tcx> { let const_data = self.encode_rendered_const_for_body(body_id); let mir = tcx.mir_const_qualif(def_id).0; - Entry { - kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), + record! { + self.per_def[def_id]: + + entry => Entry { + kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), + visibility: self.lazy(ty::Visibility::Public), + span: self.lazy(tcx.def_span(def_id)), + attributes: Lazy::empty(), + children: Lazy::empty(), + stability: None, + deprecation: None, + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: Lazy::empty(), + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, + + mir: self.encode_optimized_mir(def_id), + }, } } @@ -1608,9 +1647,11 @@ impl EncodeContext<'_, 'tcx> { } } - fn encode_info_for_foreign_item(&mut self, - (def_id, nitem): (DefId, &hir::ForeignItem)) - -> Entry<'tcx> { + fn encode_info_for_foreign_item( + &mut self, + def_id: DefId, + nitem: &hir::ForeignItem, + ) { let tcx = self.tcx; debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); @@ -1629,30 +1670,35 @@ impl EncodeContext<'_, 'tcx> { hir::ForeignItemKind::Type => EntryKind::ForeignType, }; - Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(nitem.span), - attributes: self.encode_attributes(&nitem.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: match nitem.node { - hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, + record! { + self.per_def[def_id]: + + entry => Entry { + kind, + visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), + span: self.lazy(nitem.span), + attributes: self.encode_attributes(&nitem.attrs), + children: Lazy::empty(), + stability: self.encode_stability(def_id), + deprecation: self.encode_deprecation(def_id), + + ty: Some(self.encode_item_type(def_id)), + inherent_impls: Lazy::empty(), + variances: match nitem.node { + hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => Lazy::empty(), + }, + generics: Some(self.encode_generics(def_id)), + predicates: Some(self.encode_predicates(def_id)), + predicates_defined_on: None, - mir: None, + mir: None, + }, } } } +// FIXME(eddyb) make metadata encoding walk over all definitions, instead of HIR. impl Visitor<'tcx> for EncodeContext<'_, 'tcx> { fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { NestedVisitorMap::OnlyBodies(&self.tcx.hir()) @@ -1667,16 +1713,14 @@ impl Visitor<'tcx> for EncodeContext<'_, 'tcx> { match item.node { hir::ItemKind::ExternCrate(_) | hir::ItemKind::Use(..) => {} // ignore these - _ => self.record(def_id, EncodeContext::encode_info_for_item, (def_id, item)), + _ => self.encode_info_for_item(def_id, item), } self.encode_addl_info_for_item(item); } fn visit_foreign_item(&mut self, ni: &'tcx hir::ForeignItem) { intravisit::walk_foreign_item(self, ni); let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id); - self.record(def_id, - EncodeContext::encode_info_for_foreign_item, - (def_id, ni)); + self.encode_info_for_foreign_item(def_id, ni); } fn visit_variant(&mut self, v: &'tcx hir::Variant, @@ -1686,7 +1730,7 @@ impl Visitor<'tcx> for EncodeContext<'_, 'tcx> { if let Some(ref discr) = v.node.disr_expr { let def_id = self.tcx.hir().local_def_id_from_hir_id(discr.hir_id); - self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); + self.encode_info_for_anon_const(def_id); } } fn visit_generics(&mut self, generics: &'tcx hir::Generics) { @@ -1698,8 +1742,7 @@ impl Visitor<'tcx> for EncodeContext<'_, 'tcx> { self.encode_info_for_ty(ty); } fn visit_macro_def(&mut self, macro_def: &'tcx hir::MacroDef) { - let def_id = self.tcx.hir().local_def_id_from_hir_id(macro_def.hir_id); - self.record(def_id, EncodeContext::encode_info_for_macro_def, macro_def); + self.encode_info_for_macro_def(macro_def); } } @@ -1707,10 +1750,10 @@ impl EncodeContext<'_, 'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); for (variant_index, variant) in def.variants.iter_enumerated() { - for (field_index, field) in variant.fields.iter().enumerate() { - self.record(field.did, - EncodeContext::encode_field, - (adt_def_id, variant_index, field_index)); + for (field_index, _field) in variant.fields.iter().enumerate() { + // FIXME(eddyb) `adt_def_id` is leftover from incremental isolation, + // pass `def`, `variant` or `field` instead. + self.encode_field(adt_def_id, variant_index, field_index); } } } @@ -1721,14 +1764,14 @@ impl EncodeContext<'_, 'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => continue, GenericParamKind::Type { ref default, .. } => { - self.record( + self.encode_info_for_generic_param( def_id, - EncodeContext::encode_info_for_ty_param, - (def_id, default.is_some()), + EntryKind::TypeParam, + default.is_some(), ); } GenericParamKind::Const { .. } => { - self.record(def_id, EncodeContext::encode_info_for_const_param, def_id); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); } } } @@ -1738,7 +1781,7 @@ impl EncodeContext<'_, 'tcx> { match ty.node { hir::TyKind::Array(_, ref length) => { let def_id = self.tcx.hir().local_def_id_from_hir_id(length.hir_id); - self.record(def_id, EncodeContext::encode_info_for_anon_const, def_id); + self.encode_info_for_anon_const(def_id); } _ => {} } @@ -1748,7 +1791,7 @@ impl EncodeContext<'_, 'tcx> { match expr.node { hir::ExprKind::Closure(..) => { let def_id = self.tcx.hir().local_def_id_from_hir_id(expr.hir_id); - self.record(def_id, EncodeContext::encode_info_for_closure, def_id); + self.encode_info_for_closure(def_id); } _ => {} } @@ -1779,14 +1822,14 @@ impl EncodeContext<'_, 'tcx> { let def = self.tcx.adt_def(def_id); for (i, variant) in def.variants.iter_enumerated() { - self.record(variant.def_id, - EncodeContext::encode_enum_variant_info, - (def_id, i)); - - if let Some(ctor_def_id) = variant.ctor_def_id { - self.record(ctor_def_id, - EncodeContext::encode_enum_variant_ctor, - (def_id, i)); + // FIXME(eddyb) `def_id` is leftover from incremental isolation, + // pass `def` or `variant` instead. + self.encode_enum_variant_info(def_id, i); + + // FIXME(eddyb) `def_id` is leftover from incremental isolation, + // pass `def`, `variant` or `ctor_def_id` instead. + if let Some(_ctor_def_id) = variant.ctor_def_id { + self.encode_enum_variant_ctor(def_id, i); } } } @@ -1796,9 +1839,7 @@ impl EncodeContext<'_, 'tcx> { // 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_from_hir_id(ctor_hir_id); - self.record(ctor_def_id, - EncodeContext::encode_struct_ctor, - (def_id, ctor_def_id)); + self.encode_struct_ctor(def_id, ctor_def_id); } } hir::ItemKind::Union(..) => { @@ -1806,16 +1847,12 @@ impl EncodeContext<'_, 'tcx> { } hir::ItemKind::Impl(..) => { for &trait_item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(trait_item_def_id, - EncodeContext::encode_info_for_impl_item, - trait_item_def_id); + self.encode_info_for_impl_item(trait_item_def_id); } } hir::ItemKind::Trait(..) => { for &item_def_id in self.tcx.associated_item_def_ids(def_id).iter() { - self.record(item_def_id, - EncodeContext::encode_info_for_trait_item, - item_def_id); + self.encode_info_for_trait_item(item_def_id); } } } @@ -1885,7 +1922,9 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) let mut ecx = EncodeContext { opaque: encoder, tcx, - entries_table: PerDefTable::new(tcx.hir().definitions().def_index_counts_lo_hi()), + per_def: PerDefTables { + entry: PerDefTable::new(tcx.hir().definitions().def_index_counts_lo_hi()), + }, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), predicate_shorthands: Default::default(), diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f5d1393630f9b..641f31ea1b514 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -193,7 +193,7 @@ pub struct CrateRoot<'tcx> { pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), pub interpret_alloc_index: Lazy<[u32]>, - pub entries_table: Lazy!(PerDefTable>), + pub per_def: LazyPerDefTables<'tcx>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -218,6 +218,11 @@ pub struct TraitImpls { pub impls: Lazy<[DefIndex]>, } +#[derive(RustcEncodable, RustcDecodable)] +pub struct LazyPerDefTables<'tcx> { + pub entry: Lazy!(PerDefTable>), +} + #[derive(RustcEncodable, RustcDecodable)] pub struct Entry<'tcx> { pub kind: EntryKind<'tcx>, From 050276a66567efe0aca21597239c461e04855d77 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 13 Apr 2019 23:30:53 +0300 Subject: [PATCH 12/14] rustc_metadata: generalize Table to hold T, not Lazy, elements. --- src/librustc_metadata/decoder.rs | 6 +- src/librustc_metadata/encoder.rs | 10 +-- src/librustc_metadata/schema.rs | 2 +- src/librustc_metadata/table.rs | 111 ++++++++++++++++++++----------- 4 files changed, 80 insertions(+), 49 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index b4062bef4fe28..db6652b4e911e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -2,7 +2,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule}; use crate::schema::*; -use crate::table::PerDefTable; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; @@ -255,7 +255,7 @@ impl<'a, 'tcx, T: Encodable> SpecializedDecoder> for DecodeContext<'a, } impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> - where T: LazyMeta, + where Option: FixedSizeEncoding, { fn specialized_decode(&mut self) -> Result>, Self::Error> { let lo_hi = [ @@ -498,7 +498,7 @@ impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { assert!(!self.is_proc_macro(item_id)); - self.root.per_def.entry.lookup(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.get(self.blob.raw_bytes(), item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0ca6badabe506..058ad40bd2ea9 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,5 +1,5 @@ use crate::schema::*; -use crate::table::PerDefTable; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -59,7 +59,7 @@ pub struct EncodeContext<'a, 'tcx: 'a> { } struct PerDefTables<'tcx> { - entry: PerDefTable>, + entry: PerDefTable>>, } macro_rules! encoder_methods { @@ -117,7 +117,7 @@ impl<'a, 'tcx, T: Encodable> SpecializedEncoder> for EncodeContext<'a, } impl<'a, 'tcx, T> SpecializedEncoder>> for EncodeContext<'a, 'tcx> - where T: LazyMeta, + where Option: FixedSizeEncoding, { fn specialized_encode(&mut self, lazy: &Lazy>) -> Result<(), Self::Error> { self.emit_usize(lazy.meta[0])?; @@ -273,14 +273,14 @@ impl EncodeContentsForLazy<[T]> for I } } -// Shorthand for `$self.$tables.$table.record($key, $self.lazy($value))`, which would +// Shorthand for `$self.$tables.$table.set($key, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record { ($self:ident.$tables:ident[$key:expr]: $($table:ident => $value:expr,)+) => {{ $({ let value = $value; let lazy = $self.lazy(value); - $self.$tables.$table.record($key, lazy); + $self.$tables.$table.set($key, lazy); })+ }} } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 641f31ea1b514..30632b5670ce5 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -220,7 +220,7 @@ pub struct TraitImpls { #[derive(RustcEncodable, RustcDecodable)] pub struct LazyPerDefTables<'tcx> { - pub entry: Lazy!(PerDefTable>), + pub entry: Lazy!(PerDefTable>>), } #[derive(RustcEncodable, RustcDecodable)] diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index 6e461a11919a7..cacf6d088656a 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -7,7 +7,10 @@ use std::num::NonZeroUsize; use log::debug; /// Helper trait, for encoding to, and decoding from, a fixed number of bytes. -pub trait FixedSizeEncoding { +/// Used mainly for Lazy positions and lengths. +/// Unchecked invariant: `Self::default()` should encode as `[0; BYTE_LEN]`, +/// but this has no impact on safety. +pub trait FixedSizeEncoding: Default { const BYTE_LEN: usize; // FIXME(eddyb) convert to and from `[u8; Self::BYTE_LEN]` instead, @@ -37,7 +40,7 @@ macro_rules! fixed_size_encoding_byte_len_and_defaults { b.len() / BYTE_LEN, ) }; - Self::from_bytes(&b[i]) + FixedSizeEncoding::from_bytes(&b[i]) } fn write_to_bytes_at(self, b: &mut [u8], i: usize) { const BYTE_LEN: usize = $byte_len; @@ -68,38 +71,71 @@ impl FixedSizeEncoding for u32 { } } -/// Random-access position table, allowing encoding in an arbitrary order -/// (e.g. while visiting the definitions of a crate), and on-demand decoding -/// of specific indices (e.g. queries for per-definition data). -/// Similar to `Vec>`, but with zero-copy decoding. -// FIXME(eddyb) newtype `[u8]` here, such that `Box>` would be used +// NOTE(eddyb) there could be an impl for `usize`, which would enable a more +// generic `Lazy` impl, but in the general case we might not need / want to +// fit every `usize` in `u32`. +impl FixedSizeEncoding for Option> { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position(NonZeroUsize::new(u32::from_bytes(b) as usize)?)) + } + + fn write_to_bytes(self, b: &mut [u8]) { + let position = self.map_or(0, |lazy| lazy.position.get()); + let position_u32 = position as u32; + assert_eq!(position_u32 as usize, position); + + position_u32.write_to_bytes(b) + } +} + +impl FixedSizeEncoding for Option> { + fixed_size_encoding_byte_len_and_defaults!(u32::BYTE_LEN * 2); + + fn from_bytes(b: &[u8]) -> Self { + Some(Lazy::from_position_and_meta( + >>::from_bytes(b)?.position, + u32::from_bytes(&b[u32::BYTE_LEN..]) as usize, + )) + } + + fn write_to_bytes(self, b: &mut [u8]) { + self.map(|lazy| Lazy::::from_position(lazy.position)) + .write_to_bytes(b); + + let len = self.map_or(0, |lazy| lazy.meta); + let len_u32 = len as u32; + assert_eq!(len_u32 as usize, len); + + len_u32.write_to_bytes(&mut b[u32::BYTE_LEN..]); + } +} + +/// Random-access table, similar to `Vec>`, but without requiring +/// encoding or decoding all the values eagerly and in-order. +// FIXME(eddyb) replace `Vec` with `[_]` here, such that `Box>` would be used // when building it, and `Lazy>` or `&Table` when reading it. // Sadly, that doesn't work for `DefPerTable`, which is `(Table, Table)`, // and so would need two lengths in its metadata, which is not supported yet. -pub struct Table> { +pub struct Table where Option: FixedSizeEncoding { + // FIXME(eddyb) store `[u8; >::BYTE_LEN]` instead of `u8` in `Vec`, + // once that starts being allowed by the compiler (i.e. lazy normalization). bytes: Vec, _marker: PhantomData, } -impl> Table { +impl Table where Option: FixedSizeEncoding { pub fn new(len: usize) -> Self { Table { - bytes: vec![0; len * 4], + // FIXME(eddyb) only allocate and encode as many entries as needed. + bytes: vec![0; len * >::BYTE_LEN], _marker: PhantomData, } } - pub fn record(&mut self, i: usize, entry: Lazy) { - let position = entry.position.get() as u32; - assert_eq!(position as usize, entry.position.get()); - - assert!(u32::read_from_bytes_at(&self.bytes, i) == 0, - "recorded position for index {:?} twice, first at {:?} and now at {:?}", - i, - u32::read_from_bytes_at(&self.bytes, i), - position); - - position.write_to_bytes_at(&mut self.bytes, i) + pub fn set(&mut self, i: usize, value: T) { + Some(value).write_to_bytes_at(&mut self.bytes, i); } pub fn encode(&self, buf: &mut Encoder) -> Lazy { @@ -112,7 +148,7 @@ impl> Table { } } -impl> LazyMeta for Table { +impl LazyMeta for Table where Option: FixedSizeEncoding { type Meta = usize; fn min_size(len: usize) -> usize { @@ -120,29 +156,24 @@ impl> LazyMeta for Table { } } -impl Lazy> { - /// Given the metadata, extract out the offset of a particular index (if any). +impl Lazy> where Option: FixedSizeEncoding { + /// Given the metadata, extract out the value at a particular index (if any). #[inline(never)] - pub fn lookup(&self, bytes: &[u8], i: usize) -> Option> { + pub fn get(&self, bytes: &[u8], i: usize) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - let bytes = &bytes[self.position.get()..][..self.meta]; - let position = u32::read_from_bytes_at(bytes, i); - debug!("Table::lookup: position={:?}", position); - - NonZeroUsize::new(position as usize).map(Lazy::from_position) + >::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i) } } - /// Per-definition table, similar to `Table` but keyed on `DefIndex`. /// Needed because of the two `DefIndexAddressSpace`s a `DefIndex` can be in. -pub struct PerDefTable> { +pub struct PerDefTable where Option: FixedSizeEncoding { lo: Table, hi: Table, } -impl> PerDefTable { +impl PerDefTable where Option: FixedSizeEncoding { pub fn new((max_index_lo, max_index_hi): (usize, usize)) -> Self { PerDefTable { lo: Table::new(max_index_lo), @@ -150,11 +181,11 @@ impl> PerDefTable { } } - pub fn record(&mut self, def_id: DefId, entry: Lazy) { + pub fn set(&mut self, def_id: DefId, value: T) { assert!(def_id.is_local()); let space_index = def_id.index.address_space().index(); let array_index = def_id.index.as_array_index(); - [&mut self.lo, &mut self.hi][space_index].record(array_index, entry); + [&mut self.lo, &mut self.hi][space_index].set(array_index, value); } pub fn encode(&self, buf: &mut Encoder) -> Lazy { @@ -169,7 +200,7 @@ impl> PerDefTable { } } -impl> LazyMeta for PerDefTable { +impl LazyMeta for PerDefTable where Option: FixedSizeEncoding { type Meta = [ as LazyMeta>::Meta; 2]; fn min_size([lo, hi]: Self::Meta) -> usize { @@ -177,7 +208,7 @@ impl> LazyMeta for PerDefTable { } } -impl Lazy> { +impl Lazy> where Option: FixedSizeEncoding { fn table_for_space(&self, space: DefIndexAddressSpace) -> Lazy> { let space_index = space.index(); let offset = space_index.checked_sub(1).map_or(0, |i| self.meta[i]); @@ -187,10 +218,10 @@ impl Lazy> { ) } - /// Given the metadata, extract out the offset of a particular DefIndex (if any). + /// Given the metadata, extract out the value at a particular DefIndex (if any). #[inline(never)] - pub fn lookup(&self, bytes: &[u8], def_index: DefIndex) -> Option> { + pub fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option { self.table_for_space(def_index.address_space()) - .lookup(bytes, def_index.as_array_index()) + .get(bytes, def_index.as_array_index()) } } From 96b6b19ae8deca71d2f50148df081f71406c7e70 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 01:36:08 +0300 Subject: [PATCH 13/14] rustc_metadata: use decoder::Metadata instead of &[u8] for Lazy>::get. --- src/librustc_metadata/decoder.rs | 10 +++++----- src/librustc_metadata/table.rs | 18 ++++++++++++++---- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index db6652b4e911e..ad8416b712828 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -130,8 +130,8 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx> } impl<'a, 'tcx: 'a, T: Encodable + Decodable> Lazy { - pub fn decode>(self, meta: M) -> T { - let mut dcx = meta.decoder(self.position.get()); + pub fn decode>(self, metadata: M) -> T { + let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); T::decode(&mut dcx).unwrap() } @@ -140,9 +140,9 @@ impl<'a, 'tcx: 'a, T: Encodable + Decodable> Lazy { impl<'a, 'tcx: 'a, T: Encodable + Decodable> Lazy<[T]> { pub fn decode>( self, - meta: M, + metadata: M, ) -> impl Iterator + Captures<'tcx> + 'a { - let mut dcx = meta.decoder(self.position.get()); + let mut dcx = metadata.decoder(self.position.get()); dcx.lazy_state = LazyState::NodeStart(self.position); (0..self.meta).map(move |_| T::decode(&mut dcx).unwrap()) } @@ -498,7 +498,7 @@ impl<'a, 'tcx> CrateMetadata { fn maybe_entry(&self, item_id: DefIndex) -> Option>> { assert!(!self.is_proc_macro(item_id)); - self.root.per_def.entry.get(self.blob.raw_bytes(), item_id) + self.root.per_def.entry.get(self, item_id) } fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs index cacf6d088656a..1c5677d023506 100644 --- a/src/librustc_metadata/table.rs +++ b/src/librustc_metadata/table.rs @@ -1,3 +1,4 @@ +use crate::decoder::Metadata; use crate::schema::*; use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; @@ -159,10 +160,15 @@ impl LazyMeta for Table where Option: FixedSizeEncoding { impl Lazy> where Option: FixedSizeEncoding { /// Given the metadata, extract out the value at a particular index (if any). #[inline(never)] - pub fn get(&self, bytes: &[u8], i: usize) -> Option { + pub fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + i: usize, + ) -> Option { debug!("Table::lookup: index={:?} len={:?}", i, self.meta); - >::read_from_bytes_at(&bytes[self.position.get()..][..self.meta], i) + let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; + >::read_from_bytes_at(bytes, i) } } @@ -220,8 +226,12 @@ impl Lazy> where Option: FixedSizeEncoding { /// Given the metadata, extract out the value at a particular DefIndex (if any). #[inline(never)] - pub fn get(&self, bytes: &[u8], def_index: DefIndex) -> Option { + pub fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + def_index: DefIndex, + ) -> Option { self.table_for_space(def_index.address_space()) - .get(bytes, def_index.as_array_index()) + .get(metadata, def_index.as_array_index()) } } From 12f0c3adcff347cfb695ca0615f8280669a04f75 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sun, 14 Apr 2019 04:19:28 +0300 Subject: [PATCH 14/14] rustc_metadata: replace Entry table with one table for each of its fields (AoS -> SoA). --- src/librustc_metadata/decoder.rs | 170 ++-- src/librustc_metadata/encoder.rs | 1249 ++++++++++++++---------------- src/librustc_metadata/schema.rs | 37 +- 3 files changed, 685 insertions(+), 771 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ad8416b712828..b82107fc2a323 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -496,21 +496,21 @@ impl<'a, 'tcx> CrateMetadata { self.proc_macros.is_some() && id != CRATE_DEF_INDEX } - fn maybe_entry(&self, item_id: DefIndex) -> Option>> { + fn maybe_kind(&self, item_id: DefIndex) -> Option> { assert!(!self.is_proc_macro(item_id)); - self.root.per_def.entry.get(self, item_id) + self.root.per_def.kind.get(self, item_id).map(|k| k.decode(self)) } - fn entry(&self, item_id: DefIndex) -> Entry<'tcx> { - match self.maybe_entry(item_id) { - None => { - bug!("entry: id not found: {:?} in crate {:?} with number {}", - item_id, - self.name, - self.cnum) - } - Some(d) => d.decode(self), - } + fn kind(&self, item_id: DefIndex) -> EntryKind<'tcx> { + assert!(!self.is_proc_macro(item_id)); + self.maybe_kind(item_id).unwrap_or_else(|| { + bug!( + "CrateMetadata::kind({:?}): id not found, in crate {:?} with number {}", + item_id, + self.name, + self.cnum, + ) + }) } fn local_def_id(&self, index: DefIndex) -> DefId { @@ -530,7 +530,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_def(&self, index: DefIndex) -> Option { if !self.is_proc_macro(index) { - self.entry(index).kind.to_def(self.local_def_id(index)) + self.kind(index).to_def(self.local_def_id(index)) } else { let kind = self.proc_macros.as_ref().unwrap()[index.to_proc_macro_index()].1.kind(); Some(Def::Macro(self.local_def_id(index), kind)) @@ -540,12 +540,12 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_span(&self, index: DefIndex, sess: &Session) -> Span { match self.is_proc_macro(index) { true => DUMMY_SP, - false => self.entry(index).span.decode((self, sess)), + false => self.root.per_def.span.get(self, index).unwrap().decode((self, sess)), } } pub fn get_trait_def(&self, item_id: DefIndex, sess: &Session) -> ty::TraitDef { - match self.entry(item_id).kind { + match self.kind(item_id) { EntryKind::Trait(data) => { let data = data.decode((self, sess)); ty::TraitDef::new(self.local_def_id(item_id), @@ -570,18 +570,24 @@ impl<'a, 'tcx> CrateMetadata { fn get_variant( &self, tcx: TyCtxt<'a, 'tcx, 'tcx>, - item: &Entry<'_>, + kind: &EntryKind<'_>, index: DefIndex, parent_did: DefId, - adt_kind: ty::AdtKind ) -> ty::VariantDef { - let data = match item.kind { + let data = match kind { EntryKind::Variant(data) | EntryKind::Struct(data, _) | EntryKind::Union(data, _) => data.decode(self), _ => bug!(), }; + let adt_kind = match kind { + EntryKind::Variant(_) => ty::AdtKind::Enum, + EntryKind::Struct(..) => ty::AdtKind::Struct, + EntryKind::Union(..) => ty::AdtKind::Union, + _ => bug!(), + }; + let variant_did = if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { @@ -595,14 +601,12 @@ impl<'a, 'tcx> CrateMetadata { variant_did, ctor_did, data.discr, - item.children.decode(self).map(|index| { - let f = self.entry(index); - ty::FieldDef { + self.root.per_def.children.get(self, index).unwrap_or(Lazy::empty()) + .decode(self).map(|index| ty::FieldDef { did: self.local_def_id(index), ident: Ident::from_interned_str(self.item_name(index)), - vis: f.visibility.decode(self) - } - }).collect(), + vis: self.get_visibility(index), + }).collect(), data.ctor_kind, adt_kind, parent_did, @@ -614,49 +618,49 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> &'tcx ty::AdtDef { - let item = self.entry(item_id); + let kind = self.kind(item_id); let did = self.local_def_id(item_id); - let (kind, repr) = match item.kind { + let (adt_kind, repr) = match kind { EntryKind::Enum(repr) => (ty::AdtKind::Enum, repr), EntryKind::Struct(_, repr) => (ty::AdtKind::Struct, repr), EntryKind::Union(_, repr) => (ty::AdtKind::Union, repr), _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; - let variants = if let ty::AdtKind::Enum = kind { - item.children + let variants = if let ty::AdtKind::Enum = adt_kind { + self.root.per_def.children.get(self, item_id).unwrap_or(Lazy::empty()) .decode(self) .map(|index| { - self.get_variant(tcx, &self.entry(index), index, did, kind) + self.get_variant(tcx, &self.kind(index), index, did) }) .collect() } else { - std::iter::once(self.get_variant(tcx, &item, item_id, did, kind)).collect() + std::iter::once(self.get_variant(tcx, &kind, item_id, did)).collect() }; - tcx.alloc_adt_def(did, kind, variants, repr) + tcx.alloc_adt_def(did, adt_kind, variants, repr) } pub fn get_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::GenericPredicates<'tcx> { - self.entry(item_id).predicates.unwrap().decode((self, tcx)) + self.root.per_def.predicates.get(self, item_id).unwrap().decode((self, tcx)) } pub fn get_predicates_defined_on(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::GenericPredicates<'tcx> { - self.entry(item_id).predicates_defined_on.unwrap().decode((self, tcx)) + self.root.per_def.predicates_defined_on.get(self, item_id).unwrap().decode((self, tcx)) } pub fn get_super_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::GenericPredicates<'tcx> { - let super_predicates = match self.entry(item_id).kind { + let super_predicates = match self.kind(item_id) { EntryKind::Trait(data) => data.decode(self).super_predicates, EntryKind::TraitAlias(data) => data.decode(self).super_predicates, _ => bug!("def-index does not refer to trait or trait alias"), @@ -669,36 +673,36 @@ impl<'a, 'tcx> CrateMetadata { item_id: DefIndex, sess: &Session) -> ty::Generics { - self.entry(item_id).generics.unwrap().decode((self, sess)) + self.root.per_def.generics.get(self, item_id).unwrap().decode((self, sess)) } pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { - self.entry(id).ty.unwrap().decode((self, tcx)) + self.root.per_def.ty.get(self, id).unwrap().decode((self, tcx)) } pub fn get_stability(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { true => self.root.proc_macro_stability.clone(), - false => self.entry(id).stability.map(|stab| stab.decode(self)), + false => self.root.per_def.stability.get(self, id).map(|stab| stab.decode(self)), } } pub fn get_deprecation(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { true => None, - false => self.entry(id).deprecation.map(|depr| depr.decode(self)), + false => self.root.per_def.deprecation.get(self, id).map(|depr| depr.decode(self)), } } pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { match self.is_proc_macro(id) { true => ty::Visibility::Public, - false => self.entry(id).visibility.decode(self), + false => self.root.per_def.visibility.get(self, id).unwrap().decode(self), } } fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Impl(data) => data.decode(self), _ => bug!(), } @@ -784,38 +788,42 @@ impl<'a, 'tcx> CrateMetadata { } // Find the item. - let item = match self.maybe_entry(id) { + let kind = match self.maybe_kind(id) { None => return, - Some(item) => item.decode((self, sess)), + Some(kind) => kind, }; // Iterate over all children. let macros_only = self.dep_kind.lock().macros_only(); - for child_index in item.children.decode((self, sess)) { + let children = self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()); + for child_index in children.decode((self, sess)) { if macros_only { continue } // Get the item. - if let Some(child) = self.maybe_entry(child_index) { - let child = child.decode((self, sess)); - match child.kind { + if let Some(child_kind) = self.maybe_kind(child_index) { + match child_kind { EntryKind::MacroDef(..) => {} _ if macros_only => continue, _ => {} } // Hand off the item to the callback. - match child.kind { + match child_kind { // FIXME(eddyb) Don't encode these in children. EntryKind::ForeignMod => { - for child_index in child.children.decode((self, sess)) { + let child_children = + self.root.per_def.children.get(self, child_index) + .unwrap_or(Lazy::empty()); + for child_index in child_children.decode((self, sess)) { if let Some(def) = self.get_def(child_index) { callback(def::Export { def, ident: Ident::from_interned_str(self.item_name(child_index)), vis: self.get_visibility(child_index), - span: self.entry(child_index).span.decode((self, sess)), + span: self.root.per_def.span.get(self, child_index).unwrap() + .decode((self, sess)), }); } } @@ -827,7 +835,7 @@ impl<'a, 'tcx> CrateMetadata { } let def_key = self.def_key(child_index); - let span = child.span.decode((self, sess)); + let span = self.get_span(child_index, sess); if let (Some(def), Some(name)) = (self.get_def(child_index), def_key.disambiguated_data.data.get_opt_name()) { let ident = Ident::from_interned_str(name); @@ -872,7 +880,7 @@ impl<'a, 'tcx> CrateMetadata { } } - if let EntryKind::Mod(data) = item.kind { + if let EntryKind::Mod(data) = kind { for exp in data.decode((self, sess)).reexports.decode((self, sess)) { match exp.def { Def::Macro(..) => {} @@ -885,7 +893,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn const_is_rvalue_promotable_to_static(&self, id: DefIndex) -> bool { - match self.entry(id).kind { + match self.kind(id) { EntryKind::AssociatedConst(_, data, _) | EntryKind::Const(data, _) => data.ast_promotable, _ => bug!(), @@ -894,7 +902,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn is_item_mir_available(&self, id: DefIndex) -> bool { !self.is_proc_macro(id) && - self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some() + self.root.per_def.mir.get(self, id).is_some() } pub fn maybe_get_optimized_mir(&self, @@ -903,12 +911,12 @@ impl<'a, 'tcx> CrateMetadata { -> Option> { match self.is_proc_macro(id) { true => None, - false => self.entry(id).mir.map(|mir| mir.decode((self, tcx))), + false => self.root.per_def.mir.get(self, id).map(|mir| mir.decode((self, tcx))), } } pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Const(qualif, _) | EntryKind::AssociatedConst(AssociatedContainer::ImplDefault, qualif, _) | EntryKind::AssociatedConst(AssociatedContainer::ImplFinal, qualif, _) => { @@ -919,12 +927,11 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_associated_item(&self, id: DefIndex) -> ty::AssociatedItem { - let item = self.entry(id); let def_key = self.def_key(id); let parent = self.local_def_id(def_key.parent.unwrap()); let name = def_key.disambiguated_data.data.get_opt_name().unwrap(); - let (kind, container, has_self) = match item.kind { + let (kind, container, has_self) = match self.kind(id) { EntryKind::AssociatedConst(container, _, _) => { (ty::AssociatedKind::Const, container, false) } @@ -944,7 +951,7 @@ impl<'a, 'tcx> CrateMetadata { ty::AssociatedItem { ident: Ident::from_interned_str(name), kind, - vis: item.visibility.decode(self), + vis: self.get_visibility(id), defaultness: container.defaultness(), def_id: self.local_def_id(id), container: container.with_def_id(parent), @@ -953,11 +960,12 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_item_variances(&self, id: DefIndex) -> Vec { - self.entry(id).variances.decode(self).collect() + self.root.per_def.variances.get(self, id).unwrap_or(Lazy::empty()) + .decode(self).collect() } pub fn get_ctor_kind(&self, node_id: DefIndex) -> CtorKind { - match self.entry(node_id).kind { + match self.kind(node_id) { EntryKind::Struct(data, _) | EntryKind::Union(data, _) | EntryKind::Variant(data) => data.decode(self).ctor_kind, @@ -966,7 +974,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_ctor_def_id(&self, node_id: DefIndex) -> Option { - match self.entry(node_id).kind { + match self.kind(node_id) { EntryKind::Struct(data, _) => { data.decode(self).ctor.map(|index| self.local_def_id(index)) } @@ -992,26 +1000,20 @@ impl<'a, 'tcx> CrateMetadata { node_id }; - let item = self.entry(item_id); - Lrc::from(self.get_attributes(&item, sess)) - } - - pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { - self.entry(id) - .children - .decode(self) - .map(|index| self.item_name(index).as_symbol()) - .collect() - } - - fn get_attributes(&self, item: &Entry<'tcx>, sess: &Session) -> Vec { - item.attributes + Lrc::from(self.root.per_def.attributes.get(self, item_id).unwrap_or(Lazy::empty()) .decode((self, sess)) .map(|mut attr| { // Need new unique IDs: old thread-local IDs won't map to new threads. attr.id = attr::mk_attr_id(); attr }) + .collect::>()) + } + + pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { + self.root.per_def.children.get(self, id).unwrap_or(Lazy::empty()) + .decode(self) + .map(|index| self.item_name(index).as_symbol()) .collect() } @@ -1031,8 +1033,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec { - self.entry(id) - .inherent_impls + self.root.per_def.inherent_impls.get(self, id).unwrap_or(Lazy::empty()) .decode(self) .map(|index| self.local_def_id(index)) .collect() @@ -1074,7 +1075,7 @@ impl<'a, 'tcx> CrateMetadata { _ => return None, } def_key.parent.and_then(|parent_index| { - match self.entry(parent_index).kind { + match self.kind(parent_index) { EntryKind::Trait(_) | EntryKind::TraitAlias(_) => Some(self.local_def_id(parent_index)), _ => None, @@ -1126,7 +1127,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { - let arg_names = match self.entry(id).kind { + let arg_names = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).arg_names, EntryKind::Method(data) => data.decode(self).fn_data.arg_names, @@ -1148,7 +1149,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_rendered_const(&self, id: DefIndex) -> String { - match self.entry(id).kind { + match self.kind(id) { EntryKind::Const(_, data) | EntryKind::AssociatedConst(_, _, data) => data.decode(self).0, _ => bug!(), @@ -1156,15 +1157,14 @@ impl<'a, 'tcx> CrateMetadata { } pub fn get_macro(&self, id: DefIndex) -> MacroDef { - let entry = self.entry(id); - match entry.kind { + match self.kind(id) { EntryKind::MacroDef(macro_def) => macro_def.decode(self), _ => bug!(), } } crate fn is_const_fn_raw(&self, id: DefIndex) -> bool { - let constness = match self.entry(id).kind { + let constness = match self.kind(id) { EntryKind::Method(data) => data.decode(self).fn_data.constness, EntryKind::Fn(data) => data.decode(self).constness, _ => hir::Constness::NotConst, @@ -1173,7 +1173,7 @@ impl<'a, 'tcx> CrateMetadata { } pub fn is_foreign_item(&self, id: DefIndex) -> bool { - match self.entry(id).kind { + match self.kind(id) { EntryKind::ForeignImmStatic | EntryKind::ForeignMutStatic | EntryKind::ForeignFn(_) => true, @@ -1185,7 +1185,7 @@ impl<'a, 'tcx> CrateMetadata { id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::PolyFnSig<'tcx> { - let sig = match self.entry(id).kind { + let sig = match self.kind(id) { EntryKind::Fn(data) | EntryKind::ForeignFn(data) => data.decode(self).sig, EntryKind::Method(data) => data.decode(self).fn_data.sig, diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 058ad40bd2ea9..1e4fb86f2b39d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -14,7 +14,7 @@ use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, use rustc::middle::lang_items; use rustc::mir::{self, interpret}; use rustc::traits::specialization_graph; -use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; +use rustc::ty::{self, Ty, TyCtxt, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::layout::VariantIdx; @@ -59,7 +59,22 @@ pub struct EncodeContext<'a, 'tcx: 'a> { } struct PerDefTables<'tcx> { - entry: PerDefTable>>, + kind: PerDefTable>>, + visibility: PerDefTable>, + span: PerDefTable>, + attributes: PerDefTable>, + children: PerDefTable>, + stability: PerDefTable>, + deprecation: PerDefTable>, + + ty: PerDefTable>>, + inherent_impls: PerDefTable>, + variances: PerDefTable>, + generics: PerDefTable>, + predicates: PerDefTable>>, + predicates_defined_on: PerDefTable>>, + + mir: PerDefTable>>, } macro_rules! encoder_methods { @@ -467,7 +482,22 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { i = self.position(); let per_def = LazyPerDefTables { - entry: self.per_def.entry.encode(&mut self.opaque), + kind: self.per_def.kind.encode(&mut self.opaque), + visibility: self.per_def.visibility.encode(&mut self.opaque), + span: self.per_def.span.encode(&mut self.opaque), + attributes: self.per_def.attributes.encode(&mut self.opaque), + children: self.per_def.children.encode(&mut self.opaque), + stability: self.per_def.stability.encode(&mut self.opaque), + deprecation: self.per_def.deprecation.encode(&mut self.opaque), + + ty: self.per_def.ty.encode(&mut self.opaque), + inherent_impls: self.per_def.inherent_impls.encode(&mut self.opaque), + variances: self.per_def.variances.encode(&mut self.opaque), + generics: self.per_def.generics.encode(&mut self.opaque), + predicates: self.per_def.predicates.encode(&mut self.opaque), + predicates_defined_on: self.per_def.predicates_defined_on.encode(&mut self.opaque), + + mir: self.per_def.mir.encode(&mut self.opaque), }; let per_def_bytes = self.position() - i; @@ -553,17 +583,22 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } impl EncodeContext<'_, 'tcx> { - fn encode_variances_of(&mut self, def_id: DefId) -> Lazy<[ty::Variance]> { + fn encode_variances_of(&mut self, def_id: DefId) { debug!("EncodeContext::encode_variances_of({:?})", def_id); - let tcx = self.tcx; - self.lazy(&tcx.variances_of(def_id)[..]) + record! { + self.per_def[def_id]: + + variances => &self.tcx.variances_of(def_id)[..], + } } - fn encode_item_type(&mut self, def_id: DefId) -> Lazy> { - let tcx = self.tcx; - let ty = tcx.type_of(def_id); - debug!("EncodeContext::encode_item_type({:?}) => {:?}", def_id, ty); - self.lazy(ty) + fn encode_item_type(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_item_type({:?})", def_id); + record! { + self.per_def[def_id]: + + ty => self.tcx.type_of(def_id), + } } fn encode_enum_variant_info( @@ -590,32 +625,24 @@ impl EncodeContext<'_, 'tcx> { record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(enum_vis, enum_id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: self.lazy(variant.fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - }, + kind => EntryKind::Variant(self.lazy(data)), + visibility => ty::Visibility::from_hir(enum_vis, enum_id, self.tcx), + span => self.tcx.def_span(def_id), + attributes => &self.tcx.get_attrs(def_id)[..], + children => variant.fields.iter().map(|f| { + assert!(f.did.is_local()); + f.did.index + }), + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); } fn encode_enum_variant_ctor( @@ -652,29 +679,19 @@ impl EncodeContext<'_, 'tcx> { record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::Variant(self.lazy(data)), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - }, + kind => EntryKind::Variant(self.lazy(data)), + visibility => ctor_vis, + span => self.tcx.def_span(def_id), } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); } fn encode_info_for_mod( @@ -698,27 +715,16 @@ impl EncodeContext<'_, 'tcx> { record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::Mod(self.lazy(data)), - visibility: self.lazy(ty::Visibility::from_hir(vis, id, tcx)), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(attrs), - children: self.lazy(md.item_ids.iter().map(|item_id| { - tcx.hir().local_def_id_from_hir_id(item_id.id).index - })), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None - }, + kind => EntryKind::Mod(self.lazy(data)), + visibility => ty::Visibility::from_hir(vis, id, self.tcx), + span => self.tcx.def_span(def_id), + attributes => attrs, + children => md.item_ids.iter().map(|item_id| { + tcx.hir().local_def_id_from_hir_id(item_id.id).index + }), } + self.encode_stability(def_id); + self.encode_deprecation(def_id); } fn encode_field( @@ -740,25 +746,16 @@ impl EncodeContext<'_, 'tcx> { record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::Field, - visibility: self.lazy(field.vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&variant_data.fields()[field_index].attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, - }, + kind => EntryKind::Field, + visibility => field.vis, + span => self.tcx.def_span(def_id), + attributes => &variant_data.fields()[field_index].attrs, } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_predicates(def_id); } fn encode_struct_ctor(&mut self, adt_def_id: DefId, def_id: DefId) { @@ -795,52 +792,49 @@ impl EncodeContext<'_, 'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - let repr_options = get_repr_options(&tcx, adt_def_id); - record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::Struct(self.lazy(data), repr_options), - visibility: self.lazy(ctor_vis), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - }, + kind => EntryKind::Struct(self.lazy(data), adt_def.repr), + visibility => ctor_vis, + span => self.tcx.def_span(def_id), + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if variant.ctor_kind == CtorKind::Fn { + self.encode_variances_of(def_id); } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); } - fn encode_generics(&mut self, def_id: DefId) -> Lazy { + fn encode_generics(&mut self, def_id: DefId) { debug!("EncodeContext::encode_generics({:?})", def_id); - let tcx = self.tcx; - self.lazy(tcx.generics_of(def_id)) + record! { + self.per_def[def_id]: + + generics => self.tcx.generics_of(def_id), + } } - fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { + fn encode_predicates(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates({:?})", def_id); - let tcx = self.tcx; - self.lazy(&*tcx.predicates_of(def_id)) + record! { + self.per_def[def_id]: + + predicates => &*self.tcx.predicates_of(def_id), + } } - fn encode_predicates_defined_on(&mut self, def_id: DefId) -> Lazy> { + fn encode_predicates_defined_on(&mut self, def_id: DefId) { debug!("EncodeContext::encode_predicates_defined_on({:?})", def_id); - let tcx = self.tcx; - self.lazy(&*tcx.predicates_defined_on(def_id)) + record! { + self.per_def[def_id]: + + predicates_defined_on => &*self.tcx.predicates_defined_on(def_id), + } } fn encode_info_for_trait_item(&mut self, def_id: DefId) { @@ -860,89 +854,76 @@ impl EncodeContext<'_, 'tcx> { span_bug!(ast_item.span, "traits cannot have final items"), }; - let kind = match trait_item.kind { - ty::AssociatedKind::Const => { - let const_qualif = - if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { - self.const_qualif(0, body) - } else { - ConstQualif { mir: 0, ast_promotable: false } - }; - - let rendered = - hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); - let rendered_const = self.lazy(RenderedConst(rendered)); - - EntryKind::AssociatedConst(container, const_qualif, rendered_const) - } - ty::AssociatedKind::Method => { - let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { - let arg_names = match *m { - hir::TraitMethod::Required(ref names) => { - self.encode_fn_arg_names(names) - } - hir::TraitMethod::Provided(body) => { - self.encode_fn_arg_names_for_body(body) - } - }; - FnData { - constness: hir::Constness::NotConst, - arg_names, - sig: self.lazy(tcx.fn_sig(def_id)), - } - } else { - bug!() - }; - EntryKind::Method(self.lazy(MethodData { - fn_data, - container, - has_self: trait_item.method_has_self_argument, - })) - } - ty::AssociatedKind::Type => EntryKind::AssociatedType(container), - ty::AssociatedKind::Existential => - span_bug!(ast_item.span, "existential type in trait"), - }; - record! { self.per_def[def_id]: - entry => Entry { - kind, - visibility: self.lazy(trait_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match trait_item.kind { - ty::AssociatedKind::Const | - ty::AssociatedKind::Method => { - Some(self.encode_item_type(def_id)) - } - ty::AssociatedKind::Type => { - if trait_item.defaultness.has_value() { - Some(self.encode_item_type(def_id)) + kind => match trait_item.kind { + ty::AssociatedKind::Const => { + let const_qualif = + if let hir::TraitItemKind::Const(_, Some(body)) = ast_item.node { + self.const_qualif(0, body) } else { - None + ConstQualif { mir: 0, ast_promotable: false } + }; + + let rendered = + hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); + let rendered_const = self.lazy(RenderedConst(rendered)); + + EntryKind::AssociatedConst(container, const_qualif, rendered_const) + } + ty::AssociatedKind::Method => { + let fn_data = if let hir::TraitItemKind::Method(_, ref m) = ast_item.node { + let arg_names = match *m { + hir::TraitMethod::Required(ref names) => { + self.encode_fn_arg_names(names) + } + hir::TraitMethod::Provided(body) => { + self.encode_fn_arg_names_for_body(body) + } + }; + FnData { + constness: hir::Constness::NotConst, + arg_names, + sig: self.lazy(tcx.fn_sig(def_id)), } - } - ty::AssociatedKind::Existential => unreachable!(), - }, - inherent_impls: Lazy::empty(), - variances: if trait_item.kind == ty::AssociatedKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), + } else { + bug!() + }; + EntryKind::Method(self.lazy(MethodData { + fn_data, + container, + has_self: trait_item.method_has_self_argument, + })) + } + ty::AssociatedKind::Type => EntryKind::AssociatedType(container), + ty::AssociatedKind::Existential => + span_bug!(ast_item.span, "existential type in trait"), }, + visibility => trait_item.vis, + span => ast_item.span, + attributes => &ast_item.attrs, } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + match trait_item.kind { + ty::AssociatedKind::Const | + ty::AssociatedKind::Method => { + self.encode_item_type(def_id); + } + ty::AssociatedKind::Type => { + if trait_item.defaultness.has_value() { + self.encode_item_type(def_id); + } + } + ty::AssociatedKind::Existential => unreachable!(), + } + if trait_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); } fn metadata_output_only(&self) -> bool { @@ -972,79 +953,67 @@ impl EncodeContext<'_, 'tcx> { span_bug!(ast_item.span, "impl items always have values (currently)"), }; - let kind = match impl_item.kind { - ty::AssociatedKind::Const => { - if let hir::ImplItemKind::Const(_, body_id) = ast_item.node { - let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; - - EntryKind::AssociatedConst(container, - self.const_qualif(mir, body_id), - self.encode_rendered_const_for_body(body_id)) - } else { - bug!() - } - } - ty::AssociatedKind::Method => { - let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { - FnData { - constness: sig.header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), - } - } else { - bug!() - }; - EntryKind::Method(self.lazy(MethodData { - fn_data, - container, - has_self: impl_item.method_has_self_argument, - })) - } - ty::AssociatedKind::Existential => EntryKind::AssociatedExistential(container), - ty::AssociatedKind::Type => EntryKind::AssociatedType(container) - }; - - let mir = - match ast_item.node { - hir::ImplItemKind::Const(..) => true, - hir::ImplItemKind::Method(ref sig, _) => { - let generics = self.tcx.generics_of(def_id); - let needs_inline = (generics.requires_monomorphization(self.tcx) || - tcx.codegen_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let is_const_fn = sig.header.constness == hir::Constness::Const; - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - needs_inline || is_const_fn || always_encode_mir - }, - hir::ImplItemKind::Existential(..) | - hir::ImplItemKind::Type(..) => false, - }; - record! { self.per_def[def_id]: - entry => Entry { - kind, - visibility: self.lazy(impl_item.vis), - span: self.lazy(ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: if impl_item.kind == ty::AssociatedKind::Method { - self.encode_variances_of(def_id) - } else { - Lazy::empty() - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + kind => match impl_item.kind { + ty::AssociatedKind::Const => { + if let hir::ImplItemKind::Const(_, body_id) = ast_item.node { + let mir = self.tcx.at(ast_item.span).mir_const_qualif(def_id).0; + + EntryKind::AssociatedConst(container, + self.const_qualif(mir, body_id), + self.encode_rendered_const_for_body(body_id)) + } else { + bug!() + } + } + ty::AssociatedKind::Method => { + let fn_data = if let hir::ImplItemKind::Method(ref sig, body) = ast_item.node { + FnData { + constness: sig.header.constness, + arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(tcx.fn_sig(def_id)), + } + } else { + bug!() + }; + EntryKind::Method(self.lazy(MethodData { + fn_data, + container, + has_self: impl_item.method_has_self_argument, + })) + } + ty::AssociatedKind::Existential => EntryKind::AssociatedExistential(container), + ty::AssociatedKind::Type => EntryKind::AssociatedType(container) + }, + visibility => impl_item.vis, + span => ast_item.span, + attributes => &ast_item.attrs, + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if impl_item.kind == ty::AssociatedKind::Method { + self.encode_variances_of(def_id); + } + self.encode_generics(def_id); + self.encode_predicates(def_id); + match ast_item.node { + hir::ImplItemKind::Const(..) => self.encode_optimized_mir(def_id), + hir::ImplItemKind::Method(ref sig, _) => { + let generics = self.tcx.generics_of(def_id); + let needs_inline = (generics.requires_monomorphization(self.tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && + !self.metadata_output_only(); + let is_const_fn = sig.header.constness == hir::Constness::Const; + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + if needs_inline || is_const_fn || always_encode_mir { + self.encode_optimized_mir(def_id); + } }, + hir::ImplItemKind::Existential(..) | + hir::ImplItemKind::Type(..) => {} } } @@ -1065,38 +1034,53 @@ impl EncodeContext<'_, 'tcx> { self.lazy(param_names.iter().map(|ident| ident.name)) } - fn encode_optimized_mir(&mut self, def_id: DefId) -> Option>> { + fn encode_optimized_mir(&mut self, def_id: DefId) { debug!("EntryBuilder::encode_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - let mir = self.tcx.optimized_mir(def_id); - Some(self.lazy(mir)) - } else { - None + record! { + self.per_def[def_id]: + + mir => self.tcx.optimized_mir(def_id), + } } } // Encodes the inherent implementations of a structure, enumeration, or trait. - fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { + fn encode_inherent_implementations(&mut self, def_id: DefId) { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); let implementations = self.tcx.inherent_impls(def_id); - if implementations.is_empty() { - Lazy::empty() - } else { - self.lazy(implementations.iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - })) + if !implementations.is_empty() { + record! { + self.per_def[def_id]: + + inherent_impls => implementations.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + }), + } } } - fn encode_stability(&mut self, def_id: DefId) -> Option> { + fn encode_stability(&mut self, def_id: DefId) { debug!("EncodeContext::encode_stability({:?})", def_id); - self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) + if let Some(stab) = self.tcx.lookup_stability(def_id) { + record! { + self.per_def[def_id]: + + stability => stab, + } + } } - fn encode_deprecation(&mut self, def_id: DefId) -> Option> { + fn encode_deprecation(&mut self, def_id: DefId) { debug!("EncodeContext::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(depr)) + if let Some(depr) = self.tcx.lookup_deprecation(def_id) { + record! { + self.per_def[def_id]: + + deprecation => depr, + } + } } fn encode_rendered_const_for_body(&mut self, body_id: hir::BodyId) -> Lazy { @@ -1111,248 +1095,238 @@ impl EncodeContext<'_, 'tcx> { debug!("EncodeContext::encode_info_for_item({:?})", def_id); - let kind = match item.node { - hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, - hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, - hir::ItemKind::Const(_, body_id) => { - let mir = tcx.at(item.span).mir_const_qualif(def_id).0; - EntryKind::Const( - self.const_qualif(mir, body_id), - self.encode_rendered_const_for_body(body_id) - ) - } - hir::ItemKind::Fn(_, header, .., body) => { - let data = FnData { - constness: header.constness, - arg_names: self.encode_fn_arg_names_for_body(body), - sig: self.lazy(tcx.fn_sig(def_id)), - }; + record! { + self.per_def[def_id]: - EntryKind::Fn(self.lazy(data)) - } - hir::ItemKind::Mod(ref m) => { - return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis); - } - hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, - hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, - hir::ItemKind::Ty(..) => EntryKind::Type, - hir::ItemKind::Existential(..) => EntryKind::Existential, - hir::ItemKind::Enum(..) => EntryKind::Enum(get_repr_options(&tcx, def_id)), - hir::ItemKind::Struct(ref struct_def, _) => { - let variant = tcx.adt_def(def_id).non_enum_variant(); - - // Encode def_ids for each field and method - // for methods, write all the stuff get_trait_method - // needs to know - let ctor = struct_def.ctor_hir_id() - .map(|ctor_hir_id| tcx.hir().local_def_id_from_hir_id(ctor_hir_id).index); - - let repr_options = get_repr_options(&tcx, def_id); - - EntryKind::Struct(self.lazy(VariantData { - ctor_kind: variant.ctor_kind, - discr: variant.discr, - ctor, - ctor_sig: None, - }), repr_options) - } - hir::ItemKind::Union(..) => { - let variant = tcx.adt_def(def_id).non_enum_variant(); - let repr_options = get_repr_options(&tcx, def_id); - - EntryKind::Union(self.lazy(VariantData { - ctor_kind: variant.ctor_kind, - discr: variant.discr, - ctor: None, - ctor_sig: None, - }), repr_options) - } - hir::ItemKind::Impl(_, polarity, defaultness, ..) => { - let trait_ref = tcx.impl_trait_ref(def_id); - let parent = if let Some(trait_ref) = trait_ref { - let trait_def = tcx.trait_def(trait_ref.def_id); - trait_def.ancestors(tcx, def_id).nth(1).and_then(|node| { - match node { - specialization_graph::Node::Impl(parent) => Some(parent), - _ => None, - } - }) - } else { - None - }; + kind => match item.node { + hir::ItemKind::Static(_, hir::MutMutable, _) => EntryKind::MutStatic, + hir::ItemKind::Static(_, hir::MutImmutable, _) => EntryKind::ImmStatic, + hir::ItemKind::Const(_, body_id) => { + let mir = self.tcx.at(item.span).mir_const_qualif(def_id).0; + EntryKind::Const( + self.const_qualif(mir, body_id), + self.encode_rendered_const_for_body(body_id) + ) + } + hir::ItemKind::Fn(_, header, .., body) => { + let data = FnData { + constness: header.constness, + arg_names: self.encode_fn_arg_names_for_body(body), + sig: self.lazy(tcx.fn_sig(def_id)), + }; - // if this is an impl of `CoerceUnsized`, create its - // "unsized info", else just store None - let coerce_unsized_info = - trait_ref.and_then(|t| { - if Some(t.def_id) == tcx.lang_items().coerce_unsized_trait() { - Some(tcx.at(item.span).coerce_unsized_info(def_id)) - } else { - None - } + EntryKind::Fn(self.lazy(data)) + } + hir::ItemKind::Mod(ref m) => { + return self.encode_info_for_mod(item.hir_id, m, &item.attrs, &item.vis); + } + hir::ItemKind::ForeignMod(_) => EntryKind::ForeignMod, + hir::ItemKind::GlobalAsm(..) => EntryKind::GlobalAsm, + hir::ItemKind::Ty(..) => EntryKind::Type, + hir::ItemKind::Existential(..) => EntryKind::Existential, + hir::ItemKind::Enum(..) => EntryKind::Enum(self.tcx.adt_def(def_id).repr), + hir::ItemKind::Struct(ref struct_def, _) => { + let adt_def = self.tcx.adt_def(def_id); + let variant = adt_def.non_enum_variant(); + + // Encode def_ids for each field and method + // for methods, write all the stuff get_trait_method + // needs to know + let ctor = struct_def.ctor_hir_id().map(|ctor_hir_id| { + self.tcx.hir().local_def_id_from_hir_id(ctor_hir_id).index }); - let data = ImplData { - polarity, - defaultness, - parent_impl: parent, - coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), - }; + EntryKind::Struct(self.lazy(VariantData { + ctor_kind: variant.ctor_kind, + discr: variant.discr, + ctor, + ctor_sig: None, + }), adt_def.repr) + } + hir::ItemKind::Union(..) => { + let adt_def = self.tcx.adt_def(def_id); + let variant = adt_def.non_enum_variant(); + + EntryKind::Union(self.lazy(VariantData { + ctor_kind: variant.ctor_kind, + discr: variant.discr, + ctor: None, + ctor_sig: None, + }), adt_def.repr) + } + hir::ItemKind::Impl(_, polarity, defaultness, ..) => { + let trait_ref = self.tcx.impl_trait_ref(def_id); + let parent = if let Some(trait_ref) = trait_ref { + let trait_def = self.tcx.trait_def(trait_ref.def_id); + trait_def.ancestors(self.tcx, def_id).nth(1).and_then(|node| { + match node { + specialization_graph::Node::Impl(parent) => Some(parent), + _ => None, + } + }) + } else { + None + }; - EntryKind::Impl(self.lazy(data)) - } - hir::ItemKind::Trait(..) => { - let trait_def = tcx.trait_def(def_id); - let data = TraitData { - unsafety: trait_def.unsafety, - paren_sugar: trait_def.paren_sugar, - has_auto_impl: tcx.trait_is_auto(def_id), - is_marker: trait_def.is_marker, - super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), - }; + // if this is an impl of `CoerceUnsized`, create its + // "unsized info", else just store None + let coerce_unsized_info = + trait_ref.and_then(|t| { + if Some(t.def_id) == self.tcx.lang_items().coerce_unsized_trait() { + Some(self.tcx.at(item.span).coerce_unsized_info(def_id)) + } else { + None + } + }); + + let data = ImplData { + polarity, + defaultness, + parent_impl: parent, + coerce_unsized_info, + trait_ref: trait_ref.map(|trait_ref| self.lazy(trait_ref)), + }; - EntryKind::Trait(self.lazy(data)) - } - hir::ItemKind::TraitAlias(..) => { - let data = TraitAliasData { - super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), - }; + EntryKind::Impl(self.lazy(data)) + } + hir::ItemKind::Trait(..) => { + let trait_def = self.tcx.trait_def(def_id); + let data = TraitData { + unsafety: trait_def.unsafety, + paren_sugar: trait_def.paren_sugar, + has_auto_impl: self.tcx.trait_is_auto(def_id), + is_marker: trait_def.is_marker, + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), + }; - EntryKind::TraitAlias(self.lazy(data)) - } - hir::ItemKind::ExternCrate(_) | - hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), - }; + EntryKind::Trait(self.lazy(data)) + } + hir::ItemKind::TraitAlias(..) => { + let data = TraitAliasData { + super_predicates: self.lazy(&*tcx.super_predicates_of(def_id)), + }; - record! { - self.per_def[def_id]: + EntryKind::TraitAlias(self.lazy(data)) + } + hir::ItemKind::ExternCrate(_) | + hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), + }, + visibility => ty::Visibility::from_hir(&item.vis, item.hir_id, tcx), + span => item.span, + attributes => &item.attrs, + } + // FIXME(eddyb) there should be a nicer way to do this. + match item.node { + hir::ItemKind::ForeignMod(ref fm) => record! { + self.per_def[def_id]: - entry => Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), - span: self.lazy(item.span), - attributes: self.encode_attributes(&item.attrs), - children: match item.node { - hir::ItemKind::ForeignMod(ref fm) => { - self.lazy(fm.items - .iter() - .map(|foreign_item| tcx.hir().local_def_id_from_hir_id( - foreign_item.hir_id).index)) - } - hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.variants.iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - })) - } - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy(def.non_enum_variant().fields.iter().map(|f| { - assert!(f.did.is_local()); - f.did.index - })) - } - hir::ItemKind::Impl(..) | - hir::ItemKind::Trait(..) => { - self.lazy(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - })) - } - _ => Lazy::empty(), - }, - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: match item.node { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) => Some(self.encode_item_type(def_id)), - _ => None, - }, - inherent_impls: self.encode_inherent_implementations(def_id), - variances: match item.node { - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: match item.node { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Trait(..) => Some(self.encode_generics(def_id)), - hir::ItemKind::TraitAlias(..) => Some(self.encode_generics(def_id)), - _ => None, - }, - predicates: match item.node { - hir::ItemKind::Static(..) | - hir::ItemKind::Const(..) | - hir::ItemKind::Fn(..) | - hir::ItemKind::Ty(..) | - hir::ItemKind::Enum(..) | - hir::ItemKind::Struct(..) | - hir::ItemKind::Union(..) | - hir::ItemKind::Impl(..) | - hir::ItemKind::Existential(..) | - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => Some(self.encode_predicates(def_id)), - _ => None, - }, - - // The only time that `predicates_defined_on` is used (on - // an external item) is for traits, during chalk lowering, - // so only encode it in that case as an efficiency - // hack. (No reason not to expand it in the future if - // necessary.) - predicates_defined_on: match item.node { - hir::ItemKind::Trait(..) | - hir::ItemKind::TraitAlias(..) => { - Some(self.encode_predicates_defined_on(def_id)) - } - _ => None, // not *wrong* for other kinds of items, but not needed - }, + children => fm.items + .iter() + .map(|foreign_item| tcx.hir().local_def_id_from_hir_id( + foreign_item.hir_id).index), + }, + hir::ItemKind::Enum(..) => record! { + self.per_def[def_id]: - mir: match item.node { - hir::ItemKind::Static(..) => { - self.encode_optimized_mir(def_id) - } - hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), - hir::ItemKind::Fn(_, header, ..) => { - let generics = tcx.generics_of(def_id); - let needs_inline = - (generics.requires_monomorphization(tcx) || - tcx.codegen_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - if needs_inline - || header.constness == hir::Constness::Const - || always_encode_mir - { - self.encode_optimized_mir(def_id) - } else { - None - } - } - _ => None, - }, + children => 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.per_def[def_id]: + + children => 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.per_def[def_id]: + + children => associated_item_def_ids.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + }), + } + } + _ => {} + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + match item.node { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::Ty(..) | + hir::ItemKind::Existential(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) => self.encode_item_type(def_id), + _ => {} + } + self.encode_inherent_implementations(def_id); + match item.node { + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Fn(..) => self.encode_variances_of(def_id), + _ => {} + } + match item.node { + hir::ItemKind::Static(..) | + hir::ItemKind::Const(..) | + hir::ItemKind::Fn(..) | + hir::ItemKind::Ty(..) | + hir::ItemKind::Enum(..) | + hir::ItemKind::Struct(..) | + hir::ItemKind::Union(..) | + hir::ItemKind::Impl(..) | + hir::ItemKind::Existential(..) | + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_generics(def_id); + self.encode_predicates(def_id); + } + _ => {} + } + // The only time that `predicates_defined_on` is used (on + // an external item) is for traits, during chalk lowering, + // so only encode it in that case as an efficiency + // hack. (No reason not to expand it in the future if + // necessary.) + match item.node { + hir::ItemKind::Trait(..) | + hir::ItemKind::TraitAlias(..) => { + self.encode_predicates_defined_on(def_id); + } + _ => {} // not *wrong* for other kinds of items, but not needed + } + match item.node { + hir::ItemKind::Static(..) => { + self.encode_optimized_mir(def_id); + } + hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), + hir::ItemKind::Fn(_, header, ..) => { + let generics = tcx.generics_of(def_id); + let needs_inline = + (generics.requires_monomorphization(tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && + !self.metadata_output_only(); + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + if needs_inline + || header.constness == hir::Constness::Const + || always_encode_mir + { + self.encode_optimized_mir(def_id); + } + } + _ => {} } } @@ -1363,141 +1337,89 @@ impl EncodeContext<'_, 'tcx> { record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::MacroDef(self.lazy(MacroDef { - body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), - legacy: macro_def.legacy, - })), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(macro_def.span), - attributes: self.encode_attributes(¯o_def.attrs), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - children: Lazy::empty(), - ty: None, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - mir: None, - }, + kind => EntryKind::MacroDef(self.lazy(MacroDef { + body: pprust::tts_to_string(¯o_def.body.trees().collect::>()), + legacy: macro_def.legacy, + })), + visibility => ty::Visibility::Public, + span => macro_def.span, + attributes => ¯o_def.attrs, } + self.encode_stability(def_id); + self.encode_deprecation(def_id); } fn encode_info_for_generic_param( &mut self, def_id: DefId, - entry_kind: EntryKind<'tcx>, + kind: EntryKind<'tcx>, encode_type: bool, ) { - let tcx = self.tcx; record! { self.per_def[def_id]: - entry => Entry { - kind: entry_kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - ty: if encode_type { Some(self.encode_item_type(def_id)) } else { None }, - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - }, + kind => kind, + visibility => ty::Visibility::Public, + span => self.tcx.def_span(def_id), + } + if encode_type { + self.encode_item_type(def_id); } } fn encode_info_for_closure(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_closure({:?})", def_id); - let tcx = self.tcx; let tables = self.tcx.typeck_tables_of(def_id); let hir_id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); - let kind = match tables.node_type(hir_id).sty { - ty::Generator(def_id, ..) => { - let layout = self.tcx.generator_layout(def_id); - let data = GeneratorData { - layout: layout.clone(), - }; - EntryKind::Generator(self.lazy(data)) - } - - ty::Closure(def_id, substs) => { - let sig = substs.closure_sig(def_id, self.tcx); - let data = ClosureData { sig: self.lazy(sig) }; - EntryKind::Closure(self.lazy(data)) - } - - _ => bug!("closure that is neither generator nor closure") - }; record! { self.per_def[def_id]: - entry => Entry { - kind, - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: self.encode_attributes(&tcx.get_attrs(def_id)), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: None, - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), + kind => match tables.node_type(hir_id).sty { + ty::Generator(def_id, ..) => { + let layout = self.tcx.generator_layout(def_id); + let data = GeneratorData { + layout: layout.clone(), + }; + EntryKind::Generator(self.lazy(data)) + } + + ty::Closure(def_id, substs) => { + let sig = substs.closure_sig(def_id, self.tcx); + let data = ClosureData { sig: self.lazy(sig) }; + EntryKind::Closure(self.lazy(data)) + } + + _ => bug!("closure that is neither generator nor closure") }, + visibility => ty::Visibility::Public, + span => self.tcx.def_span(def_id), + attributes => &self.tcx.get_attrs(def_id)[..], } + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_optimized_mir(def_id); } fn encode_info_for_anon_const(&mut self, def_id: DefId) { debug!("EncodeContext::encode_info_for_anon_const({:?})", def_id); - let tcx = self.tcx; - let id = tcx.hir().as_local_hir_id(def_id).unwrap(); - let body_id = tcx.hir().body_owned_by(id); + let id = self.tcx.hir().as_local_hir_id(def_id).unwrap(); + let body_id = self.tcx.hir().body_owned_by(id); let const_data = self.encode_rendered_const_for_body(body_id); - let mir = tcx.mir_const_qualif(def_id).0; + let mir = self.tcx.mir_const_qualif(def_id).0; record! { self.per_def[def_id]: - entry => Entry { - kind: EntryKind::Const(self.const_qualif(mir, body_id), const_data), - visibility: self.lazy(ty::Visibility::Public), - span: self.lazy(tcx.def_span(def_id)), - attributes: Lazy::empty(), - children: Lazy::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: Lazy::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), - }, + kind => EntryKind::Const(self.const_qualif(mir, body_id), const_data), + visibility => ty::Visibility::Public, + span => self.tcx.def_span(def_id), } - } - - fn encode_attributes(&mut self, attrs: &[ast::Attribute]) -> Lazy<[ast::Attribute]> { - self.lazy(attrs) + self.encode_item_type(def_id); + self.encode_generics(def_id); + self.encode_predicates(def_id); + self.encode_optimized_mir(def_id); } fn encode_native_libraries(&mut self) -> Lazy<[NativeLibrary]> { @@ -1656,45 +1578,34 @@ impl EncodeContext<'_, 'tcx> { debug!("EncodeContext::encode_info_for_foreign_item({:?})", def_id); - let kind = match nitem.node { - hir::ForeignItemKind::Fn(_, ref names, _) => { - let data = FnData { - constness: hir::Constness::NotConst, - arg_names: self.encode_fn_arg_names(names), - sig: self.lazy(tcx.fn_sig(def_id)), - }; - EntryKind::ForeignFn(self.lazy(data)) - } - hir::ForeignItemKind::Static(_, true) => EntryKind::ForeignMutStatic, - hir::ForeignItemKind::Static(_, false) => EntryKind::ForeignImmStatic, - hir::ForeignItemKind::Type => EntryKind::ForeignType, - }; - record! { self.per_def[def_id]: - entry => Entry { - kind, - visibility: self.lazy(ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, tcx)), - span: self.lazy(nitem.span), - attributes: self.encode_attributes(&nitem.attrs), - children: Lazy::empty(), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: Lazy::empty(), - variances: match nitem.node { - hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => Lazy::empty(), - }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, + kind => match nitem.node { + hir::ForeignItemKind::Fn(_, ref names, _) => { + let data = FnData { + constness: hir::Constness::NotConst, + arg_names: self.encode_fn_arg_names(names), + sig: self.lazy(tcx.fn_sig(def_id)), + }; + EntryKind::ForeignFn(self.lazy(data)) + } + hir::ForeignItemKind::Static(_, true) => EntryKind::ForeignMutStatic, + hir::ForeignItemKind::Static(_, false) => EntryKind::ForeignImmStatic, + hir::ForeignItemKind::Type => EntryKind::ForeignType, }, + visibility => ty::Visibility::from_hir(&nitem.vis, nitem.hir_id, self.tcx), + span => nitem.span, + attributes => &nitem.attrs, + } + self.encode_stability(def_id); + self.encode_deprecation(def_id); + self.encode_item_type(def_id); + if let hir::ForeignItemKind::Fn(..) = nitem.node { + self.encode_variances_of(def_id); } + self.encode_generics(def_id); + self.encode_predicates(def_id); } } @@ -1919,11 +1830,27 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) // Since encoding metadata is not in a query, and nothing is cached, // there's no need to do dep-graph tracking for any of it. let (root, mut result) = tcx.dep_graph.with_ignore(move || { + let def_counts = tcx.hir().definitions().def_index_counts_lo_hi(); let mut ecx = EncodeContext { opaque: encoder, tcx, per_def: PerDefTables { - entry: PerDefTable::new(tcx.hir().definitions().def_index_counts_lo_hi()), + kind: PerDefTable::new(def_counts), + visibility: PerDefTable::new(def_counts), + span: PerDefTable::new(def_counts), + attributes: PerDefTable::new(def_counts), + children: PerDefTable::new(def_counts), + stability: PerDefTable::new(def_counts), + deprecation: PerDefTable::new(def_counts), + + ty: PerDefTable::new(def_counts), + inherent_impls: PerDefTable::new(def_counts), + variances: PerDefTable::new(def_counts), + generics: PerDefTable::new(def_counts), + predicates: PerDefTable::new(def_counts), + predicates_defined_on: PerDefTable::new(def_counts), + + mir: PerDefTable::new(def_counts), }, lazy_state: LazyState::NoNode, type_shorthands: Default::default(), @@ -1952,11 +1879,3 @@ pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) EncodedMetadata { raw_data: result } } - -pub fn get_repr_options<'a, 'tcx, 'gcx>(tcx: &TyCtxt<'a, 'tcx, 'gcx>, did: DefId) -> ReprOptions { - let ty = tcx.type_of(did); - match ty.sty { - ty::Adt(ref def, _) => return def.repr, - _ => bug!("{} is not an ADT", ty), - } -} diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index 30632b5670ce5..80b2a9ba4d098 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -220,27 +220,22 @@ pub struct TraitImpls { #[derive(RustcEncodable, RustcDecodable)] pub struct LazyPerDefTables<'tcx> { - pub entry: Lazy!(PerDefTable>>), -} - -#[derive(RustcEncodable, RustcDecodable)] -pub struct Entry<'tcx> { - pub kind: EntryKind<'tcx>, - pub visibility: Lazy, - pub span: Lazy, - pub attributes: Lazy<[ast::Attribute]>, - pub children: Lazy<[DefIndex]>, - pub stability: Option>, - pub deprecation: Option>, - - pub ty: Option)>, - pub inherent_impls: Lazy<[DefIndex]>, - pub variances: Lazy<[ty::Variance]>, - pub generics: Option>, - pub predicates: Option)>, - pub predicates_defined_on: Option)>, - - pub mir: Option)>, + pub kind: Lazy!(PerDefTable)>), + pub visibility: Lazy!(PerDefTable>), + pub span: Lazy!(PerDefTable>), + pub attributes: Lazy!(PerDefTable>), + pub children: Lazy!(PerDefTable>), + pub stability: Lazy!(PerDefTable>), + pub deprecation: Lazy!(PerDefTable>), + + pub ty: Lazy!(PerDefTable)>), + pub inherent_impls: Lazy!(PerDefTable>), + pub variances: Lazy!(PerDefTable>), + pub generics: Lazy!(PerDefTable>), + pub predicates: Lazy!(PerDefTable)>), + pub predicates_defined_on: Lazy!(PerDefTable)>), + + pub mir: Lazy!(PerDefTable)>), } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)]