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..ce4fe1572fe92 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`, 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 @@ -73,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/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..b82107fc2a323 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::{FixedSizeEncoding, PerDefTable}; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash, Definitions}; @@ -24,9 +25,10 @@ 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}; +use rustc_serialize::{Decodable, Decoder, Encodable, SpecializedDecoder, opaque}; use syntax::attr; use syntax::ast::{self, Ident}; use syntax::source_map; @@ -127,22 +129,22 @@ 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); +impl<'a, 'tcx: 'a, T: Encodable + Decodable> Lazy { + 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() } } -impl<'a, 'tcx: 'a, T: Decodable> LazySeq { +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); + let mut dcx = metadata.decoder(self.position.get()); 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,18 +157,23 @@ 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) => { + 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(position) + self.lazy_state = LazyState::Previous(NonZeroUsize::new(position + min_size).unwrap()); + Ok(Lazy::from_position_and_meta(NonZeroUsize::new(position).unwrap(), meta)) } } @@ -230,24 +237,34 @@ 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> { - 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: Encodable> 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) + } } } +impl<'a, 'tcx, T> SpecializedDecoder>> for DecodeContext<'a, 'tcx> + where Option: FixedSizeEncoding, +{ + fn specialized_decode(&mut self) -> Result>, Self::Error> { + let lo_hi = [ + self.read_usize()?, + self.read_usize()?, + ]; + self.read_lazy_with_meta(lo_hi) + } +} impl<'a, 'tcx> SpecializedDecoder for DecodeContext<'a, 'tcx> { #[inline] @@ -366,22 +383,26 @@ 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) } pub fn get_rustc_version(&self) -> String { - Lazy::with_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 { + 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) | ((slice[offset + 2] as u32) << 8) | ((slice[offset + 3] as u32) << 0)) as usize; - Lazy::with_position(pos).decode(self) + Lazy::>::from_position( + NonZeroUsize::new(pos).unwrap(), + ).decode(self) } pub fn list_crate_metadata(&self, @@ -445,7 +466,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 { @@ -475,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.index.lookup(self.blob.raw_bytes(), 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 { @@ -509,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)) @@ -519,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), @@ -549,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 { @@ -574,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, @@ -593,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"), @@ -648,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!(), } @@ -763,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)), }); } } @@ -806,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); @@ -851,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(..) => {} @@ -864,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!(), @@ -873,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, @@ -882,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, _) => { @@ -898,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) } @@ -923,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), @@ -932,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, @@ -945,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)) } @@ -971,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() } @@ -1010,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() @@ -1053,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, @@ -1105,11 +1127,11 @@ 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, - _ => LazySeq::empty(), + _ => Lazy::empty(), }; arg_names.decode(self).collect() } @@ -1122,15 +1144,12 @@ 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() } } 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!(), @@ -1138,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, @@ -1155,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, @@ -1167,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 796d2f6a18ba3..1e4fb86f2b39d 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1,7 +1,5 @@ -use crate::index::Index; -use crate::index_builder::{FromId, IndexBuilder, Untracked}; -use crate::isolated_encoder::IsolatedEncoder; use crate::schema::*; +use crate::table::{FixedSizeEncoding, PerDefTable}; use rustc::middle::cstore::{LinkagePreference, NativeLibrary, EncodedMetadata, ForeignModule}; @@ -16,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; @@ -24,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; @@ -46,6 +45,8 @@ pub struct EncodeContext<'a, 'tcx: 'a> { opaque: opaque::Encoder, pub tcx: TyCtxt<'a, 'tcx, 'tcx>, + per_def: PerDefTables<'tcx>, + lazy_state: LazyState, type_shorthands: FxHashMap, usize>, predicate_shorthands: FxHashMap, usize>, @@ -57,6 +58,25 @@ pub struct EncodeContext<'a, 'tcx: 'a> { source_file_cache: Lrc, } +struct PerDefTables<'tcx> { + 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 { ($($name:ident($ty:ty);)*) => { $(fn $name(&mut self, value: $ty) -> Result<(), Self::Error> { @@ -95,19 +115,29 @@ 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.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: 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 { return Ok(()); } - self.emit_lazy_distance(seq.position, LazySeq::::min_size(seq.len)) + self.emit_lazy_distance(*lazy) + } +} + +impl<'a, 'tcx, T> SpecializedEncoder>> for EncodeContext<'a, 'tcx> + where Option: FixedSizeEncoding, +{ + 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) } } @@ -232,96 +262,94 @@ 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() + } +} + +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() } +} - fn emit_lazy_distance(&mut self, - position: usize, - min_size: usize) - -> Result<(), ::Error> { - let min_end = position + min_size; +// 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.set($key, lazy); + })+ + }} +} + +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + fn emit_lazy_distance( + &mut self, + lazy: Lazy, + ) -> Result<(), ::Error> { + 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 } 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.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) } - 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(); - - assert!(pos + LazySeq::::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) - } + fn lazy( + &mut self, + value: impl EncodeContentsForLazy, + ) -> Lazy { + let pos = NonZeroUsize::new(self.position()).unwrap(); - 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_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 + LazySeq::::min_size(len) <= ecx.position()); - LazySeq::with_position_and_length(pos, len) - }) - } + assert!(pos.get() + ::min_size(meta) <= self.position()); - // 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) + Lazy::from_position_and_meta(pos, meta) } - fn encode_info_for_items(&mut self) -> Index { + 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.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 { @@ -329,7 +357,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(); @@ -368,41 +396,33 @@ 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 { + 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 +436,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 @@ -459,13 +477,29 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } n = new_n; } - self.lazy_seq(interpret_alloc_index) + self.lazy(interpret_alloc_index) }; - // Index the items i = self.position(); - let index = items.write_index(&mut self.opaque); - let index_bytes = self.position() - i; + let per_def = LazyPerDefTables { + 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; let attrs = tcx.hir().krate_attrs(); let is_proc_macro = tcx.sess.crate_types.borrow().contains(&CrateType::ProcMacro); @@ -473,7 +507,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(), @@ -516,7 +550,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { impls, exported_symbols, interpret_alloc_index, - index, + per_def, }); let total_bytes = self.position(); @@ -539,7 +573,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!(" per-def table bytes: {}", per_def_bytes); println!(" zero bytes: {}", zero_bytes); println!(" total bytes: {}", total_bytes); } @@ -548,40 +582,35 @@ 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> { - fn encode_variances_of(&mut self, def_id: DefId) -> LazySeq { - debug!("IsolatedEncoder::encode_variances_of({:?})", def_id); - let tcx = self.tcx; - self.lazy_seq_from_slice(&tcx.variances_of(def_id)) +impl EncodeContext<'_, 'tcx> { + fn encode_variances_of(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_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!("IsolatedEncoder::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), + } } - /// 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), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { 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, @@ -593,51 +622,46 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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_seq(variant.fields.iter().map(|f| { + record! { + self.per_def[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 - })), - 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: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - LazySeq::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), + }), + } + 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); } - /// 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), - ) -> Entry<'tcx> { + enum_did: DefId, + index: VariantIdx, + ) { 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, 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 } @@ -652,111 +676,90 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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: LazySeq::empty(), - children: LazySeq::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: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - LazySeq::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]: - 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(&mut self, - FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, - &[ast::Attribute], - &hir::Visibility)>) - -> Entry<'tcx> { + fn encode_info_for_mod( + &mut self, + 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!("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()), - _ => 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)), - attributes: self.encode_attributes(attrs), - children: self.lazy_seq(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(), - generics: None, - predicates: None, - predicates_defined_on: None, + record! { + self.per_def[def_id]: - 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); } - /// 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: 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]; 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); - 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: LazySeq::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(), - 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]: + + 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, def_id): (DefId, DefId)) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_struct_ctor({:?})", def_id); + 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); let variant = adt_def.non_enum_variant(); @@ -766,7 +769,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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 } @@ -789,52 +792,53 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ctor_vis = ty::Visibility::Restricted(DefId::local(CRATE_DEF_INDEX)); } - 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(), - 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: if variant.ctor_kind == CtorKind::Fn { - self.encode_variances_of(def_id) - } else { - LazySeq::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]: - 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 { - debug!("IsolatedEncoder::encode_generics({:?})", def_id); - let tcx = self.tcx; - self.lazy(tcx.generics_of(def_id)) + fn encode_generics(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_generics({:?})", def_id); + record! { + self.per_def[def_id]: + + generics => self.tcx.generics_of(def_id), + } } - fn encode_predicates(&mut self, def_id: DefId) -> Lazy> { - debug!("IsolatedEncoder::encode_predicates({:?})", def_id); - let tcx = self.tcx; - self.lazy(&tcx.predicates_of(def_id)) + fn encode_predicates(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_predicates({:?})", 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> { - debug!("IsolatedEncoder::encode_predicates_defined_on({:?})", def_id); - let tcx = self.tcx; - self.lazy(&tcx.predicates_defined_on(def_id)) + fn encode_predicates_defined_on(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_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) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_trait_item({:?})", def_id); + fn encode_info_for_trait_item(&mut self, def_id: DefId) { + 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(); @@ -850,85 +854,76 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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 } - }; + record! { + self.per_def[def_id]: - let rendered = - hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); - let rendered_const = self.lazy(&RenderedConst(rendered)); + 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 } + }; - 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"), - }; + let rendered = + hir::print::to_string(self.tcx.hir(), |s| s.print_trait_item(ast_item)); + let rendered_const = self.lazy(RenderedConst(rendered)); - Entry { - kind, - visibility: self.lazy(&trait_item.vis), - span: self.lazy(&ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::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)) + EntryKind::AssociatedConst(container, const_qualif, rendered_const) } - ty::AssociatedKind::Type => { - if trait_item.defaultness.has_value() { - Some(self.encode_item_type(def_id)) + 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 { - None - } + bug!() + }; + EntryKind::Method(self.lazy(MethodData { + fn_data, + container, + has_self: trait_item.method_has_self_argument, + })) } - ty::AssociatedKind::Existential => unreachable!(), + ty::AssociatedKind::Type => EntryKind::AssociatedType(container), + ty::AssociatedKind::Existential => + span_bug!(ast_item.span, "existential type in trait"), }, - inherent_impls: LazySeq::empty(), - variances: if trait_item.kind == ty::AssociatedKind::Method { - self.encode_variances_of(def_id) - } else { - LazySeq::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), + 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 { @@ -943,8 +938,8 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { ConstQualif { mir, ast_promotable } } - fn encode_info_for_impl_item(&mut self, def_id: DefId) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_impl_item({:?})", def_id); + fn encode_info_for_impl_item(&mut self, def_id: DefId) { + 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(); @@ -958,83 +953,75 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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; + record! { + self.per_def[def_id]: - 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) - }; + 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; - 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, - }; - - Entry { - kind, - visibility: self.lazy(&impl_item.vis), - span: self.lazy(&ast_item.span), - attributes: self.encode_attributes(&ast_item.attrs), - children: LazySeq::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: if impl_item.kind == ty::AssociatedKind::Method { - self.encode_variances_of(def_id) - } else { - LazySeq::empty() + 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) }, - 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 }, + 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(..) => {} } } 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(), @@ -1043,42 +1030,57 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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>> { + 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) -> LazySeq { - debug!("IsolatedEncoder::encode_inherent_implementations({:?})", def_id); + 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() { - LazySeq::empty() - } else { - self.lazy_seq(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> { - debug!("IsolatedEncoder::encode_stability({:?})", def_id); - self.tcx.lookup_stability(def_id).map(|stab| self.lazy(stab)) + fn encode_stability(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_stability({:?})", def_id); + 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> { - debug!("IsolatedEncoder::encode_deprecation({:?})", def_id); - self.tcx.lookup_deprecation(def_id).map(|depr| self.lazy(&depr)) + fn encode_deprecation(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_deprecation({:?})", def_id); + 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 { @@ -1088,408 +1090,349 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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!("IsolatedEncoder::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)), - }; - - 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))); - } - 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 - }; - - // 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 - } - }); - - let data = ImplData { - polarity, - defaultness, - parent_impl: parent, - coerce_unsized_info, - trait_ref: trait_ref.map(|trait_ref| self.lazy(&trait_ref)), - }; - - 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)), - }; + debug!("EncodeContext::encode_info_for_item({:?})", def_id); - 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), - }; + 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)), + }; - 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_seq(fm.items - .iter() - .map(|foreign_item| tcx.hir().local_def_id_from_hir_id( - foreign_item.hir_id).index)) + EntryKind::Fn(self.lazy(data)) } - hir::ItemKind::Enum(..) => { - let def = self.tcx.adt_def(def_id); - self.lazy_seq(def.variants.iter().map(|v| { - assert!(v.def_id.is_local()); - v.def_id.index - })) + 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 + }); + + EntryKind::Struct(self.lazy(VariantData { + ctor_kind: variant.ctor_kind, + discr: variant.discr, + ctor, + ctor_sig: None, + }), adt_def.repr) } - 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| { - assert!(f.did.is_local()); - f.did.index - })) + 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 + }; + + // 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::Impl(self.lazy(data)) } - hir::ItemKind::Impl(..) | hir::ItemKind::Trait(..) => { - self.lazy_seq(tcx.associated_item_def_ids(def_id).iter().map(|&def_id| { - assert!(def_id.is_local()); - def_id.index - })) + 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::Trait(self.lazy(data)) } - _ => LazySeq::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), - _ => LazySeq::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, + hir::ItemKind::TraitAlias(..) => { + let data = TraitAliasData { + 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), }, - 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, + 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]: + + 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]: - // 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 => 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]: - mir: match item.node { - hir::ItemKind::Static(..) => { - self.encode_optimized_mir(def_id) + children => associated_item_def_ids.iter().map(|&def_id| { + assert!(def_id.is_local()); + def_id.index + }), } - 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 - } + } + _ => {} + } + 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); } - _ => 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 { + record! { + self.per_def[def_id]: + + 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), - attributes: self.encode_attributes(¯o_def.attrs), - stability: self.encode_stability(def_id), - deprecation: self.encode_deprecation(def_id), - - children: LazySeq::empty(), - ty: None, - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), - generics: None, - predicates: None, - predicates_defined_on: None, - mir: None, + 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, - ) -> 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: LazySeq::empty(), - children: LazySeq::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(), - generics: None, - predicates: None, - predicates_defined_on: None, - - mir: None, - } - } + ) { + record! { + self.per_def[def_id]: - fn encode_info_for_ty_param( - &mut self, - (def_id, Untracked(encode_type)): (DefId, Untracked), - ) -> Entry<'tcx> { - debug!("IsolatedEncoder::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!("IsolatedEncoder::encode_info_for_const_param({:?})", def_id); - self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true) + 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) -> Entry<'tcx> { - debug!("IsolatedEncoder::encode_info_for_closure({:?})", def_id); - let tcx = self.tcx; + fn encode_info_for_closure(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_info_for_closure({:?})", def_id); 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)) - } + record! { + self.per_def[def_id]: - _ => bug!("closure that is neither generator nor closure") - }; + 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)) + } - 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: LazySeq::empty(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::empty(), - generics: Some(self.encode_generics(def_id)), - predicates: None, - predicates_defined_on: None, - - mir: self.encode_optimized_mir(def_id), + _ => 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) -> Entry<'tcx> { - debug!("IsolatedEncoder::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); + fn encode_info_for_anon_const(&mut self, def_id: DefId) { + debug!("EncodeContext::encode_info_for_anon_const({:?})", def_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; - - 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(), - stability: None, - deprecation: None, - - ty: Some(self.encode_item_type(def_id)), - inherent_impls: LazySeq::empty(), - variances: LazySeq::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), - } - } + let mir = self.tcx.mir_const_qualif(def_id).0; - 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) + record! { + self.per_def[def_id]: + + kind => EntryKind::Const(self.const_qualif(mir, body_id), const_data), + visibility => ty::Visibility::Public, + span => self.tcx.def_span(def_id), + } + 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, _: ()) -> 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 @@ -1520,20 +1463,20 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, '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)); @@ -1543,14 +1486,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) -> 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 { - debug!("IsolatedEncoder::encode_impls()"); + fn encode_impls(&mut self) -> Lazy<[TraitImpls]> { + debug!("EncodeContext::encode_impls()"); let tcx = self.tcx; let mut visitor = ImplVisitor { tcx, @@ -1575,12 +1518,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(&impls), } }) .collect(); - self.lazy_seq_from_slice(&all_impls[..]) + self.lazy(&all_impls) } // Encodes all symbols exported from this crate into the metadata. @@ -1590,13 +1533,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)]) + -> 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)); - let lazy_seq = self.lazy_seq(exported_symbols + self.lazy(exported_symbols .iter() .filter(|&&(ref exported_symbol, _)| { match *exported_symbol { @@ -1606,18 +1549,13 @@ 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> { + 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, @@ -1627,83 +1565,73 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { } })) } - None => LazySeq::empty(), + None => Lazy::empty(), } } - 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!("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, _) => { - 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 { - 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: LazySeq::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: match nitem.node { - hir::ForeignItemKind::Fn(..) => self.encode_variances_of(def_id), - _ => LazySeq::empty(), + 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, }, - generics: Some(self.encode_generics(def_id)), - predicates: Some(self.encode_predicates(def_id)), - predicates_defined_on: None, - - mir: None, + 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); } } -struct EncodeVisitor<'a, 'b: 'a, 'tcx: 'b> { - index: IndexBuilder<'a, 'b, 'tcx>, -} - -impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { +// 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.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.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, - (def_id, ni)); + let def_id = self.tcx.hir().local_def_id_from_hir_id(ni.hir_id); + self.encode_info_for_foreign_item(def_id, ni); } fn visit_variant(&mut self, v: &'tcx hir::Variant, @@ -1712,32 +1640,31 @@ 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.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); + self.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)))); + 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); } } } @@ -1748,14 +1675,14 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { match param.kind { GenericParamKind::Lifetime { .. } => continue, GenericParamKind::Type { ref default, .. } => { - self.record( + self.encode_info_for_generic_param( def_id, - IsolatedEncoder::encode_info_for_ty_param, - (def_id, Untracked(default.is_some())), + EntryKind::TypeParam, + default.is_some(), ); } GenericParamKind::Const { .. } => { - self.record(def_id, IsolatedEncoder::encode_info_for_const_param, def_id); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); } } } @@ -1765,7 +1692,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.encode_info_for_anon_const(def_id); } _ => {} } @@ -1775,7 +1702,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.encode_info_for_closure(def_id); } _ => {} } @@ -1806,14 +1733,14 @@ 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))); - - if let Some(ctor_def_id) = variant.ctor_def_id { - self.record(ctor_def_id, - IsolatedEncoder::encode_enum_variant_ctor, - (def_id, Untracked(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); } } } @@ -1823,9 +1750,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, '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, - IsolatedEncoder::encode_struct_ctor, - (def_id, ctor_def_id)); + self.encode_struct_ctor(def_id, ctor_def_id); } } hir::ItemKind::Union(..) => { @@ -1833,16 +1758,12 @@ 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, - 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, - IsolatedEncoder::encode_info_for_trait_item, - item_def_id); + self.encode_info_for_trait_item(item_def_id); } } } @@ -1906,10 +1827,31 @@ 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 def_counts = tcx.hir().definitions().def_index_counts_lo_hi(); let mut ecx = EncodeContext { opaque: encoder, tcx, + per_def: PerDefTables { + 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(), predicate_shorthands: Default::default(), @@ -1925,11 +1867,11 @@ 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(); - 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; @@ -1937,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/index.rs b/src/librustc_metadata/index.rs deleted file mode 100644 index 18f30383090cd..0000000000000 --- a/src/librustc_metadata/index.rs +++ /dev/null @@ -1,117 +0,0 @@ -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; - -/// 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 -/// `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] -} - -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]], - } - } - - 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>) { - assert!(entry.position < (u32::MAX as usize)); - let position = entry.position as u32; - let space_index = item.address_space().index(); - let array_index = item.as_array_index(); - - assert!(self.positions[space_index][array_index] == u32::MAX, - "recorded position for item {:?} twice, first at {:?} and now at {:?}", - item, - self.positions[space_index][array_index], - position); - - self.positions[space_index][array_index] = position.to_le(); - } - - 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()])); - // ... then the values in the lower range ... - buf.emit_raw_bytes(words_to_bytes(&self.positions[0][..])); - // ... then the values in the higher range. - buf.emit_raw_bytes(words_to_bytes(&self.positions[1][..])); - LazySeq::with_position_and_length(pos as usize, - self.positions[0].len() + self.positions[1].len() + 1) - } -} - -impl<'tcx> LazySeq { - /// 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 words = &bytes_to_words(&bytes[self.position..])[..self.len]; - - debug!("Index::lookup: index={:?} words.len={:?}", - def_index, - words.len()); - - let positions = match def_index.address_space() { - DefIndexAddressSpace::Low => &words[1..], - 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 .. ] - } - }; - - let array_index = def_index.as_array_index(); - let position = u32::from_le(positions[array_index].get()); - if position == u32::MAX { - debug!("Index::lookup: position=u32::MAX"); - None - } else { - debug!("Index::lookup: position={:?}", position); - Some(Lazy::with_position(position as usize)) - } - } -} - -#[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) } -} diff --git a/src/librustc_metadata/index_builder.rs b/src/librustc_metadata/index_builder.rs deleted file mode 100644 index 8343171b99f4b..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, - 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 { - 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 4078171733fc3..f7f361522799b 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)] @@ -28,16 +29,14 @@ 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; 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 504c7da7d6b9e..80b2a9ba4d098 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -1,9 +1,9 @@ -use crate::index; +use crate::table::PerDefTable; 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; use rustc::mir; @@ -12,17 +12,14 @@ 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; use syntax_pos::{self, Span}; use std::marker::PhantomData; -use std::mem; - -use rustc_data_structures::stable_hasher::{StableHasher, HashStable, - StableHasherResult}; +use std::num::NonZeroUsize; pub fn rustc_version() -> String { format!("rustc {}", @@ -45,6 +42,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. /// @@ -60,49 +84,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 {} - -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`. +/// +/// # Sequences (`Lazy<[T]>`) /// /// Unlike `Lazy>`, the length is encoded next to the /// position, not at the position, which means that the length @@ -113,68 +96,76 @@ impl HashStable 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, - pub position: 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: NonZeroUsize, + 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: NonZeroUsize, meta: T::Meta) -> Lazy { + Lazy { position, + meta, _marker: PhantomData, } } +} - /// Returns the minimum encoded size of `length` values of type `T`. - pub fn min_size(length: usize) -> usize { - length +impl Lazy { + pub fn from_position(position: NonZeroUsize) -> Lazy { + Lazy::from_position_and_meta(position, ()) } } -impl Copy for LazySeq {} -impl Clone for LazySeq { - fn clone(&self) -> Self { - *self +impl Lazy<[T]> { + pub fn empty() -> Lazy<[T]> { + Lazy::from_position_and_meta(NonZeroUsize::new(1).unwrap(), 0) } } -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. +impl Copy for Lazy {} +impl Clone for Lazy { + fn clone(&self) -> Self { + *self } } -/// Encoding / decoding state for `Lazy` and `LazySeq`. +impl serialize::UseSpecializedEncodable for Lazy {} +impl serialize::UseSpecializedDecodable for Lazy {} + +/// 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), + NodeStart(NonZeroUsize), - /// 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(usize), + /// previous `Lazy` would end (see their comments). + 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 { + (PerDefTable<$T:ty>) => {Lazy, [usize; 2]>}; + ([$T:ty]) => {Lazy<[$T], usize>}; + ($T:ty) => {Lazy<$T, ()>}; } #[derive(RustcEncodable, RustcDecodable)] -pub struct CrateRoot { +pub struct CrateRoot<'tcx> { pub name: Symbol, pub triple: TargetTriple, pub extra_filename: String, @@ -189,20 +180,20 @@ pub struct CrateRoot { 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: EncodedExportedSymbols, - pub interpret_alloc_index: LazySeq, + pub impls: Lazy<[TraitImpls]>, + pub exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]), + pub interpret_alloc_index: Lazy<[u32]>, - pub index: LazySeq, + pub per_def: LazyPerDefTables<'tcx>, pub compiler_builtins: bool, pub needs_allocator: bool, @@ -221,72 +212,31 @@ 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); - } + pub impls: Lazy<[DefIndex]>, } #[derive(RustcEncodable, RustcDecodable)] -pub struct Entry<'tcx> { - pub kind: EntryKind<'tcx>, - pub visibility: Lazy, - pub span: Lazy, - pub attributes: LazySeq, - pub children: LazySeq, - pub stability: Option>, - pub deprecation: Option>, - - pub ty: Option>>, - pub inherent_impls: LazySeq, - pub variances: LazySeq, - pub generics: Option>, - pub predicates: Option>>, - pub predicates_defined_on: Option>>, - - pub mir: Option>>, -} +pub struct LazyPerDefTables<'tcx> { + 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>), -impl_stable_hash_for!(struct Entry<'tcx> { - kind, - visibility, - span, - attributes, - children, - stability, - deprecation, - ty, - inherent_impls, - variances, - generics, - predicates, - predicates_defined_on, - mir -}); + 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)] pub enum EntryKind<'tcx> { @@ -304,98 +254,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>), -} - -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); - } - } - } + TraitAlias(Lazy!(TraitAliasData<'tcx>)), } /// Additional data for EntryKind::Const and EntryKind::AssociatedConst @@ -405,46 +279,29 @@ 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>, + pub reexports: Lazy<[def::Export]>, } -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, - pub arg_names: LazySeq, - pub sig: Lazy>, + pub arg_names: Lazy<[ast::Name]>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } -impl_stable_hash_for!(struct FnData<'tcx> { constness, arg_names, sig }); - #[derive(RustcEncodable, RustcDecodable)] pub struct VariantData<'tcx> { pub ctor_kind: CtorKind, @@ -453,42 +310,23 @@ 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)>, } -impl_stable_hash_for!(struct VariantData<'tcx> { - ctor_kind, - discr, - ctor, - ctor_sig -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct TraitData<'tcx> { pub unsafety: hir::Unsafety, pub paren_sugar: bool, pub has_auto_impl: bool, pub is_marker: bool, - pub super_predicates: Lazy>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } -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>, + pub super_predicates: Lazy!(ty::GenericPredicates<'tcx>), } -impl_stable_hash_for!(struct TraitAliasData<'tcx> { - super_predicates -}); - #[derive(RustcEncodable, RustcDecodable)] pub struct ImplData<'tcx> { pub polarity: hir::ImplPolarity, @@ -497,17 +335,9 @@ 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)>, } -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 @@ -520,13 +350,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 { @@ -560,26 +383,17 @@ 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>, + pub sig: Lazy!(ty::PolyFnSig<'tcx>), } -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; pub const TAG_INVALID_SPAN: u8 = 1; - -#[derive(RustcEncodable, RustcDecodable)] -pub struct EncodedExportedSymbols { - pub position: usize, - pub len: usize, -} diff --git a/src/librustc_metadata/table.rs b/src/librustc_metadata/table.rs new file mode 100644 index 0000000000000..1c5677d023506 --- /dev/null +++ b/src/librustc_metadata/table.rs @@ -0,0 +1,237 @@ +use crate::decoder::Metadata; +use crate::schema::*; + +use rustc::hir::def_id::{DefId, DefIndex, DefIndexAddressSpace}; +use rustc_serialize::{Encodable, opaque::Encoder}; +use std::marker::PhantomData; +use std::num::NonZeroUsize; +use log::debug; + +/// Helper trait, for encoding to, and decoding from, a fixed number of bytes. +/// 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, + // 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, + ) + }; + FixedSizeEncoding::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()); + } +} + +// 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 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 where Option: FixedSizeEncoding { + pub fn new(len: usize) -> Self { + Table { + // FIXME(eddyb) only allocate and encode as many entries as needed. + bytes: vec![0; len * >::BYTE_LEN], + _marker: PhantomData, + } + } + + 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 { + let pos = buf.position(); + buf.emit_raw_bytes(&self.bytes); + Lazy::from_position_and_meta( + NonZeroUsize::new(pos as usize).unwrap(), + self.bytes.len(), + ) + } +} + +impl LazyMeta for Table where Option: FixedSizeEncoding { + type Meta = usize; + + fn min_size(len: usize) -> usize { + len + } +} + +impl Lazy> where Option: FixedSizeEncoding { + /// Given the metadata, extract out the value at a particular index (if any). + #[inline(never)] + pub fn get<'a, 'tcx, M: Metadata<'a, 'tcx>>( + &self, + metadata: M, + i: usize, + ) -> Option { + debug!("Table::lookup: index={:?} len={:?}", i, self.meta); + + let bytes = &metadata.raw_bytes()[self.position.get()..][..self.meta]; + >::read_from_bytes_at(bytes, 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 where Option: FixedSizeEncoding { + lo: Table, + hi: Table, +} + +impl PerDefTable where Option: FixedSizeEncoding { + 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 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].set(array_index, value); + } + + 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 where Option: FixedSizeEncoding { + type Meta = [ as LazyMeta>::Meta; 2]; + + fn min_size([lo, hi]: Self::Meta) -> usize { + Table::::min_size(lo) + Table::::min_size(hi) + } +} + +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]); + Lazy::from_position_and_meta( + NonZeroUsize::new(self.position.get() + offset).unwrap(), + self.meta[space_index] + ) + } + + /// Given the metadata, extract out the value at a particular DefIndex (if any). + #[inline(never)] + 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(metadata, def_index.as_array_index()) + } +}