// Decoding metadata from a single crate's metadata
-#![allow(non_camel_case_types)]
-
-use self::Family::*;
-
use astencode::decode_inlined_item;
-use cstore::{self, CrateMetadata};
-use common::*;
-use def_key;
-use encoder::def_to_u64;
-use index;
-use tls_context;
-use tydecode::TyDecoder;
-
-use rustc::hir::svh::Svh;
+use cstore::{self, CrateMetadata, MetadataBlob, NativeLibraryKind};
+use index::Index;
+use schema::*;
+
use rustc::hir::map as hir_map;
-use rustc::hir::map::DefKey;
+use rustc::hir::map::{DefKey, DefPathData};
use rustc::util::nodemap::FnvHashMap;
use rustc::hir;
-use rustc::session::config::PanicStrategy;
+use rustc::hir::intravisit::IdRange;
-use middle::cstore::{InlinedItem, LinkagePreference};
-use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
-use rustc::hir::def::Def;
-use rustc::hir::def_id::{DefId, DefIndex};
-use middle::lang_items;
-use rustc::ty::subst;
-use rustc::ty::{ImplContainer, TraitContainer};
-use rustc::ty::{self, Ty, TyCtxt, TypeFoldable, VariantKind};
+use rustc::middle::cstore::{InlinedItem, LinkagePreference};
+use rustc::hir::def::{self, Def};
+use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
+use rustc::middle::lang_items;
+use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::subst::Substs;
use rustc_const_math::ConstInt;
-use rustc::mir;
-use rustc::mir::visit::MutVisitor;
+use rustc::mir::repr::Mir;
-use std::cell::Cell;
+use std::cell::Ref;
use std::io;
+use std::mem;
use std::rc::Rc;
use std::str;
+use std::u32;
-use rbml::reader;
-use rbml;
-use rustc_serialize::Decodable;
+use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque};
use syntax::attr;
-use syntax::parse::token;
-use syntax::ast;
+use syntax::ast::{self, NodeId};
use syntax::codemap;
-use syntax::print::pprust;
-use syntax::ptr::P;
-use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
+use syntax_pos::{self, Span, BytePos, Pos};
-pub type Cmd<'a> = &'a CrateMetadata;
+pub struct DecodeContext<'a, 'tcx: 'a> {
+ opaque: opaque::Decoder<'a>,
+ tcx: Option<TyCtxt<'a, 'tcx, 'tcx>>,
+ cdata: Option<&'a CrateMetadata>,
+ from_id_range: IdRange,
+ to_id_range: IdRange,
-impl CrateMetadata {
- fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
- self.index.lookup_item(self.data(), item_id).map(|pos| {
- reader::doc_at(self.data(), pos as usize).unwrap().doc
- })
- }
+ // Cache the last used filemap for translating spans as an optimization.
+ last_filemap_index: usize,
- fn lookup_item(&self, item_id: DefIndex) -> rbml::Doc {
- match self.get_item(item_id) {
- None => bug!("lookup_item: id not found: {:?} in crate {:?} with number {}",
- item_id,
- self.name,
- self.cnum),
- Some(d) => d
- }
- }
+ lazy_state: LazyState
}
-pub fn load_index(data: &[u8]) -> index::Index {
- let index = reader::get_doc(rbml::Doc::new(data), tag_index);
- index::Index::from_rbml(index)
-}
+/// Abstract over the various ways one can create metadata decoders.
+pub trait Metadata<'a, 'tcx>: Copy {
+ fn raw_bytes(self) -> &'a [u8];
+ fn cdata(self) -> Option<&'a CrateMetadata> { None }
+ fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { None }
-pub fn crate_rustc_version(data: &[u8]) -> Option<String> {
- let doc = rbml::Doc::new(data);
- reader::maybe_get_doc(doc, tag_rustc_version).map(|s| s.as_str())
+ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
+ let id_range = IdRange {
+ min: NodeId::from_u32(u32::MIN),
+ max: NodeId::from_u32(u32::MAX)
+ };
+ DecodeContext {
+ opaque: opaque::Decoder::new(self.raw_bytes(), pos),
+ cdata: self.cdata(),
+ tcx: self.tcx(),
+ from_id_range: id_range,
+ to_id_range: id_range,
+ last_filemap_index: 0,
+ lazy_state: LazyState::NoNode
+ }
+ }
}
-pub fn load_xrefs(data: &[u8]) -> index::DenseIndex {
- let index = reader::get_doc(rbml::Doc::new(data), tag_xref_index);
- index::DenseIndex::from_buf(index.data, index.start, index.end)
+impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a MetadataBlob {
+ fn raw_bytes(self) -> &'a [u8] {
+ match *self {
+ MetadataBlob::Inflated(ref vec) => &vec[..],
+ MetadataBlob::Archive(ref ar) => ar.as_slice(),
+ }
+ }
}
-// Go through each item in the metadata and create a map from that
-// item's def-key to the item's DefIndex.
-pub fn load_key_map(data: &[u8]) -> FnvHashMap<DefKey, DefIndex> {
- let root_doc = rbml::Doc::new(data);
- let items_doc = reader::get_doc(root_doc, tag_items);
- let items_data_doc = reader::get_doc(items_doc, tag_items_data);
- reader::docs(items_data_doc)
- .filter(|&(tag, _)| tag == tag_items_data_item)
- .map(|(_, item_doc)| {
- // load def-key from item
- let key = item_def_key(item_doc);
-
- // load def-index from item; we only encode the full def-id,
- // so just pull out the index
- let def_id_doc = reader::get_doc(item_doc, tag_def_id);
- let def_id = untranslated_def_id(def_id_doc);
- assert!(def_id.is_local()); // local to the crate we are decoding, that is
-
- (key, def_id.index)
- })
- .collect()
+impl<'a, 'tcx> Metadata<'a, 'tcx> for &'a CrateMetadata {
+ fn raw_bytes(self) -> &'a [u8] { self.blob.raw_bytes() }
+ fn cdata(self) -> Option<&'a CrateMetadata> { Some(self) }
}
-#[derive(Clone, Copy, Debug, PartialEq)]
-enum Family {
- ImmStatic, // c
- MutStatic, // b
- Fn, // f
- StaticMethod, // F
- Method, // h
- Type, // y
- Mod, // m
- ForeignMod, // n
- Enum, // t
- Variant(VariantKind), // V, v, w
- Impl, // i
- DefaultImpl, // d
- Trait, // I
- Struct(VariantKind), // S, s, u
- PublicField, // g
- InheritedField, // N
- Constant, // C
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>) {
+ fn raw_bytes(self) -> &'a [u8] { self.0.raw_bytes() }
+ fn cdata(self) -> Option<&'a CrateMetadata> { Some(self.0) }
+ fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { Some(self.1) }
}
-fn item_family(item: rbml::Doc) -> Family {
- let fam = reader::get_doc(item, tag_items_data_item_family);
- match reader::doc_as_u8(fam) as char {
- 'C' => Constant,
- 'c' => ImmStatic,
- 'b' => MutStatic,
- 'f' => Fn,
- 'F' => StaticMethod,
- 'h' => Method,
- 'y' => Type,
- 'm' => Mod,
- 'n' => ForeignMod,
- 't' => Enum,
- 'V' => Variant(VariantKind::Struct),
- 'v' => Variant(VariantKind::Tuple),
- 'w' => Variant(VariantKind::Unit),
- 'i' => Impl,
- 'd' => DefaultImpl,
- 'I' => Trait,
- 'S' => Struct(VariantKind::Struct),
- 's' => Struct(VariantKind::Tuple),
- 'u' => Struct(VariantKind::Unit),
- 'g' => PublicField,
- 'N' => InheritedField,
- c => bug!("unexpected family char: {}", c)
- }
-}
+// HACK(eddyb) Only used by astencode to customize the from/to IdRange's.
+impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'a, 'tcx, 'tcx>, [IdRange; 2]) {
+ fn raw_bytes(self) -> &'a [u8] { self.0.raw_bytes() }
+ fn cdata(self) -> Option<&'a CrateMetadata> { Some(self.0) }
+ fn tcx(self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> { Some(self.1) }
-fn item_visibility(item: rbml::Doc) -> ty::Visibility {
- match reader::maybe_get_doc(item, tag_items_data_item_visibility) {
- None => ty::Visibility::Public,
- Some(visibility_doc) => {
- match reader::doc_as_u8(visibility_doc) as char {
- 'y' => ty::Visibility::Public,
- 'i' => ty::Visibility::PrivateExternal,
- _ => bug!("unknown visibility character")
- }
- }
+ fn decoder(self, pos: usize) -> DecodeContext<'a, 'tcx> {
+ let mut dcx = (self.0, self.1).decoder(pos);
+ dcx.from_id_range = self.2[0];
+ dcx.to_id_range = self.2[1];
+ dcx
}
}
-fn fn_constness(item: rbml::Doc) -> hir::Constness {
- match reader::maybe_get_doc(item, tag_items_data_item_constness) {
- None => hir::Constness::NotConst,
- Some(constness_doc) => {
- match reader::doc_as_u8(constness_doc) as char {
- 'c' => hir::Constness::Const,
- 'n' => hir::Constness::NotConst,
- _ => bug!("unknown constness character")
- }
- }
+impl<'a, 'tcx: 'a, T: Decodable> Lazy<T> {
+ pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> T {
+ let mut dcx = meta.decoder(self.position);
+ dcx.lazy_state = LazyState::NodeStart(self.position);
+ T::decode(&mut dcx).unwrap()
}
}
-fn item_defaultness(item: rbml::Doc) -> hir::Defaultness {
- match reader::maybe_get_doc(item, tag_items_data_item_defaultness) {
- None => hir::Defaultness::Default, // should occur only for default impls on traits
- Some(defaultness_doc) => {
- match reader::doc_as_u8(defaultness_doc) as char {
- 'd' => hir::Defaultness::Default,
- 'f' => hir::Defaultness::Final,
- _ => bug!("unknown defaultness character")
- }
- }
+impl<'a, 'tcx: 'a, T: Decodable> LazySeq<T> {
+ pub fn decode<M: Metadata<'a, 'tcx>>(self, meta: M) -> impl Iterator<Item=T> + 'a {
+ let mut dcx = meta.decoder(self.position);
+ dcx.lazy_state = LazyState::NodeStart(self.position);
+ (0..self.len).map(move |_| {
+ T::decode(&mut dcx).unwrap()
+ })
}
}
-fn item_sort(item: rbml::Doc) -> Option<char> {
- reader::tagged_docs(item, tag_item_trait_item_sort).nth(0).map(|doc| {
- doc.as_str_slice().as_bytes()[0] as char
- })
-}
+impl<'a, 'tcx> DecodeContext<'a, 'tcx> {
+ pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+ self.tcx.expect("missing TyCtxt in DecodeContext")
+ }
-fn untranslated_def_id(d: rbml::Doc) -> DefId {
- let id = reader::doc_as_u64(d);
- let index = DefIndex::new((id & 0xFFFF_FFFF) as usize);
- DefId { krate: (id >> 32) as u32, index: index }
-}
+ pub fn cdata(&self) -> &'a CrateMetadata {
+ self.cdata.expect("missing CrateMetadata in DecodeContext")
+ }
-fn translated_def_id(cdata: Cmd, d: rbml::Doc) -> DefId {
- let def_id = untranslated_def_id(d);
- translate_def_id(cdata, def_id)
-}
+ fn with_position<F: FnOnce(&mut Self) -> R, R>(&mut self, pos: usize, f: F) -> R {
+ let new_opaque = opaque::Decoder::new(self.opaque.data, pos);
+ let old_opaque = mem::replace(&mut self.opaque, new_opaque);
+ let old_state = mem::replace(&mut self.lazy_state, LazyState::NoNode);
+ let r = f(self);
+ self.opaque = old_opaque;
+ self.lazy_state = old_state;
+ r
+ }
-fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option<DefId> {
- reader::tagged_docs(d, tag_items_data_parent_item).nth(0).map(|did| {
- translated_def_id(cdata, did)
- })
+ fn read_lazy_distance(&mut self, min_size: usize)
+ -> Result<usize, <Self as Decoder>::Error> {
+ let distance = self.read_usize()?;
+ let position = match self.lazy_state {
+ LazyState::NoNode => {
+ bug!("read_lazy_distance: outside of a metadata node")
+ }
+ LazyState::NodeStart(start) => {
+ assert!(distance + min_size <= start);
+ start - distance - min_size
+ }
+ LazyState::Previous(last_min_end) => {
+ last_min_end + distance
+ }
+ };
+ self.lazy_state = LazyState::Previous(position + min_size);
+ Ok(position)
+ }
}
-fn item_require_parent_item(cdata: Cmd, d: rbml::Doc) -> DefId {
- translated_def_id(cdata, reader::get_doc(d, tag_items_data_parent_item))
+macro_rules! decoder_methods {
+ ($($name:ident -> $ty:ty;)*) => {
+ $(fn $name(&mut self) -> Result<$ty, Self::Error> {
+ self.opaque.$name()
+ })*
+ }
}
-fn item_def_id(d: rbml::Doc, cdata: Cmd) -> DefId {
- translated_def_id(cdata, reader::get_doc(d, tag_def_id))
-}
+impl<'doc, 'tcx> Decoder for DecodeContext<'doc, 'tcx> {
+ type Error = <opaque::Decoder<'doc> as Decoder>::Error;
-fn reexports<'a>(d: rbml::Doc<'a>) -> reader::TaggedDocsIterator<'a> {
- reader::tagged_docs(d, tag_items_data_item_reexport)
-}
+ decoder_methods! {
+ read_nil -> ();
-fn variant_disr_val(d: rbml::Doc) -> Option<u64> {
- reader::maybe_get_doc(d, tag_disr_val).and_then(|val_doc| {
- reader::with_doc_data(val_doc, |data| {
- str::from_utf8(data).ok().and_then(|s| s.parse().ok())
- })
- })
-}
+ read_u64 -> u64;
+ read_u32 -> u32;
+ read_u16 -> u16;
+ read_u8 -> u8;
+ read_usize -> usize;
-fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
- let tp = reader::get_doc(doc, tag_items_data_item_type);
- TyDecoder::with_doc(tcx, cdata.cnum, tp,
- &mut |did| translate_def_id(cdata, did))
- .parse_ty()
-}
+ read_i64 -> i64;
+ read_i32 -> i32;
+ read_i16 -> i16;
+ read_i8 -> i8;
+ read_isize -> isize;
-fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
- -> Option<Ty<'tcx>> {
- reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| {
- TyDecoder::with_doc(tcx, cdata.cnum, tp,
- &mut |did| translate_def_id(cdata, did))
- .parse_ty()
- })
-}
+ read_bool -> bool;
+ read_f64 -> f64;
+ read_f32 -> f32;
+ read_char -> char;
+ read_str -> String;
+ }
-pub fn item_type<'a, 'tcx>(_item_id: DefId, item: rbml::Doc,
- tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
- doc_type(item, tcx, cdata)
+ fn error(&mut self, err: &str) -> Self::Error {
+ self.opaque.error(err)
+ }
}
-fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
- -> ty::TraitRef<'tcx> {
- TyDecoder::with_doc(tcx, cdata.cnum, doc,
- &mut |did| translate_def_id(cdata, did))
- .parse_trait_ref()
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
+ Ok(Lazy::with_position(self.read_lazy_distance(Lazy::<T>::min_size())?))
+ }
}
-fn item_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
- -> ty::TraitRef<'tcx> {
- let tp = reader::get_doc(doc, tag_item_trait_ref);
- doc_trait_ref(tp, tcx, cdata)
+impl<'a, 'tcx, T> SpecializedDecoder<LazySeq<T>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<LazySeq<T>, Self::Error> {
+ let len = self.read_usize()?;
+ let position = if len == 0 {
+ 0
+ } else {
+ self.read_lazy_distance(LazySeq::<T>::min_size(len))?
+ };
+ Ok(LazySeq::with_position_and_length(position, len))
+ }
}
-fn item_name(item: rbml::Doc) -> ast::Name {
- maybe_item_name(item).expect("no item in item_name")
-}
+impl<'a, 'tcx> SpecializedDecoder<NodeId> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<NodeId, Self::Error> {
+ let id = u32::decode(self)?;
-fn maybe_item_name(item: rbml::Doc) -> Option<ast::Name> {
- reader::maybe_get_doc(item, tag_paths_data_name).map(|name| {
- let string = name.as_str_slice();
- token::intern(string)
- })
-}
+ // from_id_range should be non-empty
+ assert!(!self.from_id_range.empty());
+ // Make sure that translating the NodeId will actually yield a
+ // meaningful result
+ if !self.from_id_range.contains(NodeId::from_u32(id)) {
+ bug!("NodeId::decode: {} out of DecodeContext range ({:?} -> {:?})",
+ id, self.from_id_range, self.to_id_range);
+ }
-fn family_to_variant_kind<'tcx>(family: Family) -> Option<ty::VariantKind> {
- match family {
- Struct(VariantKind::Struct) | Variant(VariantKind::Struct) =>
- Some(ty::VariantKind::Struct),
- Struct(VariantKind::Tuple) | Variant(VariantKind::Tuple) =>
- Some(ty::VariantKind::Tuple),
- Struct(VariantKind::Unit) | Variant(VariantKind::Unit) =>
- Some(ty::VariantKind::Unit),
- _ => None,
+ // Use wrapping arithmetic because otherwise it introduces control flow.
+ // Maybe we should just have the control flow? -- aatch
+ Ok(NodeId::from_u32(id.wrapping_sub(self.from_id_range.min.as_u32())
+ .wrapping_add(self.to_id_range.min.as_u32())))
}
}
-fn item_to_def_like(cdata: Cmd, item: rbml::Doc, did: DefId) -> DefLike {
- let fam = item_family(item);
- match fam {
- Constant => {
- // Check whether we have an associated const item.
- match item_sort(item) {
- Some('C') | Some('c') => {
- DlDef(Def::AssociatedConst(did))
- }
- _ => {
- // Regular const item.
- DlDef(Def::Const(did))
- }
- }
- }
- ImmStatic => DlDef(Def::Static(did, false)),
- MutStatic => DlDef(Def::Static(did, true)),
- Struct(..) => DlDef(Def::Struct(did)),
- Fn => DlDef(Def::Fn(did)),
- Method | StaticMethod => {
- DlDef(Def::Method(did))
- }
- Type => {
- if item_sort(item) == Some('t') {
- let trait_did = item_require_parent_item(cdata, item);
- DlDef(Def::AssociatedTy(trait_did, did))
- } else {
- DlDef(Def::TyAlias(did))
- }
- }
- Mod => DlDef(Def::Mod(did)),
- ForeignMod => DlDef(Def::ForeignMod(did)),
- Variant(..) => {
- let enum_did = item_require_parent_item(cdata, item);
- DlDef(Def::Variant(enum_did, did))
+impl<'a, 'tcx> SpecializedDecoder<CrateNum> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
+ let cnum = CrateNum::from_u32(u32::decode(self)?);
+ if cnum == LOCAL_CRATE {
+ Ok(self.cdata().cnum)
+ } else {
+ Ok(self.cdata().cnum_map.borrow()[cnum])
}
- Trait => DlDef(Def::Trait(did)),
- Enum => DlDef(Def::Enum(did)),
- Impl | DefaultImpl => DlImpl(did),
- PublicField | InheritedField => DlField,
}
}
-fn parse_unsafety(item_doc: rbml::Doc) -> hir::Unsafety {
- let unsafety_doc = reader::get_doc(item_doc, tag_unsafety);
- if reader::doc_as_u8(unsafety_doc) != 0 {
- hir::Unsafety::Unsafe
- } else {
- hir::Unsafety::Normal
- }
-}
-
-fn parse_paren_sugar(item_doc: rbml::Doc) -> bool {
- let paren_sugar_doc = reader::get_doc(item_doc, tag_paren_sugar);
- reader::doc_as_u8(paren_sugar_doc) != 0
-}
+impl<'a, 'tcx> SpecializedDecoder<Span> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<Span, Self::Error> {
+ let lo = BytePos::decode(self)?;
+ let hi = BytePos::decode(self)?;
-fn parse_polarity(item_doc: rbml::Doc) -> hir::ImplPolarity {
- let polarity_doc = reader::get_doc(item_doc, tag_polarity);
- if reader::doc_as_u8(polarity_doc) != 0 {
- hir::ImplPolarity::Negative
- } else {
- hir::ImplPolarity::Positive
- }
-}
+ let tcx = if let Some(tcx) = self.tcx {
+ tcx
+ } else {
+ return Ok(syntax_pos::mk_sp(lo, hi));
+ };
-fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
- let names_doc = reader::get_doc(item_doc, tag_associated_type_names);
- reader::tagged_docs(names_doc, tag_associated_type_name)
- .map(|name_doc| token::intern(name_doc.as_str_slice()))
- .collect()
-}
+ let (lo, hi) = if lo > hi {
+ // Currently macro expansion sometimes produces invalid Span values
+ // where lo > hi. In order not to crash the compiler when trying to
+ // translate these values, let's transform them into something we
+ // can handle (and which will produce useful debug locations at
+ // least some of the time).
+ // This workaround is only necessary as long as macro expansion is
+ // not fixed. FIXME(#23480)
+ (lo, lo)
+ } else {
+ (lo, hi)
+ };
-pub fn get_trait_def<'a, 'tcx>(cdata: Cmd,
- item_id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx>
-{
- let item_doc = cdata.lookup_item(item_id);
- let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
- let unsafety = parse_unsafety(item_doc);
- let associated_type_names = parse_associated_type_names(item_doc);
- let paren_sugar = parse_paren_sugar(item_doc);
-
- ty::TraitDef::new(unsafety,
- paren_sugar,
- generics,
- item_trait_ref(item_doc, tcx, cdata),
- associated_type_names)
-}
+ let imported_filemaps = self.cdata().imported_filemaps(&tcx.sess.codemap());
+ let filemap = {
+ // Optimize for the case that most spans within a translated item
+ // originate from the same filemap.
+ let last_filemap = &imported_filemaps[self.last_filemap_index];
+
+ if lo >= last_filemap.original_start_pos &&
+ lo <= last_filemap.original_end_pos &&
+ hi >= last_filemap.original_start_pos &&
+ hi <= last_filemap.original_end_pos {
+ last_filemap
+ } else {
+ let mut a = 0;
+ let mut b = imported_filemaps.len();
-pub fn get_adt_def<'a, 'tcx>(cdata: Cmd,
- item_id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::AdtDefMaster<'tcx>
-{
- fn expect_variant_kind(family: Family) -> ty::VariantKind {
- match family_to_variant_kind(family) {
- Some(kind) => kind,
- _ => bug!("unexpected family: {:?}", family),
- }
- }
- fn get_enum_variants<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec<ty::VariantDefData<'tcx, 'tcx>> {
- let mut disr_val = 0;
- reader::tagged_docs(doc, tag_items_data_item_variant).map(|p| {
- let did = translated_def_id(cdata, p);
- let item = cdata.lookup_item(did.index);
+ while b - a > 1 {
+ let m = (a + b) / 2;
+ if imported_filemaps[m].original_start_pos > lo {
+ b = m;
+ } else {
+ a = m;
+ }
+ }
- if let Some(disr) = variant_disr_val(item) {
- disr_val = disr;
- }
- let disr = disr_val;
- disr_val = disr_val.wrapping_add(1);
-
- ty::VariantDefData {
- did: did,
- name: item_name(item),
- fields: get_variant_fields(cdata, item),
- disr_val: ConstInt::Infer(disr),
- kind: expect_variant_kind(item_family(item)),
+ self.last_filemap_index = a;
+ &imported_filemaps[a]
}
- }).collect()
- }
- fn get_variant_fields<'tcx>(cdata: Cmd, doc: rbml::Doc) -> Vec<ty::FieldDefData<'tcx, 'tcx>> {
- let mut index = 0;
- reader::tagged_docs(doc, tag_item_field).map(|f| {
- let ff = item_family(f);
- match ff {
- PublicField | InheritedField => {},
- _ => bug!("expected field, found {:?}", ff)
- };
- ty::FieldDefData::new(item_def_id(f, cdata),
- item_name(f),
- struct_field_family_to_visibility(ff))
- }).chain(reader::tagged_docs(doc, tag_item_unnamed_field).map(|f| {
- let ff = item_family(f);
- let name = token::with_ident_interner(|interner| interner.intern(index.to_string()));
- index += 1;
- ty::FieldDefData::new(item_def_id(f, cdata), name,
- struct_field_family_to_visibility(ff))
- })).collect()
- }
- fn get_struct_variant<'tcx>(cdata: Cmd,
- doc: rbml::Doc,
- did: DefId) -> ty::VariantDefData<'tcx, 'tcx> {
- ty::VariantDefData {
- did: did,
- name: item_name(doc),
- fields: get_variant_fields(cdata, doc),
- disr_val: ConstInt::Infer(0),
- kind: expect_variant_kind(item_family(doc)),
- }
+ };
+
+ let lo = (lo - filemap.original_start_pos) +
+ filemap.translated_filemap.start_pos;
+ let hi = (hi - filemap.original_start_pos) +
+ filemap.translated_filemap.start_pos;
+
+ Ok(syntax_pos::mk_sp(lo, hi))
}
+}
- let doc = cdata.lookup_item(item_id);
- let did = DefId { krate: cdata.cnum, index: item_id };
- let mut ctor_did = None;
- let (kind, variants) = match item_family(doc) {
- Enum => {
- (ty::AdtKind::Enum,
- get_enum_variants(cdata, doc))
- }
- Struct(..) => {
- // Use separate constructor id for unit/tuple structs and reuse did for braced structs.
- ctor_did = reader::maybe_get_doc(doc, tag_items_data_item_struct_ctor).map(|ctor_doc| {
- translated_def_id(cdata, ctor_doc)
- });
- (ty::AdtKind::Struct,
- vec![get_struct_variant(cdata, doc, ctor_did.unwrap_or(did))])
- }
- _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}",
- item_family(doc), did)
- };
-
- let adt = tcx.intern_adt_def(did, kind, variants);
- if let Some(ctor_did) = ctor_did {
- // Make adt definition available through constructor id as well.
- tcx.insert_adt_def(ctor_did, adt);
- }
-
- // this needs to be done *after* the variant is interned,
- // to support recursive structures
- for variant in &adt.variants {
- if variant.kind == ty::VariantKind::Tuple &&
- adt.adt_kind() == ty::AdtKind::Enum {
- // tuple-like enum variant fields aren't real items - get the types
- // from the ctor.
- debug!("evaluating the ctor-type of {:?}",
- variant.name);
- let ctor_ty = get_type(cdata, variant.did.index, tcx).ty;
- debug!("evaluating the ctor-type of {:?}.. {:?}",
- variant.name,
- ctor_ty);
- let field_tys = match ctor_ty.sty {
- ty::TyFnDef(_, _, &ty::BareFnTy { sig: ty::Binder(ty::FnSig {
- ref inputs, ..
- }), ..}) => {
- // tuple-struct constructors don't have escaping regions
- assert!(!inputs.has_escaping_regions());
- inputs
- },
- _ => bug!("tuple-variant ctor is not an ADT")
+// FIXME(#36588) These impls are horribly unsound as they allow
+// the caller to pick any lifetime for 'tcx, including 'static,
+// by using the unspecialized proxies to them.
+
+impl<'a, 'tcx> SpecializedDecoder<Ty<'tcx>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<Ty<'tcx>, Self::Error> {
+ let tcx = self.tcx();
+
+ // Handle shorthands first, if we have an usize > 0x80.
+ if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
+ let pos = self.read_usize()?;
+ assert!(pos >= SHORTHAND_OFFSET);
+ let key = ty::CReaderCacheKey {
+ cnum: self.cdata().cnum,
+ pos: pos - SHORTHAND_OFFSET
};
- for (field, &ty) in variant.fields.iter().zip(field_tys.iter()) {
- field.fulfill_ty(ty);
+ if let Some(ty) = tcx.rcache.borrow().get(&key).cloned() {
+ return Ok(ty);
}
+
+ let ty = self.with_position(key.pos, Ty::decode)?;
+ tcx.rcache.borrow_mut().insert(key, ty);
+ Ok(ty)
} else {
- for field in &variant.fields {
- debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
- let ty = get_type(cdata, field.did.index, tcx).ty;
- field.fulfill_ty(ty);
- debug!("evaluating the type of {:?}::{:?}: {:?}",
- variant.name, field.name, ty);
- }
+ Ok(tcx.mk_ty(ty::TypeVariants::decode(self)?))
}
}
-
- adt
}
-pub fn get_predicates<'a, 'tcx>(cdata: Cmd,
- item_id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::GenericPredicates<'tcx>
-{
- let item_doc = cdata.lookup_item(item_id);
- doc_predicates(item_doc, tcx, cdata, tag_item_generics)
-}
-pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd,
- item_id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::GenericPredicates<'tcx>
-{
- let item_doc = cdata.lookup_item(item_id);
- doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates)
-}
+impl<'a, 'tcx> SpecializedDecoder<ty::GenericPredicates<'tcx>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<ty::GenericPredicates<'tcx>, Self::Error> {
+ Ok(ty::GenericPredicates {
+ parent: Decodable::decode(self)?,
+ predicates: (0..self.read_usize()?).map(|_| {
+ // Handle shorthands first, if we have an usize > 0x80.
+ if self.opaque.data[self.opaque.position()] & 0x80 != 0 {
+ let pos = self.read_usize()?;
+ assert!(pos >= SHORTHAND_OFFSET);
+ let pos = pos - SHORTHAND_OFFSET;
-pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::TypeScheme<'tcx>
-{
- let item_doc = cdata.lookup_item(id);
- let t = item_type(DefId { krate: cdata.cnum, index: id }, item_doc, tcx,
- cdata);
- let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
- ty::TypeScheme {
- generics: generics,
- ty: t
+ self.with_position(pos, ty::Predicate::decode)
+ } else {
+ ty::Predicate::decode(self)
+ }
+ }).collect::<Result<Vec<_>, _>>()?
+ })
}
}
-pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option<attr::Stability> {
- let item = cdata.lookup_item(id);
- reader::maybe_get_doc(item, tag_items_data_item_stability).map(|doc| {
- let mut decoder = reader::Decoder::new(doc);
- Decodable::decode(&mut decoder).unwrap()
- })
+impl<'a, 'tcx> SpecializedDecoder<&'tcx Substs<'tcx>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<&'tcx Substs<'tcx>, Self::Error> {
+ Ok(self.tcx().mk_substs(Decodable::decode(self)?))
+ }
}
-pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option<attr::Deprecation> {
- let item = cdata.lookup_item(id);
- reader::maybe_get_doc(item, tag_items_data_item_deprecation).map(|doc| {
- let mut decoder = reader::Decoder::new(doc);
- Decodable::decode(&mut decoder).unwrap()
- })
+impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Region> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<&'tcx ty::Region, Self::Error> {
+ Ok(self.tcx().mk_region(Decodable::decode(self)?))
+ }
}
-pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility {
- item_visibility(cdata.lookup_item(id))
+impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::Slice<Ty<'tcx>>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<&'tcx ty::Slice<Ty<'tcx>>, Self::Error> {
+ Ok(self.tcx().mk_type_list(Decodable::decode(self)?))
+ }
}
-pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option<DefId> {
- let item = cdata.lookup_item(id);
- reader::maybe_get_doc(item, tag_items_data_parent_impl).map(|doc| {
- translated_def_id(cdata, doc)
- })
+impl<'a, 'tcx> SpecializedDecoder<&'tcx ty::BareFnTy<'tcx>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<&'tcx ty::BareFnTy<'tcx>, Self::Error> {
+ Ok(self.tcx().mk_bare_fn(Decodable::decode(self)?))
+ }
}
-pub fn get_repr_attrs(cdata: Cmd, id: DefIndex) -> Vec<attr::ReprAttr> {
- let item = cdata.lookup_item(id);
- match reader::maybe_get_doc(item, tag_items_data_item_repr).map(|doc| {
- let mut decoder = reader::Decoder::new(doc);
- Decodable::decode(&mut decoder).unwrap()
- }) {
- Some(attrs) => attrs,
- None => Vec::new(),
+impl<'a, 'tcx> SpecializedDecoder<ty::AdtDef<'tcx>> for DecodeContext<'a, 'tcx> {
+ fn specialized_decode(&mut self) -> Result<ty::AdtDef<'tcx>, Self::Error> {
+ let def_id = DefId::decode(self)?;
+ Ok(self.tcx().lookup_adt_def(def_id))
}
}
-pub fn get_impl_polarity<'tcx>(cdata: Cmd,
- id: DefIndex)
- -> Option<hir::ImplPolarity>
-{
- let item_doc = cdata.lookup_item(id);
- let fam = item_family(item_doc);
- match fam {
- Family::Impl => {
- Some(parse_polarity(item_doc))
- }
- _ => None
+impl<'a, 'tcx> MetadataBlob {
+ pub fn is_compatible(&self) -> bool {
+ self.raw_bytes().starts_with(METADATA_HEADER)
}
-}
-pub fn get_custom_coerce_unsized_kind<'tcx>(
- cdata: Cmd,
- id: DefIndex)
- -> Option<ty::adjustment::CustomCoerceUnsized>
-{
- let item_doc = cdata.lookup_item(id);
- reader::maybe_get_doc(item_doc, tag_impl_coerce_unsized_kind).map(|kind_doc| {
- let mut decoder = reader::Decoder::new(kind_doc);
- Decodable::decode(&mut decoder).unwrap()
- })
-}
+ pub fn get_root(&self) -> CrateRoot {
+ 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)
+ }
+
+ /// Go through each item in the metadata and create a map from that
+ /// item's def-key to the item's DefIndex.
+ pub fn load_key_map(&self, index: LazySeq<Index>) -> FnvHashMap<DefKey, DefIndex> {
+ index.iter_enumerated(self.raw_bytes()).map(|(index, item)| {
+ (item.decode(self).def_key.decode(self), index)
+ }).collect()
+ }
-pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd,
- id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Option<ty::TraitRef<'tcx>>
-{
- let item_doc = cdata.lookup_item(id);
- let fam = item_family(item_doc);
- match fam {
- Family::Impl | Family::DefaultImpl => {
- reader::maybe_get_doc(item_doc, tag_item_trait_ref).map(|tp| {
- doc_trait_ref(tp, tcx, cdata)
- })
+ pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> {
+ write!(out, "=External Dependencies=\n")?;
+ let root = self.get_root();
+ for (i, dep) in root.crate_deps.decode(self).enumerate() {
+ write!(out, "{} {}-{}\n", i + 1, dep.name, dep.hash)?;
}
- _ => None
+ write!(out, "\n")?;
+ Ok(())
}
}
-/// Iterates over the language items in the given crate.
-pub fn each_lang_item<F>(cdata: Cmd, mut f: F) -> bool where
- F: FnMut(DefIndex, usize) -> bool,
-{
- let root = rbml::Doc::new(cdata.data());
- let lang_items = reader::get_doc(root, tag_lang_items);
- reader::tagged_docs(lang_items, tag_lang_items_item).all(|item_doc| {
- let id_doc = reader::get_doc(item_doc, tag_lang_items_item_id);
- let id = reader::doc_as_u32(id_doc) as usize;
- let index_doc = reader::get_doc(item_doc, tag_lang_items_item_index);
- let index = DefIndex::from_u32(reader::doc_as_u32(index_doc));
-
- f(index, id)
- })
+impl<'tcx> EntryKind<'tcx> {
+ fn to_def(&self, did: DefId) -> Option<Def> {
+ Some(match *self {
+ EntryKind::Const => Def::Const(did),
+ EntryKind::AssociatedConst(_) => Def::AssociatedConst(did),
+ EntryKind::ImmStatic |
+ EntryKind::ForeignImmStatic => Def::Static(did, false),
+ EntryKind::MutStatic |
+ EntryKind::ForeignMutStatic => Def::Static(did, true),
+ EntryKind::Struct(_) => Def::Struct(did),
+ EntryKind::Union(_) => Def::Union(did),
+ EntryKind::Fn(_) |
+ EntryKind::ForeignFn(_) => Def::Fn(did),
+ EntryKind::Method(_) => Def::Method(did),
+ EntryKind::Type => Def::TyAlias(did),
+ EntryKind::AssociatedType(_) => Def::AssociatedTy(did),
+ EntryKind::Mod(_) => Def::Mod(did),
+ EntryKind::Variant(_) => Def::Variant(did),
+ EntryKind::Trait(_) => Def::Trait(did),
+ EntryKind::Enum => Def::Enum(did),
+
+ EntryKind::ForeignMod |
+ EntryKind::Impl(_) |
+ EntryKind::DefaultImpl(_) |
+ EntryKind::Field |
+ EntryKind::Closure (_) => {
+ return None
+ }
+ })
+ }
}
-fn each_child_of_item_or_crate<F, G>(cdata: Cmd,
- item_doc: rbml::Doc,
- mut get_crate_data: G,
- mut callback: F) where
- F: FnMut(DefLike, ast::Name, ty::Visibility),
- G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
-{
- // Iterate over all children.
- for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) {
- let child_def_id = translated_def_id(cdata, child_info_doc);
-
- // This item may be in yet another crate if it was the child of a
- // reexport.
- let crate_data = if child_def_id.krate == cdata.cnum {
- None
- } else {
- Some(get_crate_data(child_def_id.krate))
- };
- let crate_data = match crate_data {
- Some(ref cdata) => &**cdata,
- None => cdata
- };
+impl<'a, 'tcx> CrateMetadata {
+ fn maybe_entry(&self, item_id: DefIndex) -> Option<Lazy<Entry<'tcx>>> {
+ self.root.index.lookup(self.blob.raw_bytes(), item_id)
+ }
- // Get the item.
- if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) {
- // Hand off the item to the callback.
- let child_name = item_name(child_item_doc);
- let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
- let visibility = item_visibility(child_item_doc);
- callback(def_like, child_name, visibility);
+ 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)
}
}
- for reexport_doc in reexports(item_doc) {
- let def_id_doc = reader::get_doc(reexport_doc,
- tag_items_data_item_reexport_def_id);
- let child_def_id = translated_def_id(cdata, def_id_doc);
-
- let name_doc = reader::get_doc(reexport_doc,
- tag_items_data_item_reexport_name);
- let name = name_doc.as_str_slice();
-
- // This reexport may be in yet another crate.
- let crate_data = if child_def_id.krate == cdata.cnum {
- None
- } else {
- Some(get_crate_data(child_def_id.krate))
- };
- let crate_data = match crate_data {
- Some(ref cdata) => &**cdata,
- None => cdata
- };
-
- // Get the item.
- if let Some(child_item_doc) = crate_data.get_item(child_def_id.index) {
- // Hand off the item to the callback.
- let def_like = item_to_def_like(crate_data, child_item_doc, child_def_id);
- // These items have a public visibility because they're part of
- // a public re-export.
- callback(def_like, token::intern(name), ty::Visibility::Public);
+ fn local_def_id(&self, index: DefIndex) -> DefId {
+ DefId {
+ krate: self.cnum,
+ index: index
}
}
-}
-
-/// Iterates over each child of the given item.
-pub fn each_child_of_item<F, G>(cdata: Cmd, id: DefIndex, get_crate_data: G, callback: F)
- where F: FnMut(DefLike, ast::Name, ty::Visibility),
- G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
-{
- // Find the item.
- let item_doc = match cdata.get_item(id) {
- None => return,
- Some(item_doc) => item_doc,
- };
-
- each_child_of_item_or_crate(cdata, item_doc, get_crate_data, callback)
-}
-
-/// Iterates over all the top-level crate items.
-pub fn each_top_level_item_of_crate<F, G>(cdata: Cmd, get_crate_data: G, callback: F)
- where F: FnMut(DefLike, ast::Name, ty::Visibility),
- G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
-{
- let root_doc = rbml::Doc::new(cdata.data());
- let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
- let crate_items_doc = reader::get_doc(misc_info_doc,
- tag_misc_info_crate_items);
-
- each_child_of_item_or_crate(cdata,
- crate_items_doc,
- get_crate_data,
- callback)
-}
-
-pub fn get_item_name(cdata: Cmd, id: DefIndex) -> ast::Name {
- item_name(cdata.lookup_item(id))
-}
-
-pub fn maybe_get_item_name(cdata: Cmd, id: DefIndex) -> Option<ast::Name> {
- maybe_item_name(cdata.lookup_item(id))
-}
-pub enum FoundAst<'ast> {
- Found(&'ast InlinedItem),
- FoundParent(DefId, &'ast hir::Item),
- NotFound,
-}
-
-pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
- -> FoundAst<'tcx> {
- debug!("Looking up item: {:?}", id);
- let item_doc = cdata.lookup_item(id);
- let item_did = item_def_id(item_doc, cdata);
- let parent_def_id = DefId {
- krate: cdata.cnum,
- index: def_key(cdata, id).parent.unwrap()
- };
- let mut parent_def_path = def_path(cdata, id);
- parent_def_path.data.pop();
- if let Some(ast_doc) = reader::maybe_get_doc(item_doc, tag_ast as usize) {
- let ii = decode_inlined_item(cdata,
- tcx,
- parent_def_path,
- parent_def_id,
- ast_doc,
- item_did);
- return FoundAst::Found(ii);
- } else if let Some(parent_did) = item_parent_item(cdata, item_doc) {
- // Remove the last element from the paths, since we are now
- // trying to inline the parent.
- let grandparent_def_id = DefId {
- krate: cdata.cnum,
- index: def_key(cdata, parent_def_id.index).parent.unwrap()
- };
- let mut grandparent_def_path = parent_def_path;
- grandparent_def_path.data.pop();
- let parent_doc = cdata.lookup_item(parent_did.index);
- if let Some(ast_doc) = reader::maybe_get_doc(parent_doc, tag_ast as usize) {
- let ii = decode_inlined_item(cdata,
- tcx,
- grandparent_def_path,
- grandparent_def_id,
- ast_doc,
- parent_did);
- if let &InlinedItem::Item(_, ref i) = ii {
- return FoundAst::FoundParent(parent_did, i);
- }
- }
+ fn item_name(&self, item: &Entry<'tcx>) -> ast::Name {
+ item.def_key.decode(self).disambiguated_data.data.get_opt_name()
+ .expect("no name in item_name")
}
- FoundAst::NotFound
-}
-pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool {
- if let Some(item_doc) = cdata.get_item(id) {
- return reader::maybe_get_doc(item_doc, tag_mir as usize).is_some();
+ pub fn get_def(&self, index: DefIndex) -> Option<Def> {
+ self.entry(index).kind.to_def(self.local_def_id(index))
}
- false
-}
+ pub fn get_trait_def(&self,
+ item_id: DefIndex,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> {
+ let data = match self.entry(item_id).kind {
+ EntryKind::Trait(data) => data.decode(self),
+ _ => bug!()
+ };
-pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- id: DefIndex)
- -> Option<mir::repr::Mir<'tcx>> {
- let item_doc = cdata.lookup_item(id);
+ ty::TraitDef::new(data.unsafety, data.paren_sugar,
+ tcx.lookup_generics(self.local_def_id(item_id)),
+ data.trait_ref.decode((self, tcx)),
+ self.def_path(item_id).unwrap().deterministic_hash(tcx))
+ }
- return reader::maybe_get_doc(item_doc, tag_mir as usize).map(|mir_doc| {
- let dcx = tls_context::DecodingContext {
- crate_metadata: cdata,
- tcx: tcx,
+ fn get_variant(&self, item: &Entry<'tcx>, index: DefIndex)
+ -> (ty::VariantDefData<'tcx, 'tcx>, Option<DefIndex>) {
+ let data = match item.kind {
+ EntryKind::Variant(data) |
+ EntryKind::Struct(data) |
+ EntryKind::Union(data) => data.decode(self),
+ _ => bug!()
};
- let mut decoder = reader::Decoder::new(mir_doc);
- let mut mir = decoder.read_opaque(|opaque_decoder, _| {
- tls::enter_decoding_context(&dcx, opaque_decoder, |_, opaque_decoder| {
- Decodable::decode(opaque_decoder)
- })
- }).unwrap();
-
- assert!(decoder.position() == mir_doc.end);
+ let fields = item.children.decode(self).map(|index| {
+ let f = self.entry(index);
+ ty::FieldDefData::new(self.local_def_id(index),
+ self.item_name(&f),
+ f.visibility)
+ }).collect();
+
+ (ty::VariantDefData {
+ did: self.local_def_id(data.struct_ctor.unwrap_or(index)),
+ name: self.item_name(item),
+ fields: fields,
+ disr_val: ConstInt::Infer(data.disr),
+ kind: data.kind,
+ }, data.struct_ctor)
+ }
- let mut def_id_and_span_translator = MirDefIdAndSpanTranslator {
- crate_metadata: cdata,
- codemap: tcx.sess.codemap(),
- last_filemap_index_hint: Cell::new(0),
+ pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> ty::AdtDefMaster<'tcx> {
+ let item = self.entry(item_id);
+ let did = self.local_def_id(item_id);
+ let mut ctor_index = None;
+ let variants = if let EntryKind::Enum = item.kind {
+ item.children.decode(self).map(|index| {
+ let (variant, struct_ctor) = self.get_variant(&self.entry(index), index);
+ assert_eq!(struct_ctor, None);
+ variant
+ }).collect()
+ } else{
+ let (variant, struct_ctor) = self.get_variant(&item, item_id);
+ ctor_index = struct_ctor;
+ vec![variant]
+ };
+ let kind = match item.kind {
+ EntryKind::Enum => ty::AdtKind::Enum,
+ EntryKind::Struct(_) => ty::AdtKind::Struct,
+ EntryKind::Union(_) => ty::AdtKind::Union,
+ _ => bug!("get_adt_def called on a non-ADT {:?}", did)
};
- def_id_and_span_translator.visit_mir(&mut mir);
- for promoted in &mut mir.promoted {
- def_id_and_span_translator.visit_mir(promoted);
+ let adt = tcx.intern_adt_def(did, kind, variants);
+ if let Some(ctor_index) = ctor_index {
+ // Make adt definition available through constructor id as well.
+ tcx.insert_adt_def(self.local_def_id(ctor_index), adt);
}
- mir
- });
+ // this needs to be done *after* the variant is interned,
+ // to support recursive structures
+ for variant in &adt.variants {
+ for field in &variant.fields {
+ debug!("evaluating the type of {:?}::{:?}", variant.name, field.name);
+ let ty = self.get_type(field.did.index, tcx);
+ field.fulfill_ty(ty);
+ debug!("evaluating the type of {:?}::{:?}: {:?}",
+ variant.name, field.name, ty);
+ }
+ }
- struct MirDefIdAndSpanTranslator<'cdata, 'codemap> {
- crate_metadata: Cmd<'cdata>,
- codemap: &'codemap codemap::CodeMap,
- last_filemap_index_hint: Cell<usize>
+ adt
}
- impl<'v, 'cdata, 'codemap> mir::visit::MutVisitor<'v>
- for MirDefIdAndSpanTranslator<'cdata, 'codemap>
- {
- fn visit_def_id(&mut self, def_id: &mut DefId) {
- *def_id = translate_def_id(self.crate_metadata, *def_id);
- }
+ 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))
+ }
- fn visit_span(&mut self, span: &mut Span) {
- *span = translate_span(self.crate_metadata,
- self.codemap,
- &self.last_filemap_index_hint,
- *span);
+ pub fn get_super_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> ty::GenericPredicates<'tcx> {
+ match self.entry(item_id).kind {
+ EntryKind::Trait(data) => {
+ data.decode(self).super_predicates.decode((self, tcx))
+ }
+ _ => bug!()
}
}
-}
-fn get_explicit_self(item: rbml::Doc) -> ty::ExplicitSelfCategory {
- fn get_mutability(ch: u8) -> hir::Mutability {
- match ch as char {
- 'i' => hir::MutImmutable,
- 'm' => hir::MutMutable,
- _ => bug!("unknown mutability character: `{}`", ch as char),
- }
+ pub fn get_generics(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> ty::Generics<'tcx> {
+ self.entry(item_id).generics.unwrap().decode((self, tcx))
}
- let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
- let string = explicit_self_doc.as_str_slice();
+ pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
+ self.entry(id).ty.unwrap().decode((self, tcx))
+ }
- let explicit_self_kind = string.as_bytes()[0];
- match explicit_self_kind as char {
- 's' => ty::ExplicitSelfCategory::Static,
- 'v' => ty::ExplicitSelfCategory::ByValue,
- '~' => ty::ExplicitSelfCategory::ByBox,
- // FIXME(#4846) expl. region
- '&' => {
- ty::ExplicitSelfCategory::ByReference(
- ty::ReEmpty,
- get_mutability(string.as_bytes()[1]))
- }
- _ => bug!("unknown self type code: `{}`", explicit_self_kind as char)
+ pub fn get_stability(&self, id: DefIndex) -> Option<attr::Stability> {
+ self.entry(id).stability.map(|stab| stab.decode(self))
}
-}
-/// Returns the def IDs of all the items in the given implementation.
-pub fn get_impl_items(cdata: Cmd, impl_id: DefIndex)
- -> Vec<ty::ImplOrTraitItemId> {
- reader::tagged_docs(cdata.lookup_item(impl_id), tag_item_impl_item).map(|doc| {
- let def_id = item_def_id(doc, cdata);
- match item_sort(doc) {
- Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
- Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
- Some('t') => ty::TypeTraitItemId(def_id),
- _ => bug!("unknown impl item sort"),
- }
- }).collect()
-}
+ pub fn get_deprecation(&self, id: DefIndex) -> Option<attr::Deprecation> {
+ self.entry(id).deprecation.map(|depr| depr.decode(self))
+ }
-pub fn get_trait_name(cdata: Cmd, id: DefIndex) -> ast::Name {
- let doc = cdata.lookup_item(id);
- item_name(doc)
-}
+ pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility {
+ self.entry(id).visibility
+ }
-pub fn is_static_method(cdata: Cmd, id: DefIndex) -> bool {
- let doc = cdata.lookup_item(id);
- match item_sort(doc) {
- Some('r') | Some('p') => {
- get_explicit_self(doc) == ty::ExplicitSelfCategory::Static
+ fn get_impl_data(&self, id: DefIndex) -> ImplData<'tcx> {
+ match self.entry(id).kind {
+ EntryKind::Impl(data) => data.decode(self),
+ _ => bug!()
}
- _ => false
}
-}
-pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Option<ty::ImplOrTraitItem<'tcx>> {
- let item_doc = cdata.lookup_item(id);
-
- let def_id = item_def_id(item_doc, cdata);
-
- let container_id = if let Some(id) = item_parent_item(cdata, item_doc) {
- id
- } else {
- return None;
- };
- let container_doc = cdata.lookup_item(container_id.index);
- let container = match item_family(container_doc) {
- Trait => TraitContainer(container_id),
- _ => ImplContainer(container_id),
- };
-
- let name = item_name(item_doc);
- let vis = item_visibility(item_doc);
- let defaultness = item_defaultness(item_doc);
-
- Some(match item_sort(item_doc) {
- sort @ Some('C') | sort @ Some('c') => {
- let ty = doc_type(item_doc, tcx, cdata);
- ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
- name: name,
- ty: ty,
- vis: vis,
- defaultness: defaultness,
- def_id: def_id,
- container: container,
- has_value: sort == Some('C')
- }))
- }
- Some('r') | Some('p') => {
- let generics = doc_generics(item_doc, tcx, cdata, tag_method_ty_generics);
- let predicates = doc_predicates(item_doc, tcx, cdata, tag_method_ty_generics);
- let ity = tcx.lookup_item_type(def_id).ty;
- let fty = match ity.sty {
- ty::TyFnDef(_, _, fty) => fty,
- _ => bug!(
- "the type {:?} of the method {:?} is not a function?",
- ity, name)
- };
- let explicit_self = get_explicit_self(item_doc);
-
- ty::MethodTraitItem(Rc::new(ty::Method::new(name,
- generics,
- predicates,
- fty,
- explicit_self,
- vis,
- defaultness,
- def_id,
- container)))
- }
- Some('t') => {
- let ty = maybe_doc_type(item_doc, tcx, cdata);
- ty::TypeTraitItem(Rc::new(ty::AssociatedType {
- name: name,
- ty: ty,
- vis: vis,
- defaultness: defaultness,
- def_id: def_id,
- container: container,
- }))
- }
- _ => return None
- })
-}
+ pub fn get_parent_impl(&self, id: DefIndex) -> Option<DefId> {
+ self.get_impl_data(id).parent_impl
+ }
-pub fn get_trait_item_def_ids(cdata: Cmd, id: DefIndex)
- -> Vec<ty::ImplOrTraitItemId> {
- let item = cdata.lookup_item(id);
- reader::tagged_docs(item, tag_item_trait_item).map(|mth| {
- let def_id = item_def_id(mth, cdata);
- match item_sort(mth) {
- Some('C') | Some('c') => ty::ConstTraitItemId(def_id),
- Some('r') | Some('p') => ty::MethodTraitItemId(def_id),
- Some('t') => ty::TypeTraitItemId(def_id),
- _ => bug!("unknown trait item sort"),
- }
- }).collect()
-}
+ pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity {
+ self.get_impl_data(id).polarity
+ }
-pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> ty::ItemVariances {
- let item_doc = cdata.lookup_item(id);
- let variance_doc = reader::get_doc(item_doc, tag_item_variances);
- let mut decoder = reader::Decoder::new(variance_doc);
- Decodable::decode(&mut decoder).unwrap()
-}
+ pub fn get_custom_coerce_unsized_kind(&self, id: DefIndex)
+ -> Option<ty::adjustment::CustomCoerceUnsized> {
+ self.get_impl_data(id).coerce_unsized_kind
+ }
-pub fn get_provided_trait_methods<'a, 'tcx>(cdata: Cmd,
- id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Vec<Rc<ty::Method<'tcx>>> {
- let item = cdata.lookup_item(id);
+ pub fn get_impl_trait(&self,
+ id: DefIndex,
+ tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> Option<ty::TraitRef<'tcx>> {
+ self.get_impl_data(id).trait_ref.map(|tr| tr.decode((self, tcx)))
+ }
- reader::tagged_docs(item, tag_item_trait_item).filter_map(|mth_id| {
- let did = item_def_id(mth_id, cdata);
- let mth = cdata.lookup_item(did.index);
+ /// Iterates over the language items in the given crate.
+ pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> {
+ self.root.lang_items.decode(self).collect()
+ }
- if item_sort(mth) == Some('p') {
- let trait_item = get_impl_or_trait_item(cdata, did.index, tcx);
- if let Some(ty::MethodTraitItem(ref method)) = trait_item {
- Some((*method).clone())
- } else {
- None
- }
- } else {
- None
- }
- }).collect()
-}
+ /// Iterates over each child of the given item.
+ pub fn each_child_of_item<F>(&self, id: DefIndex, mut callback: F)
+ where F: FnMut(def::Export)
+ {
+ // Find the item.
+ let item = match self.maybe_entry(id) {
+ None => return,
+ Some(item) => item.decode(self),
+ };
-pub fn get_associated_consts<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
- let item = cdata.lookup_item(id);
+ // Iterate over all children.
+ for child_index in item.children.decode(self) {
+ // Get the item.
+ if let Some(child) = self.maybe_entry(child_index) {
+ let child = child.decode(self);
+ // Hand off the item to the callback.
+ match child.kind {
+ // FIXME(eddyb) Don't encode these in children.
+ EntryKind::ForeignMod => {
+ for child_index in child.children.decode(self) {
+ callback(def::Export {
+ def_id: self.local_def_id(child_index),
+ name: self.item_name(&self.entry(child_index))
+ });
+ }
+ continue;
+ }
+ EntryKind::Impl(_) | EntryKind::DefaultImpl(_) => continue,
- [tag_item_trait_item, tag_item_impl_item].iter().flat_map(|&tag| {
- reader::tagged_docs(item, tag).filter_map(|ac_id| {
- let did = item_def_id(ac_id, cdata);
- let ac_doc = cdata.lookup_item(did.index);
+ _ => {}
+ }
- match item_sort(ac_doc) {
- Some('C') | Some('c') => {
- let trait_item = get_impl_or_trait_item(cdata, did.index, tcx);
- if let Some(ty::ConstTraitItem(ref ac)) = trait_item {
- Some((*ac).clone())
- } else {
- None
- }
+ let def_key = child.def_key.decode(self);
+ if let Some(name) = def_key.disambiguated_data.data.get_opt_name() {
+ callback(def::Export {
+ def_id: self.local_def_id(child_index),
+ name: name
+ });
}
- _ => None
}
- })
- }).collect()
-}
-
-pub fn get_variant_kind(cdata: Cmd, node_id: DefIndex) -> Option<VariantKind>
-{
- let item = cdata.lookup_item(node_id);
- family_to_variant_kind(item_family(item))
-}
-
-pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option<DefId>
-{
- let item = cdata.lookup_item(node_id);
- reader::maybe_get_doc(item, tag_items_data_item_struct_ctor).
- map(|ctor_doc| translated_def_id(cdata, ctor_doc))
-}
+ }
-/// If node_id is the constructor of a tuple struct, retrieve the NodeId of
-/// the actual type definition, otherwise, return None
-pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
- node_id: DefIndex)
- -> Option<DefId>
-{
- let item = cdata.lookup_item(node_id);
- reader::tagged_docs(item, tag_items_data_item_is_tuple_struct_ctor).next().map(|_| {
- item_require_parent_item(cdata, item)
- })
-}
+ if let EntryKind::Mod(data) = item.kind {
+ for exp in data.decode(self).reexports.decode(self) {
+ callback(exp);
+ }
+ }
+ }
-pub fn get_item_attrs(cdata: Cmd,
- orig_node_id: DefIndex)
- -> Vec<ast::Attribute> {
- // The attributes for a tuple struct are attached to the definition, not the ctor;
- // we assume that someone passing in a tuple struct ctor is actually wanting to
- // look at the definition
- let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
- let node_id = node_id.map(|x| x.index).unwrap_or(orig_node_id);
- let item = cdata.lookup_item(node_id);
- get_attributes(item)
-}
+ pub fn maybe_get_item_ast(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
+ -> Option<&'tcx InlinedItem> {
+ debug!("Looking up item: {:?}", id);
+ let item_doc = self.entry(id);
+ let item_did = self.local_def_id(id);
+ let parent_def_id = self.local_def_id(self.def_key(id).parent.unwrap());
+ let mut parent_def_path = self.def_path(id).unwrap();
+ parent_def_path.data.pop();
+ item_doc.ast.map(|ast| {
+ let ast = ast.decode(self);
+ decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast, item_did)
+ })
+ }
-pub fn get_struct_field_attrs(cdata: Cmd) -> FnvHashMap<DefId, Vec<ast::Attribute>> {
- let data = rbml::Doc::new(cdata.data());
- let fields = reader::get_doc(data, tag_struct_fields);
- reader::tagged_docs(fields, tag_struct_field).map(|field| {
- let def_id = translated_def_id(cdata, reader::get_doc(field, tag_def_id));
- let attrs = get_attributes(field);
- (def_id, attrs)
- }).collect()
-}
+ pub fn is_item_mir_available(&self, id: DefIndex) -> bool {
+ self.maybe_entry(id).and_then(|item| item.decode(self).mir).is_some()
+ }
-fn struct_field_family_to_visibility(family: Family) -> ty::Visibility {
- match family {
- PublicField => ty::Visibility::Public,
- InheritedField => ty::Visibility::PrivateExternal,
- _ => bug!()
+ pub fn maybe_get_item_mir(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
+ -> Option<Mir<'tcx>> {
+ self.entry(id).mir.map(|mir| mir.decode((self, tcx)))
}
-}
-pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec<ast::Name> {
- let item = cdata.lookup_item(id);
- let mut index = 0;
- reader::tagged_docs(item, tag_item_field).map(|an_item| {
- item_name(an_item)
- }).chain(reader::tagged_docs(item, tag_item_unnamed_field).map(|_| {
- let name = token::with_ident_interner(|interner| interner.intern(index.to_string()));
- index += 1;
- name
- })).collect()
-}
+ pub fn get_impl_or_trait_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> Option<ty::ImplOrTraitItem<'tcx>> {
+ let item = self.entry(id);
+ let parent_and_name = || {
+ let def_key = item.def_key.decode(self);
+ (self.local_def_id(def_key.parent.unwrap()),
+ def_key.disambiguated_data.data.get_opt_name().unwrap())
+ };
-fn get_meta_items(md: rbml::Doc) -> Vec<P<ast::MetaItem>> {
- reader::tagged_docs(md, tag_meta_item_word).map(|meta_item_doc| {
- let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
- let n = token::intern_and_get_ident(nd.as_str_slice());
- attr::mk_word_item(n)
- }).chain(reader::tagged_docs(md, tag_meta_item_name_value).map(|meta_item_doc| {
- let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
- let vd = reader::get_doc(meta_item_doc, tag_meta_item_value);
- let n = token::intern_and_get_ident(nd.as_str_slice());
- let v = token::intern_and_get_ident(vd.as_str_slice());
- // FIXME (#623): Should be able to decode MetaItemKind::NameValue variants,
- // but currently the encoder just drops them
- attr::mk_name_value_item_str(n, v)
- })).chain(reader::tagged_docs(md, tag_meta_item_list).map(|meta_item_doc| {
- let nd = reader::get_doc(meta_item_doc, tag_meta_item_name);
- let n = token::intern_and_get_ident(nd.as_str_slice());
- let subitems = get_meta_items(meta_item_doc);
- attr::mk_list_item(n, subitems)
- })).collect()
-}
+ Some(match item.kind {
+ EntryKind::AssociatedConst(container) => {
+ let (parent, name) = parent_and_name();
+ ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
+ name: name,
+ ty: item.ty.unwrap().decode((self, tcx)),
+ vis: item.visibility,
+ defaultness: container.defaultness(),
+ def_id: self.local_def_id(id),
+ container: container.with_def_id(parent),
+ has_value: container.has_body(),
+ }))
+ }
+ EntryKind::Method(data) => {
+ let (parent, name) = parent_and_name();
+ let ity = item.ty.unwrap().decode((self, tcx));
+ let fty = match ity.sty {
+ ty::TyFnDef(.., fty) => fty,
+ _ => bug!(
+ "the type {:?} of the method {:?} is not a function?",
+ ity, name)
+ };
+
+ let data = data.decode(self);
+ ty::MethodTraitItem(Rc::new(ty::Method {
+ name: name,
+ generics: tcx.lookup_generics(self.local_def_id(id)),
+ predicates: item.predicates.unwrap().decode((self, tcx)),
+ fty: fty,
+ explicit_self: data.explicit_self.decode((self, tcx)),
+ vis: item.visibility,
+ defaultness: data.container.defaultness(),
+ has_body: data.container.has_body(),
+ def_id: self.local_def_id(id),
+ container: data.container.with_def_id(parent),
+ }))
+ }
+ EntryKind::AssociatedType(container) => {
+ let (parent, name) = parent_and_name();
+ ty::TypeTraitItem(Rc::new(ty::AssociatedType {
+ name: name,
+ ty: item.ty.map(|ty| ty.decode((self, tcx))),
+ vis: item.visibility,
+ defaultness: container.defaultness(),
+ def_id: self.local_def_id(id),
+ container: container.with_def_id(parent),
+ }))
+ }
+ _ => return None
+ })
+ }
-fn get_attributes(md: rbml::Doc) -> Vec<ast::Attribute> {
- match reader::maybe_get_doc(md, tag_attributes) {
- Some(attrs_d) => {
- reader::tagged_docs(attrs_d, tag_attribute).map(|attr_doc| {
- let is_sugared_doc = reader::doc_as_u8(
- reader::get_doc(attr_doc, tag_attribute_is_sugared_doc)
- ) == 1;
- let meta_items = get_meta_items(attr_doc);
- // Currently it's only possible to have a single meta item on
- // an attribute
- assert_eq!(meta_items.len(), 1);
- let meta_item = meta_items.into_iter().nth(0).unwrap();
- attr::mk_doc_attr_outer(attr::mk_attr_id(), meta_item, is_sugared_doc)
- }).collect()
- },
- None => vec![],
+ pub fn get_item_variances(&self, id: DefIndex) -> Vec<ty::Variance> {
+ self.entry(id).variances.decode(self).collect()
}
-}
-fn list_crate_attributes(md: rbml::Doc, hash: &Svh,
- out: &mut io::Write) -> io::Result<()> {
- write!(out, "=Crate Attributes ({})=\n", *hash)?;
+ pub fn get_variant_kind(&self, node_id: DefIndex) -> Option<ty::VariantKind> {
+ match self.entry(node_id).kind {
+ EntryKind::Struct(data) |
+ EntryKind::Union(data) |
+ EntryKind::Variant(data) => Some(data.decode(self).kind),
+ _ => None
+ }
+ }
- let r = get_attributes(md);
- for attr in &r {
- write!(out, "{}\n", pprust::attribute_to_string(attr))?;
+ pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option<DefId> {
+ match self.entry(node_id).kind {
+ EntryKind::Struct(data) => {
+ data.decode(self).struct_ctor.map(|index| self.local_def_id(index))
+ }
+ _ => None
+ }
}
- write!(out, "\n\n")
-}
+ pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec<ast::Attribute> {
+ // The attributes for a tuple struct are attached to the definition, not the ctor;
+ // we assume that someone passing in a tuple struct ctor is actually wanting to
+ // look at the definition
+ let mut item = self.entry(node_id);
+ let def_key = item.def_key.decode(self);
+ if def_key.disambiguated_data.data == DefPathData::StructCtor {
+ item = self.entry(def_key.parent.unwrap());
+ }
+ self.get_attributes(&item)
+ }
-pub fn get_crate_attributes(data: &[u8]) -> Vec<ast::Attribute> {
- get_attributes(rbml::Doc::new(data))
-}
+ pub fn get_struct_field_names(&self, id: DefIndex) -> Vec<ast::Name> {
+ self.entry(id).children.decode(self).map(|index| {
+ self.item_name(&self.entry(index))
+ }).collect()
+ }
-#[derive(Clone)]
-pub struct CrateDep {
- pub cnum: ast::CrateNum,
- pub name: String,
- pub hash: Svh,
- pub explicitly_linked: bool,
-}
+ fn get_attributes(&self, item: &Entry<'tcx>) -> Vec<ast::Attribute> {
+ item.attributes.decode(self).map(|mut attr| {
+ // Need new unique IDs: old thread-local IDs won't map to new threads.
+ attr.node.id = attr::mk_attr_id();
+ attr
+ }).collect()
+ }
-pub fn get_crate_deps(data: &[u8]) -> Vec<CrateDep> {
- let cratedoc = rbml::Doc::new(data);
- let depsdoc = reader::get_doc(cratedoc, tag_crate_deps);
-
- fn docstr(doc: rbml::Doc, tag_: usize) -> String {
- let d = reader::get_doc(doc, tag_);
- d.as_str_slice().to_string()
- }
-
- reader::tagged_docs(depsdoc, tag_crate_dep).enumerate().map(|(crate_num, depdoc)| {
- let name = docstr(depdoc, tag_crate_dep_crate_name);
- let hash = Svh::new(reader::doc_as_u64(reader::get_doc(depdoc, tag_crate_dep_hash)));
- let doc = reader::get_doc(depdoc, tag_crate_dep_explicitly_linked);
- let explicitly_linked = reader::doc_as_u8(doc) != 0;
- CrateDep {
- cnum: crate_num as u32 + 1,
- name: name,
- hash: hash,
- explicitly_linked: explicitly_linked,
+ // Translate a DefId from the current compilation environment to a DefId
+ // for an external crate.
+ fn reverse_translate_def_id(&self, did: DefId) -> Option<DefId> {
+ for (local, &global) in self.cnum_map.borrow().iter_enumerated() {
+ if global == did.krate {
+ return Some(DefId { krate: local, index: did.index });
+ }
}
- }).collect()
-}
-fn list_crate_deps(data: &[u8], out: &mut io::Write) -> io::Result<()> {
- write!(out, "=External Dependencies=\n")?;
- for dep in &get_crate_deps(data) {
- write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)?;
+ None
}
- write!(out, "\n")?;
- Ok(())
-}
-pub fn maybe_get_crate_hash(data: &[u8]) -> Option<Svh> {
- let cratedoc = rbml::Doc::new(data);
- reader::maybe_get_doc(cratedoc, tag_crate_hash).map(|doc| {
- Svh::new(reader::doc_as_u64(doc))
- })
-}
+ pub fn get_inherent_implementations_for_type(&self, id: DefIndex) -> Vec<DefId> {
+ self.entry(id).inherent_impls.decode(self).map(|index| {
+ self.local_def_id(index)
+ }).collect()
+ }
-pub fn get_crate_hash(data: &[u8]) -> Svh {
- let cratedoc = rbml::Doc::new(data);
- let hashdoc = reader::get_doc(cratedoc, tag_crate_hash);
- Svh::new(reader::doc_as_u64(hashdoc))
-}
+ pub fn get_implementations_for_trait(&self, filter: Option<DefId>, result: &mut Vec<DefId>) {
+ // Do a reverse lookup beforehand to avoid touching the crate_num
+ // hash map in the loop below.
+ let filter = match filter.map(|def_id| self.reverse_translate_def_id(def_id)) {
+ Some(Some(def_id)) => Some((def_id.krate.as_u32(), def_id.index)),
+ Some(None) => return,
+ None => None
+ };
-pub fn maybe_get_crate_name(data: &[u8]) -> Option<&str> {
- let cratedoc = rbml::Doc::new(data);
- reader::maybe_get_doc(cratedoc, tag_crate_crate_name).map(|doc| {
- doc.as_str_slice()
- })
-}
+ // FIXME(eddyb) Make this O(1) instead of O(n).
+ for trait_impls in self.root.impls.decode(self) {
+ if filter.is_some() && filter != Some(trait_impls.trait_id) {
+ continue;
+ }
-pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
- let crate_doc = rbml::Doc::new(data);
- let disambiguator_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
- let slice: &'a str = disambiguator_doc.as_str_slice();
- slice
-}
+ result.extend(trait_impls.impls.decode(self).map(|index| {
+ self.local_def_id(index)
+ }));
-pub fn get_crate_triple(data: &[u8]) -> Option<String> {
- let cratedoc = rbml::Doc::new(data);
- let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
- triple_doc.map(|s| s.as_str().to_string())
-}
+ if filter.is_some() {
+ break;
+ }
+ }
+ }
-pub fn get_crate_name(data: &[u8]) -> &str {
- maybe_get_crate_name(data).expect("no crate name in crate")
-}
+ pub fn get_trait_of_item(&self, id: DefIndex) -> Option<DefId> {
+ self.entry(id).def_key.decode(self).parent.and_then(|parent_index| {
+ match self.entry(parent_index).kind {
+ EntryKind::Trait(_) => Some(self.local_def_id(parent_index)),
+ _ => None
+ }
+ })
+ }
-pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> {
- let hash = get_crate_hash(bytes);
- let md = rbml::Doc::new(bytes);
- list_crate_attributes(md, &hash, out)?;
- list_crate_deps(bytes, out)
-}
-// Translates a def_id from an external crate to a def_id for the current
-// compilation environment. We use this when trying to load types from
-// external crates - if those types further refer to types in other crates
-// then we must translate the crate number from that encoded in the external
-// crate to the correct local crate number.
-pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
- if did.is_local() {
- return DefId { krate: cdata.cnum, index: did.index };
+ pub fn get_native_libraries(&self) -> Vec<(NativeLibraryKind, String)> {
+ self.root.native_libraries.decode(self).collect()
}
- DefId {
- krate: cdata.cnum_map.borrow()[did.krate],
- index: did.index
+ pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> {
+ self.root.dylib_dependency_formats.decode(self).enumerate().flat_map(|(i, link)| {
+ let cnum = CrateNum::new(i + 1);
+ link.map(|link| (self.cnum_map.borrow()[cnum], link))
+ }).collect()
}
-}
-// Translate a DefId from the current compilation environment to a DefId
-// for an external crate.
-fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
- for (local, &global) in cdata.cnum_map.borrow().iter_enumerated() {
- if global == did.krate {
- return Some(DefId { krate: local, index: did.index });
- }
+ pub fn get_missing_lang_items(&self) -> Vec<lang_items::LangItem> {
+ self.root.lang_items_missing.decode(self).collect()
}
- None
-}
-
-/// Translates a `Span` from an extern crate to the corresponding `Span`
-/// within the local crate's codemap.
-pub fn translate_span(cdata: Cmd,
- codemap: &codemap::CodeMap,
- last_filemap_index_hint: &Cell<usize>,
- span: syntax_pos::Span)
- -> syntax_pos::Span {
- let span = if span.lo > span.hi {
- // Currently macro expansion sometimes produces invalid Span values
- // where lo > hi. In order not to crash the compiler when trying to
- // translate these values, let's transform them into something we
- // can handle (and which will produce useful debug locations at
- // least some of the time).
- // This workaround is only necessary as long as macro expansion is
- // not fixed. FIXME(#23480)
- syntax_pos::mk_sp(span.lo, span.lo)
- } else {
- span
- };
-
- let imported_filemaps = cdata.imported_filemaps(&codemap);
- let filemap = {
- // Optimize for the case that most spans within a translated item
- // originate from the same filemap.
- let last_filemap_index = last_filemap_index_hint.get();
- let last_filemap = &imported_filemaps[last_filemap_index];
-
- if span.lo >= last_filemap.original_start_pos &&
- span.lo <= last_filemap.original_end_pos &&
- span.hi >= last_filemap.original_start_pos &&
- span.hi <= last_filemap.original_end_pos {
- last_filemap
- } else {
- let mut a = 0;
- let mut b = imported_filemaps.len();
+ pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec<ast::Name> {
+ let arg_names = match self.entry(id).kind {
+ EntryKind::Fn(data) |
+ EntryKind::ForeignFn(data) => data.decode(self).arg_names,
+ EntryKind::Method(data) => data.decode(self).fn_data.arg_names,
+ _ => LazySeq::empty()
+ };
+ arg_names.decode(self).collect()
+ }
- while b - a > 1 {
- let m = (a + b) / 2;
- if imported_filemaps[m].original_start_pos > span.lo {
- b = m;
- } else {
- a = m;
- }
- }
+ pub fn get_reachable_ids(&self) -> Vec<DefId> {
+ self.root.reachable_ids.decode(self).map(|index| self.local_def_id(index)).collect()
+ }
- last_filemap_index_hint.set(a);
- &imported_filemaps[a]
- }
- };
+ pub fn is_const_fn(&self, id: DefIndex) -> bool {
+ let constness = match self.entry(id).kind {
+ EntryKind::Method(data) => data.decode(self).fn_data.constness,
+ EntryKind::Fn(data) => data.decode(self).constness,
+ _ => hir::Constness::NotConst
+ };
+ constness == hir::Constness::Const
+ }
- let lo = (span.lo - filemap.original_start_pos) +
- filemap.translated_filemap.start_pos;
- let hi = (span.hi - filemap.original_start_pos) +
- filemap.translated_filemap.start_pos;
+ pub fn is_extern_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
+ let item = match self.maybe_entry(id) {
+ Some(item) => item.decode(self),
+ None => return false,
+ };
+ let applicable = match item.kind {
+ EntryKind::ImmStatic |
+ EntryKind::MutStatic |
+ EntryKind::ForeignImmStatic |
+ EntryKind::ForeignMutStatic => true,
+
+ EntryKind::Fn(_) | EntryKind::ForeignFn(_) => {
+ self.get_generics(id, tcx).types.is_empty()
+ }
- syntax_pos::mk_sp(lo, hi)
-}
+ _ => false,
+ };
-pub fn each_inherent_implementation_for_type<F>(cdata: Cmd,
- id: DefIndex,
- mut callback: F)
- where F: FnMut(DefId),
-{
- let item_doc = cdata.lookup_item(id);
- for impl_doc in reader::tagged_docs(item_doc, tag_items_data_item_inherent_impl) {
- if reader::maybe_get_doc(impl_doc, tag_item_trait_ref).is_none() {
- callback(item_def_id(impl_doc, cdata));
+ if applicable {
+ attr::contains_extern_indicator(tcx.sess.diagnostic(),
+ &self.get_attributes(&item))
+ } else {
+ false
}
}
-}
-pub fn each_implementation_for_trait<F>(cdata: Cmd,
- def_id: DefId,
- mut callback: F) where
- F: FnMut(DefId),
-{
- // Do a reverse lookup beforehand to avoid touching the crate_num
- // hash map in the loop below.
- if let Some(crate_local_did) = reverse_translate_def_id(cdata, def_id) {
- let def_id_u64 = def_to_u64(crate_local_did);
-
- let impls_doc = reader::get_doc(rbml::Doc::new(cdata.data()), tag_impls);
- for trait_doc in reader::tagged_docs(impls_doc, tag_impls_trait) {
- let trait_def_id = reader::get_doc(trait_doc, tag_def_id);
- if reader::doc_as_u64(trait_def_id) != def_id_u64 {
- continue;
- }
- for impl_doc in reader::tagged_docs(trait_doc, tag_impls_trait_impl) {
- callback(translated_def_id(cdata, impl_doc));
- }
+ pub fn is_foreign_item(&self, id: DefIndex) -> bool {
+ match self.entry(id).kind {
+ EntryKind::ForeignImmStatic |
+ EntryKind::ForeignMutStatic |
+ EntryKind::ForeignFn(_) => true,
+ _ => false
}
}
-}
-pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd,
- id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> Option<DefId> {
- let item_doc = cdata.lookup_item(id);
- let parent_item_id = match item_parent_item(cdata, item_doc) {
- None => return None,
- Some(item_id) => item_id,
- };
- let parent_item_doc = cdata.lookup_item(parent_item_id.index);
- match item_family(parent_item_doc) {
- Trait => Some(item_def_id(parent_item_doc, cdata)),
- Impl | DefaultImpl => {
- reader::maybe_get_doc(parent_item_doc, tag_item_trait_ref)
- .map(|_| item_trait_ref(parent_item_doc, tcx, cdata).def_id)
+ pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool {
+ match self.entry(trait_id).kind {
+ EntryKind::Trait(data) => data.decode(self).has_default_impl,
+ _ => bug!()
}
- _ => None
}
-}
-
-pub fn get_native_libraries(cdata: Cmd)
- -> Vec<(cstore::NativeLibraryKind, String)> {
- let libraries = reader::get_doc(rbml::Doc::new(cdata.data()),
- tag_native_libraries);
- reader::tagged_docs(libraries, tag_native_libraries_lib).map(|lib_doc| {
- let kind_doc = reader::get_doc(lib_doc, tag_native_libraries_kind);
- let name_doc = reader::get_doc(lib_doc, tag_native_libraries_name);
- let kind: cstore::NativeLibraryKind =
- cstore::NativeLibraryKind::from_u32(reader::doc_as_u32(kind_doc)).unwrap();
- let name = name_doc.as_str().to_string();
- (kind, name)
- }).collect()
-}
-
-pub fn get_plugin_registrar_fn(data: &[u8]) -> Option<DefIndex> {
- reader::maybe_get_doc(rbml::Doc::new(data), tag_plugin_registrar_fn)
- .map(|doc| DefIndex::from_u32(reader::doc_as_u32(doc)))
-}
-
-pub fn each_exported_macro<F>(data: &[u8], mut f: F) where
- F: FnMut(ast::Name, Vec<ast::Attribute>, Span, String) -> bool,
-{
- let macros = reader::get_doc(rbml::Doc::new(data), tag_macro_defs);
- for macro_doc in reader::tagged_docs(macros, tag_macro_def) {
- let name = item_name(macro_doc);
- let attrs = get_attributes(macro_doc);
- let span = get_macro_span(macro_doc);
- let body = reader::get_doc(macro_doc, tag_macro_def_body);
- if !f(name, attrs, span, body.as_str().to_string()) {
- break;
+ pub fn is_default_impl(&self, impl_id: DefIndex) -> bool {
+ match self.entry(impl_id).kind {
+ EntryKind::DefaultImpl(_) => true,
+ _ => false
}
}
-}
-
-pub fn get_macro_span(doc: rbml::Doc) -> Span {
- let lo_doc = reader::get_doc(doc, tag_macro_def_span_lo);
- let lo = BytePos(reader::doc_as_u32(lo_doc));
- let hi_doc = reader::get_doc(doc, tag_macro_def_span_hi);
- let hi = BytePos(reader::doc_as_u32(hi_doc));
- return Span { lo: lo, hi: hi, expn_id: NO_EXPANSION };
-}
-
-pub fn get_dylib_dependency_formats(cdata: Cmd)
- -> Vec<(ast::CrateNum, LinkagePreference)>
-{
- let formats = reader::get_doc(rbml::Doc::new(cdata.data()),
- tag_dylib_dependency_formats);
- let mut result = Vec::new();
-
- debug!("found dylib deps: {}", formats.as_str_slice());
- for spec in formats.as_str_slice().split(',') {
- if spec.is_empty() { continue }
- let cnum = spec.split(':').nth(0).unwrap();
- let link = spec.split(':').nth(1).unwrap();
- let cnum: ast::CrateNum = cnum.parse().unwrap();
- let cnum = cdata.cnum_map.borrow()[cnum];
- result.push((cnum, if link == "d" {
- LinkagePreference::RequireDynamic
- } else {
- LinkagePreference::RequireStatic
- }));
- }
- return result;
-}
-pub fn get_missing_lang_items(cdata: Cmd)
- -> Vec<lang_items::LangItem>
-{
- let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_lang_items);
- reader::tagged_docs(items, tag_lang_items_missing).map(|missing_docs| {
- lang_items::LangItem::from_u32(reader::doc_as_u32(missing_docs)).unwrap()
- }).collect()
-}
-
-pub fn get_method_arg_names(cdata: Cmd, id: DefIndex) -> Vec<String> {
- let method_doc = cdata.lookup_item(id);
- match reader::maybe_get_doc(method_doc, tag_method_argument_names) {
- Some(args_doc) => {
- reader::tagged_docs(args_doc, tag_method_argument_name).map(|name_doc| {
- name_doc.as_str_slice().to_string()
- }).collect()
- },
- None => vec![],
+ pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind {
+ match self.entry(closure_id).kind {
+ EntryKind::Closure(data) => data.decode(self).kind,
+ _ => bug!()
+ }
}
-}
-pub fn get_reachable_ids(cdata: Cmd) -> Vec<DefId> {
- let items = reader::get_doc(rbml::Doc::new(cdata.data()),
- tag_reachable_ids);
- reader::tagged_docs(items, tag_reachable_id).map(|doc| {
- DefId {
- krate: cdata.cnum,
- index: DefIndex::from_u32(reader::doc_as_u32(doc)),
+ pub fn closure_ty(&self, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
+ -> ty::ClosureTy<'tcx> {
+ match self.entry(closure_id).kind {
+ EntryKind::Closure(data) => data.decode(self).ty.decode((self, tcx)),
+ _ => bug!()
}
- }).collect()
-}
-
-pub fn is_typedef(cdata: Cmd, id: DefIndex) -> bool {
- let item_doc = cdata.lookup_item(id);
- match item_family(item_doc) {
- Type => true,
- _ => false,
}
-}
-pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
- let item_doc = cdata.lookup_item(id);
- match fn_constness(item_doc) {
- hir::Constness::Const => true,
- hir::Constness::NotConst => false,
+ pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey {
+ debug!("def_key: id={:?}", id);
+ self.entry(id).def_key.decode(self)
}
-}
-pub fn is_extern_item<'a, 'tcx>(cdata: Cmd,
- id: DefIndex,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> bool {
- let item_doc = match cdata.get_item(id) {
- Some(doc) => doc,
- None => return false,
- };
- let applicable = match item_family(item_doc) {
- ImmStatic | MutStatic => true,
- Fn => {
- let ty::TypeScheme { generics, .. } = get_type(cdata, id, tcx);
- let no_generics = generics.types.is_empty();
- no_generics
- },
- _ => false,
- };
-
- if applicable {
- attr::contains_extern_indicator(tcx.sess.diagnostic(),
- &get_attributes(item_doc))
- } else {
- false
+ // Returns the path leading to the thing with this `id`. Note that
+ // some def-ids don't wind up in the metadata, so `def_path` sometimes
+ // returns `None`
+ pub fn def_path(&self, id: DefIndex) -> Option<hir_map::DefPath> {
+ debug!("def_path(id={:?})", id);
+ if self.maybe_entry(id).is_some() {
+ Some(hir_map::DefPath::make(self.cnum, id, |parent| self.def_key(parent)))
+ } else {
+ None
+ }
}
-}
-pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool {
- let item_doc = cdata.lookup_item(id);
- let parent_item_id = match item_parent_item(cdata, item_doc) {
- None => return false,
- Some(item_id) => item_id,
- };
- let parent_item_doc = cdata.lookup_item(parent_item_id.index);
- item_family(parent_item_doc) == ForeignMod
-}
-
-pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
- let item_doc = cdata.lookup_item(id);
- match item_family(item_doc) {
- Impl => true,
- _ => false,
- }
-}
+ /// Imports the codemap from an external crate into the codemap of the crate
+ /// currently being compiled (the "local crate").
+ ///
+ /// The import algorithm works analogous to how AST items are inlined from an
+ /// external crate's metadata:
+ /// For every FileMap in the external codemap an 'inline' copy is created in the
+ /// local codemap. The correspondence relation between external and local
+ /// FileMaps is recorded in the `ImportedFileMap` objects returned from this
+ /// function. When an item from an external crate is later inlined into this
+ /// crate, this correspondence information is used to translate the span
+ /// information of the inlined item so that it refers the correct positions in
+ /// the local codemap (see `<decoder::DecodeContext as SpecializedDecoder<Span>>`).
+ ///
+ /// The import algorithm in the function below will reuse FileMaps already
+ /// existing in the local codemap. For example, even if the FileMap of some
+ /// source file of libstd gets imported many times, there will only ever be
+ /// one FileMap object for the corresponding file in the local codemap.
+ ///
+ /// Note that imported FileMaps do not actually contain the source code of the
+ /// file they represent, just information about length, line breaks, and
+ /// multibyte characters. This information is enough to generate valid debuginfo
+ /// for items inlined from other crates.
+ pub fn imported_filemaps(&'a self, local_codemap: &codemap::CodeMap)
+ -> Ref<'a, Vec<cstore::ImportedFileMap>> {
+ {
+ let filemaps = self.codemap_import_info.borrow();
+ if !filemaps.is_empty() {
+ return filemaps;
+ }
+ }
-fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- cdata: Cmd,
- tag: usize)
- -> ty::Generics<'tcx>
-{
- let doc = reader::get_doc(base_doc, tag);
-
- let mut types = subst::VecPerParamSpace::empty();
- for p in reader::tagged_docs(doc, tag_type_param_def) {
- let bd =
- TyDecoder::with_doc(tcx, cdata.cnum, p,
- &mut |did| translate_def_id(cdata, did))
- .parse_type_param_def();
- types.push(bd.space, bd);
- }
-
- let mut regions = subst::VecPerParamSpace::empty();
- for p in reader::tagged_docs(doc, tag_region_param_def) {
- let bd =
- TyDecoder::with_doc(tcx, cdata.cnum, p,
- &mut |did| translate_def_id(cdata, did))
- .parse_region_param_def();
- regions.push(bd.space, bd);
- }
-
- ty::Generics { types: types, regions: regions }
-}
+ let external_codemap = self.root.codemap.decode(self);
+
+ let imported_filemaps = external_codemap.map(|filemap_to_import| {
+ // Try to find an existing FileMap that can be reused for the filemap to
+ // be imported. A FileMap is reusable if it is exactly the same, just
+ // positioned at a different offset within the codemap.
+ let reusable_filemap = {
+ local_codemap.files
+ .borrow()
+ .iter()
+ .find(|fm| are_equal_modulo_startpos(&fm, &filemap_to_import))
+ .map(|rc| rc.clone())
+ };
-fn doc_predicate<'a, 'tcx>(cdata: Cmd,
- doc: rbml::Doc,
- tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::Predicate<'tcx>
-{
- let predicate_pos = cdata.xref_index.lookup(
- cdata.data(), reader::doc_as_u32(doc)).unwrap() as usize;
- TyDecoder::new(
- cdata.data(), cdata.cnum, predicate_pos, tcx,
- &mut |did| translate_def_id(cdata, did)
- ).parse_predicate()
-}
+ match reusable_filemap {
+ Some(fm) => {
+ cstore::ImportedFileMap {
+ original_start_pos: filemap_to_import.start_pos,
+ original_end_pos: filemap_to_import.end_pos,
+ translated_filemap: fm
+ }
+ }
+ None => {
+ // We can't reuse an existing FileMap, so allocate a new one
+ // containing the information we need.
+ let syntax_pos::FileMap {
+ name,
+ abs_path,
+ start_pos,
+ end_pos,
+ lines,
+ multibyte_chars,
+ ..
+ } = filemap_to_import;
+
+ let source_length = (end_pos - start_pos).to_usize();
+
+ // Translate line-start positions and multibyte character
+ // position into frame of reference local to file.
+ // `CodeMap::new_imported_filemap()` will then translate those
+ // coordinates to their new global frame of reference when the
+ // offset of the FileMap is known.
+ let mut lines = lines.into_inner();
+ for pos in &mut lines {
+ *pos = *pos - start_pos;
+ }
+ let mut multibyte_chars = multibyte_chars.into_inner();
+ for mbc in &mut multibyte_chars {
+ mbc.pos = mbc.pos - start_pos;
+ }
-fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
- tcx: TyCtxt<'a, 'tcx, 'tcx>,
- cdata: Cmd,
- tag: usize)
- -> ty::GenericPredicates<'tcx>
-{
- let doc = reader::get_doc(base_doc, tag);
+ let local_version = local_codemap.new_imported_filemap(name,
+ abs_path,
+ source_length,
+ lines,
+ multibyte_chars);
+ cstore::ImportedFileMap {
+ original_start_pos: start_pos,
+ original_end_pos: end_pos,
+ translated_filemap: local_version
+ }
+ }
+ }
+ }).collect();
- let mut predicates = subst::VecPerParamSpace::empty();
- for predicate_doc in reader::tagged_docs(doc, tag_type_predicate) {
- predicates.push(subst::TypeSpace,
- doc_predicate(cdata, predicate_doc, tcx));
- }
- for predicate_doc in reader::tagged_docs(doc, tag_self_predicate) {
- predicates.push(subst::SelfSpace,
- doc_predicate(cdata, predicate_doc, tcx));
+ // This shouldn't borrow twice, but there is no way to downgrade RefMut to Ref.
+ *self.codemap_import_info.borrow_mut() = imported_filemaps;
+ self.codemap_import_info.borrow()
}
- for predicate_doc in reader::tagged_docs(doc, tag_fn_predicate) {
- predicates.push(subst::FnSpace,
- doc_predicate(cdata, predicate_doc, tcx));
- }
-
- ty::GenericPredicates { predicates: predicates }
}
-pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool {
- let trait_doc = cdata.lookup_item(trait_id);
- assert!(item_family(trait_doc) == Family::Trait);
- let defaulted_doc = reader::get_doc(trait_doc, tag_defaulted_trait);
- reader::doc_as_u8(defaulted_doc) != 0
-}
+fn are_equal_modulo_startpos(fm1: &syntax_pos::FileMap, fm2: &syntax_pos::FileMap) -> bool {
+ if fm1.byte_length() != fm2.byte_length() {
+ return false;
+ }
-pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool {
- let impl_doc = cdata.lookup_item(impl_id);
- item_family(impl_doc) == Family::DefaultImpl
-}
+ if fm1.name != fm2.name {
+ return false;
+ }
-pub fn get_imported_filemaps(metadata: &[u8]) -> Vec<syntax_pos::FileMap> {
- let crate_doc = rbml::Doc::new(metadata);
- let cm_doc = reader::get_doc(crate_doc, tag_codemap);
+ let lines1 = fm1.lines.borrow();
+ let lines2 = fm2.lines.borrow();
- reader::tagged_docs(cm_doc, tag_codemap_filemap).map(|filemap_doc| {
- let mut decoder = reader::Decoder::new(filemap_doc);
- decoder.read_opaque(|opaque_decoder, _| {
- Decodable::decode(opaque_decoder)
- }).unwrap()
- }).collect()
-}
+ if lines1.len() != lines2.len() {
+ return false;
+ }
-pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind {
- let closure_doc = cdata.lookup_item(closure_id);
- let closure_kind_doc = reader::get_doc(closure_doc, tag_items_closure_kind);
- let mut decoder = reader::Decoder::new(closure_kind_doc);
- ty::ClosureKind::decode(&mut decoder).unwrap()
-}
+ for (&line1, &line2) in lines1.iter().zip(lines2.iter()) {
+ if (line1 - fm1.start_pos) != (line2 - fm2.start_pos) {
+ return false;
+ }
+ }
-pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
- -> ty::ClosureTy<'tcx> {
- let closure_doc = cdata.lookup_item(closure_id);
- let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty);
- TyDecoder::with_doc(tcx, cdata.cnum, closure_ty_doc, &mut |did| translate_def_id(cdata, did))
- .parse_closure_ty()
-}
+ let multibytes1 = fm1.multibyte_chars.borrow();
+ let multibytes2 = fm2.multibyte_chars.borrow();
-pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey {
- debug!("def_key: id={:?}", id);
- let item_doc = cdata.lookup_item(id);
- item_def_key(item_doc)
-}
+ if multibytes1.len() != multibytes2.len() {
+ return false;
+ }
-fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey {
- match reader::maybe_get_doc(item_doc, tag_def_key) {
- Some(def_key_doc) => {
- let mut decoder = reader::Decoder::new(def_key_doc);
- let simple_key = def_key::DefKey::decode(&mut decoder).unwrap();
- let name = reader::maybe_get_doc(item_doc, tag_paths_data_name).map(|name| {
- token::intern(name.as_str_slice()).as_str()
- });
- def_key::recover_def_key(simple_key, name)
- }
- None => {
- bug!("failed to find block with tag {:?} for item with family {:?}",
- tag_def_key,
- item_family(item_doc))
+ for (mb1, mb2) in multibytes1.iter().zip(multibytes2.iter()) {
+ if (mb1.bytes != mb2.bytes) ||
+ ((mb1.pos - fm1.start_pos) != (mb2.pos - fm2.start_pos)) {
+ return false;
}
}
-}
-pub fn def_path(cdata: Cmd, id: DefIndex) -> hir_map::DefPath {
- debug!("def_path(id={:?})", id);
- hir_map::DefPath::make(cdata.cnum, id, |parent| def_key(cdata, parent))
-}
-
-pub fn get_panic_strategy(data: &[u8]) -> PanicStrategy {
- let crate_doc = rbml::Doc::new(data);
- let strat_doc = reader::get_doc(crate_doc, tag_panic_strategy);
- match reader::doc_as_u8(strat_doc) {
- b'U' => PanicStrategy::Unwind,
- b'A' => PanicStrategy::Abort,
- b => panic!("unknown panic strategy in metadata: {}", b),
- }
+ true
}