diff --git a/src/librustc/middle/cstore.rs b/src/librustc/middle/cstore.rs index 87fdc858cf0f..6324995f328b 100644 --- a/src/librustc/middle/cstore.rs +++ b/src/librustc/middle/cstore.rs @@ -188,7 +188,6 @@ pub trait CrateStore<'tcx> { fn is_compiler_builtins(&self, cnum: CrateNum) -> bool; fn panic_strategy(&self, cnum: CrateNum) -> PanicStrategy; fn extern_crate(&self, cnum: CrateNum) -> Option; - fn crate_attrs(&self, cnum: CrateNum) -> Vec; /// The name of the crate as it is referred to in source code of the current /// crate. fn crate_name(&self, cnum: CrateNum) -> InternedString; @@ -365,8 +364,6 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore { bug!("panic_strategy") } fn extern_crate(&self, cnum: CrateNum) -> Option { bug!("extern_crate") } - fn crate_attrs(&self, cnum: CrateNum) -> Vec - { bug!("crate_attrs") } fn crate_name(&self, cnum: CrateNum) -> InternedString { bug!("crate_name") } fn original_crate_name(&self, cnum: CrateNum) -> InternedString { bug!("original_crate_name") diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs index 518e66244121..f48c31fc2f9d 100644 --- a/src/librustc_metadata/astencode.rs +++ b/src/librustc_metadata/astencode.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_camel_case_types)] - use rustc::hir::map as ast_map; use rustc::hir::intravisit::{Visitor, IdRangeComputingVisitor, IdRange}; @@ -64,9 +62,7 @@ pub fn decode_inlined_item<'a, 'tcx>(cdata: &CrateMetadata, orig_did: DefId) -> &'tcx InlinedItem { debug!("> Decoding inlined fn: {:?}", tcx.item_path_str(orig_did)); - let dcx = &mut ast_doc.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); + let dcx = &mut DecodeContext::new(ast_doc, Some(cdata)).typed(tcx); dcx.from_id_range = IdRange::decode(dcx).unwrap(); let cnt = dcx.from_id_range.max.as_usize() - dcx.from_id_range.min.as_usize(); dcx.to_id_range.min = tcx.sess.reserve_node_ids(cnt); diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index 73dcf9470183..77a583f7379c 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -14,7 +14,6 @@ use common::CrateInfo; use cstore::{self, CStore, CrateSource, MetadataBlob}; -use decoder; use loader::{self, CratePaths}; use rustc::hir::def_id::{CrateNum, DefIndex}; @@ -28,6 +27,7 @@ use rustc::util::nodemap::{FnvHashMap, FnvHashSet}; use rustc::hir::map as hir_map; use std::cell::{RefCell, Cell}; +use std::ops::Deref; use std::path::PathBuf; use std::rc::Rc; use std::fs; @@ -143,11 +143,13 @@ enum PMDSource { Owned(loader::Library), } -impl PMDSource { - pub fn as_slice<'a>(&'a self) -> &'a [u8] { +impl Deref for PMDSource { + type Target = MetadataBlob; + + fn deref(&self) -> &MetadataBlob { match *self { - PMDSource::Registered(ref cmd) => cmd.data(), - PMDSource::Owned(ref lib) => lib.metadata.as_slice(), + PMDSource::Registered(ref cmd) => &cmd.data, + PMDSource::Owned(ref lib) => &lib.metadata } } } @@ -295,7 +297,7 @@ impl<'a> CrateReader<'a> { -> (CrateNum, Rc, cstore::CrateSource) { info!("register crate `extern crate {} as {}`", name, ident); - let crate_info = decoder::get_crate_info(lib.metadata.as_slice()); + let crate_info = lib.metadata.get_crate_info(); self.verify_no_symbol_conflicts(span, &crate_info); // Claim this crate number and cache it @@ -317,7 +319,7 @@ impl<'a> CrateReader<'a> { let loader::Library { dylib, rlib, metadata } = lib; - let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span); + let cnum_map = self.resolve_crate_deps(root, &metadata, cnum, span); if crate_info.macro_derive_registrar.is_some() { self.sess.span_err(span, "crates of the `rustc-macro` crate type \ @@ -328,8 +330,8 @@ impl<'a> CrateReader<'a> { name: name.to_string(), extern_crate: Cell::new(None), info: crate_info, - index: decoder::load_index(metadata.as_slice()), - key_map: decoder::load_key_map(metadata.as_slice()), + index: metadata.load_index(), + key_map: metadata.load_key_map(), data: metadata, cnum_map: RefCell::new(cnum_map), cnum: cnum, @@ -414,7 +416,7 @@ impl<'a> CrateReader<'a> { // Note that we only do this for target triple crates, though, as we // don't want to match a host crate against an equivalent target one // already loaded. - let crate_info = decoder::get_crate_info(library.metadata.as_slice()); + let crate_info = library.metadata.get_crate_info(); if loader.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { @@ -465,14 +467,14 @@ impl<'a> CrateReader<'a> { // Go through the crate metadata and load any crates that it references fn resolve_crate_deps(&mut self, root: &Option, - cdata: &[u8], + metadata: &MetadataBlob, krate: CrateNum, span: Span) -> cstore::CrateNumMap { debug!("resolving deps of external crate"); // The map from crate numbers in the crate we're resolving to local crate // numbers - let map: FnvHashMap<_, _> = decoder::get_crate_deps(cdata).iter().map(|dep| { + let map: FnvHashMap<_, _> = metadata.get_crate_deps().iter().map(|dep| { debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash); let (local_cnum, ..) = self.resolve_crate(root, &dep.name, @@ -566,7 +568,7 @@ impl<'a> CrateReader<'a> { let ci = self.extract_crate_info(item).unwrap(); let ekrate = self.read_extension_crate(item.span, &ci); - let crate_info = decoder::get_crate_info(ekrate.metadata.as_slice()); + let crate_info = ekrate.metadata.get_crate_info(); let source_name = format!("<{} macros>", item.ident); let mut ret = Macros { macro_rules: Vec::new(), @@ -574,8 +576,7 @@ impl<'a> CrateReader<'a> { svh: crate_info.hash, dylib: None, }; - decoder::each_exported_macro(ekrate.metadata.as_slice(), - |name, attrs, span, body| { + ekrate.metadata.each_exported_macro(|name, attrs, span, body| { // NB: Don't use parse::parse_tts_from_source_str because it parses with // quote_depth > 0. let mut p = parse::new_parser_from_source_str(&self.sess.parse_sess, @@ -670,7 +671,7 @@ impl<'a> CrateReader<'a> { span_fatal!(self.sess, span, E0456, "{}", &message[..]); } - let crate_info = decoder::get_crate_info(ekrate.metadata.as_slice()); + let crate_info = ekrate.metadata.get_crate_info(); match (ekrate.dylib.as_ref(), crate_info.plugin_registrar_fn) { (Some(dylib), Some(reg)) => { Some((dylib.to_path_buf(), crate_info.hash, reg)) @@ -1111,7 +1112,7 @@ pub fn read_local_crates(sess: & Session, pub fn import_codemap(local_codemap: &codemap::CodeMap, metadata: &MetadataBlob) -> Vec { - let external_codemap = decoder::get_imported_filemaps(metadata.as_slice()); + let external_codemap = metadata.get_imported_filemaps(); let imported_filemaps = external_codemap.into_iter().map(|filemap_to_import| { // Try to find an existing FileMap that can be reused for the filemap to diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs index f650155c0354..8136fc7e845f 100644 --- a/src/librustc_metadata/csearch.rs +++ b/src/librustc_metadata/csearch.rs @@ -10,7 +10,6 @@ use cstore; use common; -use decoder; use encoder; use loader; @@ -40,101 +39,87 @@ use rustc::hir; impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn stability(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_stability(&cdata, def.index) + self.get_crate_data(def.krate).get_stability(def.index) } fn deprecation(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_deprecation(&cdata, def.index) + self.get_crate_data(def.krate).get_deprecation(def.index) } fn visibility(&self, def: DefId) -> ty::Visibility { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_visibility(&cdata, def.index) + self.get_crate_data(def.krate).get_visibility(def.index) } fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind { assert!(!def_id.is_local()); self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::closure_kind(&cdata, def_id.index) + self.get_crate_data(def_id.krate).closure_kind(def_id.index) } fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx> { assert!(!def_id.is_local()); self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::closure_ty(&cdata, def_id.index, tcx) + self.get_crate_data(def_id.krate).closure_ty(def_id.index, tcx) } fn item_variances(&self, def: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_item_variances(&cdata, def.index) + self.get_crate_data(def.krate).get_item_variances(def.index) } fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Ty<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_type(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_type(def.index, tcx) } fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_predicates(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_predicates(def.index, tcx) } fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::GenericPredicates<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_super_predicates(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_super_predicates(def.index, tcx) } fn item_generics<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> &'tcx ty::Generics<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_generics(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_generics(def.index, tcx) } fn item_attrs(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::get_item_attrs(&cdata, def_id.index) + self.get_crate_data(def_id.krate).get_item_attrs(def_id.index) } fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_trait_def(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_trait_def(def.index, tcx) } fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_adt_def(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_adt_def(def.index, tcx) } fn fn_arg_names(&self, did: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::get_fn_arg_names(&cdata, did.index) + self.get_crate_data(did.krate).get_fn_arg_names(did.index) } fn opt_item_name(&self, def: DefId) -> Option { @@ -143,7 +128,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { if def.index == CRATE_DEF_INDEX { Some(token::intern(&cdata.name())) } else { - decoder::maybe_get_item_name(&cdata, def.index) + cdata.maybe_get_item_name(def.index) } } @@ -151,9 +136,8 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let cdata = self.get_crate_data(def_id.krate); - decoder::each_inherent_implementation_for_type(&cdata, def_id.index, - |iid| result.push(iid)); + self.get_crate_data(def_id.krate) + .each_inherent_implementation_for_type(def_id.index, |iid| result.push(iid)); result } @@ -164,7 +148,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { } let mut result = vec![]; self.iter_crate_data(|_, cdata| { - decoder::each_implementation_for_trait(cdata, filter, &mut |iid| { + cdata.each_implementation_for_trait(filter, &mut |iid| { result.push(iid) }) }); @@ -174,85 +158,74 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn impl_or_trait_items(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let crate_data = self.get_crate_data(def_id.krate); let get_crate_data = &mut |cnum| self.get_crate_data(cnum); - decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, - &mut |def, _, _| result.push(def.def_id())); + self.get_crate_data(def_id.krate) + .each_child_of_item(def_id.index, get_crate_data, + &mut |def, _, _| result.push(def.def_id())); result } fn impl_polarity(&self, def: DefId) -> hir::ImplPolarity { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_impl_polarity(&cdata, def.index) + self.get_crate_data(def.krate).get_impl_polarity(def.index) } fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_impl_trait(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_impl_trait(def.index, tcx) } fn custom_coerce_unsized_kind(&self, def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_custom_coerce_unsized_kind(&cdata, def.index) + self.get_crate_data(def.krate).get_custom_coerce_unsized_kind(def.index) } fn impl_parent(&self, impl_def: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(impl_def)); - let cdata = self.get_crate_data(impl_def.krate); - decoder::get_parent_impl(&*cdata, impl_def.index) + self.get_crate_data(impl_def.krate).get_parent_impl(impl_def.index) } fn trait_of_item(&self, def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(def_id)); - let cdata = self.get_crate_data(def_id.krate); - decoder::get_trait_of_item(&cdata, def_id.index) + self.get_crate_data(def_id.krate).get_trait_of_item(def_id.index) } fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_impl_or_trait_item(&cdata, def.index, tcx) + self.get_crate_data(def.krate).get_impl_or_trait_item(def.index, tcx) } fn is_const_fn(&self, did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::is_const_fn(&cdata, did.index) + self.get_crate_data(did.krate).is_const_fn(did.index) } fn is_defaulted_trait(&self, trait_def_id: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(trait_def_id)); - let cdata = self.get_crate_data(trait_def_id.krate); - decoder::is_defaulted_trait(&cdata, trait_def_id.index) + self.get_crate_data(trait_def_id.krate).is_defaulted_trait(trait_def_id.index) } fn is_default_impl(&self, impl_did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(impl_did)); - let cdata = self.get_crate_data(impl_did.krate); - decoder::is_default_impl(&cdata, impl_did.index) + self.get_crate_data(impl_did.krate).is_default_impl(impl_did.index) } fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(did)); - let cdata = self.get_crate_data(did.krate); - decoder::is_extern_item(&cdata, did.index, tcx) + self.get_crate_data(did.krate).is_extern_item(did.index, tcx) } fn is_foreign_item(&self, did: DefId) -> bool { - let cdata = self.get_crate_data(did.krate); - decoder::is_foreign_item(&cdata, did.index) + self.get_crate_data(did.krate).is_foreign_item(did.index) } fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool @@ -263,21 +236,18 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn dylib_dependency_formats(&self, cnum: CrateNum) -> Vec<(CrateNum, LinkagePreference)> { - let cdata = self.get_crate_data(cnum); - decoder::get_dylib_dependency_formats(&cdata) + self.get_crate_data(cnum).get_dylib_dependency_formats() } fn lang_items(&self, cnum: CrateNum) -> Vec<(DefIndex, usize)> { - let crate_data = self.get_crate_data(cnum); - decoder::get_lang_items(&crate_data) + self.get_crate_data(cnum).get_lang_items() } fn missing_lang_items(&self, cnum: CrateNum) -> Vec { - let cdata = self.get_crate_data(cnum); - decoder::get_missing_lang_items(&cdata) + self.get_crate_data(cnum).get_missing_lang_items() } fn is_staged_api(&self, cnum: CrateNum) -> bool @@ -308,11 +278,6 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { self.get_crate_data(cnum).panic_strategy() } - fn crate_attrs(&self, cnum: CrateNum) -> Vec - { - decoder::get_item_attrs(&self.get_crate_data(cnum), CRATE_DEF_INDEX) - } - fn crate_name(&self, cnum: CrateNum) -> token::InternedString { token::intern_and_get_ident(&self.get_crate_data(cnum).name[..]) @@ -348,18 +313,16 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn native_libraries(&self, cnum: CrateNum) -> Vec<(NativeLibraryKind, String)> { - let cdata = self.get_crate_data(cnum); - decoder::get_native_libraries(&cdata) + self.get_crate_data(cnum).get_native_libraries() } fn reachable_ids(&self, cnum: CrateNum) -> Vec { - let cdata = self.get_crate_data(cnum); - decoder::get_reachable_ids(&cdata) + self.get_crate_data(cnum).get_reachable_ids() } fn is_no_builtins(&self, cnum: CrateNum) -> bool { - attr::contains_name(&self.crate_attrs(cnum), "no_builtins") + self.get_crate_data(cnum).is_no_builtins() } fn def_index_for_def_key(&self, @@ -380,8 +343,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { // canonical name for an item. // // self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::def_key(&cdata, def.index) + self.get_crate_data(def.krate).def_key(def.index) } fn relative_def_path(&self, def: DefId) -> Option { @@ -389,34 +351,35 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { // commented out: // // self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::def_path(&cdata, def.index) + self.get_crate_data(def.krate).def_path(def.index) } fn struct_ctor_def_id(&self, struct_def_id: DefId) -> Option { self.dep_graph.read(DepNode::MetaData(struct_def_id)); - let cdata = self.get_crate_data(struct_def_id.krate); - decoder::get_struct_ctor_def_id(&cdata, struct_def_id.index) + self.get_crate_data(struct_def_id.krate).get_struct_ctor_def_id(struct_def_id.index) } fn struct_field_names(&self, def: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::get_struct_field_names(&cdata, def.index) + self.get_crate_data(def.krate).get_struct_field_names(def.index) } fn item_children(&self, def_id: DefId) -> Vec { self.dep_graph.read(DepNode::MetaData(def_id)); let mut result = vec![]; - let crate_data = self.get_crate_data(def_id.krate); let get_crate_data = &mut |cnum| self.get_crate_data(cnum); - decoder::each_child_of_item(&crate_data, def_id.index, get_crate_data, - &mut |def, name, vis| { - result.push(ChildItem { def: def, name: name, vis: vis }); - }); + self.get_crate_data(def_id.krate) + .each_child_of_item(def_id.index, get_crate_data, + &mut |def, name, vis| { + result.push(ChildItem { + def: def, + name: name, + vis: vis + }); + }); result } @@ -445,8 +408,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { debug!("maybe_get_item_ast({}): inlining item", tcx.item_path_str(def_id)); - let cdata = self.get_crate_data(def_id.krate); - let inlined = decoder::maybe_get_item_ast(&cdata, tcx, def_id.index); + let inlined = self.get_crate_data(def_id.krate).maybe_get_item_ast(tcx, def_id.index); let cache_inlined_item = |original_def_id, inlined_item_id, inlined_root_node_id| { let cache_entry = cstore::CachedInlinedItem { @@ -534,14 +496,12 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore { fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> Option> { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::maybe_get_item_mir(&cdata, tcx, def.index) + self.get_crate_data(def.krate).maybe_get_item_mir(tcx, def.index) } fn is_item_mir_available(&self, def: DefId) -> bool { self.dep_graph.read(DepNode::MetaData(def)); - let cdata = self.get_crate_data(def.krate); - decoder::is_item_mir_available(&cdata, def.index) + self.get_crate_data(def.krate).is_item_mir_available(def.index) } fn crates(&self) -> Vec diff --git a/src/librustc_metadata/cstore.rs b/src/librustc_metadata/cstore.rs index 44fdf29aa73c..4151f98b3dae 100644 --- a/src/librustc_metadata/cstore.rs +++ b/src/librustc_metadata/cstore.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![allow(non_camel_case_types)] - // The crate store - a central repo for information collected about external // crates and libraries @@ -17,7 +15,6 @@ pub use self::MetadataBlob::*; use common; use creader; -use decoder; use index; use loader; @@ -297,7 +294,6 @@ impl CStore { } impl CrateMetadata { - pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() } pub fn name(&self) -> &str { &self.info.name } pub fn hash(&self) -> Svh { self.info.hash } pub fn disambiguator(&self) -> &str { &self.info.disambiguator } @@ -317,37 +313,41 @@ impl CrateMetadata { } pub fn is_staged_api(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); - attrs.iter().any(|attr| { + self.get_item_attrs(CRATE_DEF_INDEX).iter().any(|attr| { attr.name() == "stable" || attr.name() == "unstable" }) } pub fn is_allocator(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "allocator") } pub fn needs_allocator(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "needs_allocator") } pub fn is_panic_runtime(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "panic_runtime") } pub fn needs_panic_runtime(&self) -> bool { - let attrs = decoder::get_item_attrs(self, CRATE_DEF_INDEX); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "needs_panic_runtime") } pub fn is_compiler_builtins(&self) -> bool { - let attrs = decoder::get_crate_attributes(self.data()); + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); attr::contains_name(&attrs, "compiler_builtins") } + pub fn is_no_builtins(&self) -> bool { + let attrs = self.get_item_attrs(CRATE_DEF_INDEX); + attr::contains_name(&attrs, "no_builtins") + } + pub fn panic_strategy(&self) -> PanicStrategy { self.info.panic_strategy.clone() } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index c665a7be955d..05bd9e97234e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -10,14 +10,11 @@ // Decoding metadata from a single crate's metadata -#![allow(non_camel_case_types)] - use astencode::decode_inlined_item; -use cstore::{self, CrateMetadata}; +use cstore::{CrateMetadata, MetadataBlob, NativeLibraryKind}; use common::*; use index; -use rustc::hir::def_id::CRATE_DEF_INDEX; use rustc::hir::svh::Svh; use rustc::hir::map as hir_map; use rustc::hir::map::{DefKey, DefPathData}; @@ -43,7 +40,6 @@ use std::rc::Rc; use std::str; use std::u32; -use rbml::reader; use rbml; use rustc_serialize::{Decodable, Decoder, SpecializedDecoder, opaque}; use syntax::attr; @@ -53,37 +49,36 @@ use syntax_pos::{self, Span, BytePos}; pub struct DecodeContext<'a, 'tcx: 'a> { pub opaque: opaque::Decoder<'a>, - pub tcx: Option>, - pub cdata: Option<&'a cstore::CrateMetadata>, + tcx: Option>, + cdata: Option<&'a CrateMetadata>, pub from_id_range: IdRange, pub to_id_range: IdRange, // Cache the last used filemap for translating spans as an optimization. last_filemap_index: usize, } -impl<'doc> rbml::Doc<'doc> { - pub fn decoder<'tcx>(self) -> DecodeContext<'doc, 'tcx> { +impl<'a, 'tcx> DecodeContext<'a, 'tcx> { + pub fn new(doc: rbml::Doc<'a>, cdata: Option<&'a CrateMetadata>) + -> 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.data, self.start), - cdata: None, + opaque: opaque::Decoder::new(doc.data, doc.start), + cdata: cdata, tcx: None, from_id_range: id_range, to_id_range: id_range, last_filemap_index: 0 } } -} -impl<'a, 'tcx> DecodeContext<'a, 'tcx> { pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx.expect("missing TyCtxt in DecodeContext") } - pub fn cdata(&self) -> &'a cstore::CrateMetadata { + pub fn cdata(&self) -> &'a CrateMetadata { self.cdata.expect("missing CrateMetadata in DecodeContext") } @@ -91,6 +86,11 @@ impl<'a, 'tcx> DecodeContext<'a, 'tcx> { T::decode(self).unwrap() } + pub fn typed(mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { + self.tcx = Some(tcx); + self + } + /// Iterate over the indices of a sequence. /// This will work solely because of `serialize::opaque`'s /// simple encoding of `n: usize` followed by `n` elements. @@ -295,126 +295,86 @@ impl<'a, 'tcx> SpecializedDecoder> for DecodeContext<'a, 'tcx> } } -pub type Cmd<'a> = &'a CrateMetadata; +#[derive(Clone)] +pub struct CrateDep { + pub cnum: CrateNum, + pub name: String, + pub hash: Svh, + pub explicitly_linked: bool, +} -impl CrateMetadata { - fn get_item(&self, item_id: DefIndex) -> Option { - self.index.lookup_item(self.data(), item_id).map(|pos| { - rbml::Doc::at(self.data(), pos as usize) +impl<'a, 'tcx> MetadataBlob { + fn root(&self) -> rbml::Doc { + rbml::Doc::new(self.as_slice()) + } + + fn child_at(&'a self, pos: usize, tag: usize) -> DecodeContext<'a, 'tcx> { + DecodeContext::new(rbml::Doc::at(self.as_slice(), pos).child(tag), None) + } + + fn get(&'a self, tag: usize) -> DecodeContext<'a, 'tcx> { + DecodeContext::new(self.root().child(tag), None) + } + + pub fn load_index(&self) -> index::Index { + index::Index::from_rbml(self.root().child(root_tag::index)) + } + + pub fn crate_rustc_version(&self) -> Option { + self.root().maybe_child(root_tag::rustc_version).map(|s| { + str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() }) } - 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 - } + // 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) -> FnvHashMap { + self.load_index().iter_enumerated(self.as_slice()).map(|(index, pos)| { + (self.child_at(pos as usize, item_tag::def_key).decode(), index) + }).collect() } - fn local_def_id(&self, index: DefIndex) -> DefId { - DefId { - krate: self.cnum, - index: index + pub fn get_crate_deps(&self) -> Vec { + let dcx = self.get(root_tag::crate_deps); + + dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { + CrateDep { + cnum: CrateNum::new(crate_num + 1), + name: name, + hash: hash, + explicitly_linked: explicitly_linked, + } + }).collect() + } + + pub fn get_crate_info(&self) -> CrateInfo { + self.get(root_tag::crate_info).decode() + } + + pub fn list_crate_metadata(&self, out: &mut io::Write) -> io::Result<()> { + write!(out, "=External Dependencies=\n")?; + for dep in &self.get_crate_deps() { + write!(out, "{} {}-{}\n", dep.cnum, dep.name, dep.hash)?; + } + write!(out, "\n")?; + Ok(()) + } + + pub fn get_imported_filemaps(&self) -> Vec { + self.get(root_tag::codemap).decode() + } + + pub fn each_exported_macro(&self, mut f: F) where + F: FnMut(ast::Name, Vec, Span, String) -> bool, + { + for (name, attrs, span, body) in self.get(root_tag::macro_defs).seq() { + if !f(name, attrs, span, body) { + break; + } } } } -pub fn load_index(data: &[u8]) -> index::Index { - index::Index::from_rbml(rbml::Doc::new(data).get(root_tag::index)) -} - -pub fn crate_rustc_version(data: &[u8]) -> Option { - let doc = rbml::Doc::new(data); - reader::maybe_get_doc(doc, root_tag::rustc_version).map(|s| { - str::from_utf8(&s.data[s.start..s.end]).unwrap().to_string() - }) -} - -// 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 { - load_index(data).iter_enumerated(data).map(|(index, pos)| { - // load def-key from item - let key = item_def_key(rbml::Doc::at(data, pos as usize)); - (key, index) - }).collect() -} - -fn item_family(item: rbml::Doc) -> Family { - item.get(item_tag::family).decoder().decode() -} - -fn item_visibility(item: rbml::Doc) -> ty::Visibility { - item.get(item_tag::visibility).decoder().decode() -} - -fn entry_data(doc: rbml::Doc, cdata: Cmd) -> EntryData { - let mut dcx = doc.get(item_tag::data).decoder(); - dcx.cdata = Some(cdata); - - dcx.decode() -} - -fn entry_typed_data<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) - -> EntryTypedData<'tcx> { - let mut dcx = doc.get(item_tag::typed_data).decoder(); - dcx.cdata = Some(cdata); - dcx.tcx = Some(tcx); - - dcx.decode() -} - -fn item_parent_item(cdata: Cmd, d: rbml::Doc) -> Option { - item_def_key(d).parent.map(|index| cdata.local_def_id(index)) -} - -fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> { - maybe_doc_type(doc, tcx, cdata).expect("missing item_tag::ty") -} - -fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) - -> Option> { - reader::maybe_get_doc(doc, item_tag::ty).map(|tp| { - let mut dcx = tp.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() - }) -} - -fn item_name(item: rbml::Doc) -> ast::Name { - maybe_item_name(item).expect("no item in item_name") -} - -fn maybe_item_name(item: rbml::Doc) -> Option { - let name = match item_def_key(item).disambiguated_data.data { - DefPathData::TypeNs(name) | - DefPathData::ValueNs(name) | - DefPathData::Module(name) | - DefPathData::MacroDef(name) | - DefPathData::TypeParam(name) | - DefPathData::LifetimeDef(name) | - DefPathData::EnumVariant(name) | - DefPathData::Field(name) | - DefPathData::Binding(name) => Some(name), - - DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - - DefPathData::CrateRoot | - DefPathData::Misc | - DefPathData::Impl | - DefPathData::ClosureExpr | - DefPathData::StructCtor | - DefPathData::Initializer | - DefPathData::ImplTrait => None - }; - - name.map(|s| token::intern(&s)) -} - impl Family { fn to_def(&self, did: DefId) -> Option { Some(match *self { @@ -444,729 +404,698 @@ impl Family { } } -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); +impl<'a, 'tcx> CrateMetadata { + fn maybe_get(&'a self, item: rbml::Doc<'a>, tag: usize) + -> Option> { + item.maybe_child(tag).map(|child| { + DecodeContext::new(child, Some(self)) + }) + } - let data = match entry_data(item_doc, cdata) { - EntryData::Trait(data) => data, - _ => bug!() - }; - let typed_data = match entry_typed_data(item_doc, tcx, cdata) { - EntryTypedData::Trait(data) => data, - _ => bug!() - }; + fn get(&'a self, item: rbml::Doc<'a>, tag: usize) -> DecodeContext<'a, 'tcx> { + match self.maybe_get(item, tag) { + Some(dcx) => dcx, + None => bug!("failed to find child with tag {}", tag) + } + } - ty::TraitDef::new(data.unsafety, data.paren_sugar, generics, typed_data.trait_ref, - def_path(cdata, item_id).unwrap().deterministic_hash(tcx))) -} + fn item_family(&self, item: rbml::Doc) -> Family { + self.get(item, item_tag::family).decode() + } -fn get_variant<'tcx>(cdata: Cmd, - item: rbml::Doc, - index: DefIndex) - -> (ty::VariantDefData<'tcx, 'tcx>, Option) { - let data = match entry_data(item, cdata) { - EntryData::Variant(data) => data, - _ => bug!() - }; + fn item_visibility(&self, item: rbml::Doc) -> ty::Visibility { + self.get(item, item_tag::visibility).decode() + } - let mut dcx = item.get(item_tag::children).decoder(); - dcx.cdata = Some(cdata); + fn item_def_key(&self, item: rbml::Doc) -> hir_map::DefKey { + self.get(item, item_tag::def_key).decode() + } - let fields = dcx.seq().map(|index| { - let f = cdata.lookup_item(index); - ty::FieldDefData::new(cdata.local_def_id(index), - item_name(f), - item_visibility(f)) - }).collect(); + fn item_name(&self, item: rbml::Doc) -> ast::Name { + self.maybe_item_name(item).expect("no item in item_name") + } - (ty::VariantDefData { - did: cdata.local_def_id(data.struct_ctor.unwrap_or(index)), - name: item_name(item), - fields: fields, - disr_val: ConstInt::Infer(data.disr), - kind: data.kind, - }, data.struct_ctor) -} + fn maybe_item_name(&self, item: rbml::Doc) -> Option { + let name = match self.item_def_key(item).disambiguated_data.data { + DefPathData::TypeNs(name) | + DefPathData::ValueNs(name) | + DefPathData::Module(name) | + DefPathData::MacroDef(name) | + DefPathData::TypeParam(name) | + DefPathData::LifetimeDef(name) | + DefPathData::EnumVariant(name) | + DefPathData::Field(name) | + DefPathData::Binding(name) => Some(name), -pub fn get_adt_def<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::AdtDefMaster<'tcx> -{ - let doc = cdata.lookup_item(item_id); - let did = cdata.local_def_id(item_id); - let mut ctor_index = None; - let family = item_family(doc); - let variants = if family == Family::Enum { - let mut dcx = doc.get(item_tag::children).decoder(); - dcx.cdata = Some(cdata); + DefPathData::InlinedRoot(_) => bug!("unexpected DefPathData"), - dcx.seq().map(|index| { - let (variant, struct_ctor) = get_variant(cdata, cdata.lookup_item(index), index); - assert_eq!(struct_ctor, None); - variant + DefPathData::CrateRoot | + DefPathData::Misc | + DefPathData::Impl | + DefPathData::ClosureExpr | + DefPathData::StructCtor | + DefPathData::Initializer | + DefPathData::ImplTrait => None + }; + + name.map(|s| token::intern(&s)) + } + + fn maybe_entry(&self, item_id: DefIndex) -> Option { + self.index.lookup_item(self.data.as_slice(), item_id).map(|pos| { + rbml::Doc::at(self.data.as_slice(), pos as usize) + }) + } + + fn entry(&self, item_id: DefIndex) -> rbml::Doc { + 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 + } + } + + fn local_def_id(&self, index: DefIndex) -> DefId { + DefId { + krate: self.cnum, + index: index + } + } + + fn entry_data(&self, doc: rbml::Doc) -> EntryData { + self.get(doc, item_tag::data).decode() + } + + fn entry_typed_data(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> EntryTypedData<'tcx> { + self.get(doc, item_tag::typed_data).typed(tcx).decode() + } + + fn item_parent_item(&self, d: rbml::Doc) -> Option { + self.item_def_key(d).parent.map(|index| self.local_def_id(index)) + } + + fn doc_type(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { + self.maybe_doc_type(doc, tcx).expect("missing item_tag::ty") + } + + fn maybe_doc_type(&self, doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option> { + self.maybe_get(doc, item_tag::ty).map(|dcx| dcx.typed(tcx).decode()) + } + + pub fn get_trait_def(&self, + item_id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx> { + let item_doc = self.entry(item_id); + let generics = self.doc_generics(item_doc, tcx); + + let data = match self.entry_data(item_doc) { + EntryData::Trait(data) => data, + _ => bug!() + }; + let typed_data = match self.entry_typed_data(item_doc, tcx) { + EntryTypedData::Trait(data) => data, + _ => bug!() + }; + + ty::TraitDef::new(data.unsafety, data.paren_sugar, generics, typed_data.trait_ref, + self.def_path(item_id).unwrap().deterministic_hash(tcx))) + } + + fn get_variant(&self, item: rbml::Doc, index: DefIndex) + -> (ty::VariantDefData<'tcx, 'tcx>, Option) { + let data = match self.entry_data(item) { + EntryData::Variant(data) => data, + _ => bug!() + }; + + let fields = self.get(item, item_tag::children).seq().map(|index| { + let f = self.entry(index); + ty::FieldDefData::new(self.local_def_id(index), + self.item_name(f), + self.item_visibility(f)) + }).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) + } + + pub fn get_adt_def(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::AdtDefMaster<'tcx> { + let doc = self.entry(item_id); + let did = self.local_def_id(item_id); + let mut ctor_index = None; + let family = self.item_family(doc); + let variants = if family == Family::Enum { + self.get(doc, item_tag::children).seq().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(doc, item_id); + ctor_index = struct_ctor; + vec![variant] + }; + let kind = match family { + Family::Enum => ty::AdtKind::Enum, + Family::Struct => ty::AdtKind::Struct, + Family::Union => ty::AdtKind::Union, + _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", + family, did) + }; + + 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); + } + + // 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); + } + } + + adt + } + + pub fn get_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::GenericPredicates<'tcx> { + self.doc_predicates(self.entry(item_id), tcx, item_tag::predicates) + } + + pub fn get_super_predicates(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::GenericPredicates<'tcx> { + self.doc_predicates(self.entry(item_id), tcx, item_tag::super_predicates) + } + + pub fn get_generics(&self, item_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::Generics<'tcx> { + self.doc_generics(self.entry(item_id), tcx) + } + + pub fn get_type(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> { + self.doc_type(self.entry(id), tcx) + } + + pub fn get_stability(&self, id: DefIndex) -> Option { + self.maybe_get(self.entry(id), item_tag::stability).map(|mut dcx| { + dcx.decode() + }) + } + + pub fn get_deprecation(&self, id: DefIndex) -> Option { + self.maybe_get(self.entry(id), item_tag::deprecation).map(|mut dcx| { + dcx.decode() + }) + } + + pub fn get_visibility(&self, id: DefIndex) -> ty::Visibility { + self.item_visibility(self.entry(id)) + } + + fn get_impl_data(&self, id: DefIndex) -> ImplData { + match self.entry_data(self.entry(id)) { + EntryData::Impl(data) => data, + _ => bug!() + } + } + + pub fn get_parent_impl(&self, id: DefIndex) -> Option { + self.get_impl_data(id).parent_impl + } + + pub fn get_impl_polarity(&self, id: DefIndex) -> hir::ImplPolarity { + self.get_impl_data(id).polarity + } + + pub fn get_custom_coerce_unsized_kind(&self, id: DefIndex) + -> Option { + self.get_impl_data(id).coerce_unsized_kind + } + + pub fn get_impl_trait(&self, + id: DefIndex, + tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> Option> { + match self.entry_typed_data(self.entry(id), tcx) { + EntryTypedData::Impl(data) => data.trait_ref, + _ => bug!() + } + } + + /// Iterates over the language items in the given crate. + pub fn get_lang_items(&self) -> Vec<(DefIndex, usize)> { + self.get(self.data.root(), root_tag::lang_items).decode() + } + + /// Iterates over each child of the given item. + pub fn each_child_of_item(&self, id: DefIndex, + mut get_crate_data: &mut G, + mut callback: &mut F) + where F: FnMut(Def, ast::Name, ty::Visibility), + G: FnMut(CrateNum) -> Rc, + { + // Find the item. + let item_doc = match self.maybe_entry(id) { + None => return, + Some(item_doc) => item_doc, + }; + + let dcx = match self.maybe_get(item_doc, item_tag::children) { + Some(dcx) => dcx, + None => return + }; + + // Iterate over all children. + for child_index in dcx.seq::() { + // Get the item. + if let Some(child) = self.maybe_entry(child_index) { + // Hand off the item to the callback. + let family = self.item_family(child); + if let Family::ForeignMod = family { + self.each_child_of_item(child_index, get_crate_data, callback); + } else if let Some(def) = family.to_def(self.local_def_id(child_index)) { + callback(def, self.item_name(child), self.item_visibility(child)); + } + } + } + + let reexports = match self.entry_data(item_doc) { + EntryData::Mod(data) => data.reexports, + _ => return + }; + for exp in reexports { + // This reexport may be in yet another crate. + let crate_data = if exp.def_id.krate == self.cnum { + None + } else { + Some(get_crate_data(exp.def_id.krate)) + }; + let crate_data = match crate_data { + Some(ref cdata) => &**cdata, + None => self + }; + + // Get the item. + if let Some(child) = crate_data.maybe_entry(exp.def_id.index) { + // Hand off the item to the callback. + if let Some(def) = self.item_family(child).to_def(exp.def_id) { + // These items have a public visibility because they're part of + // a public re-export. + callback(def, exp.name, ty::Visibility::Public); + } + } + } + } + + pub fn maybe_get_item_name(&self, id: DefIndex) -> Option { + self.maybe_item_name(self.entry(id)) + } + + 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.maybe_child(item_tag::ast).map(|ast_doc| { + decode_inlined_item(self, tcx, parent_def_path, parent_def_id, ast_doc, item_did) + }) + } + + pub fn is_item_mir_available(&self, id: DefIndex) -> bool { + if let Some(item_doc) = self.maybe_entry(id) { + return item_doc.maybe_child(item_tag::mir).is_some(); + } + + false + } + + pub fn maybe_get_item_mir(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) + -> Option> { + self.maybe_get(self.entry(id), item_tag::mir).map(|dcx| { + dcx.typed(tcx).decode() + }) + } + + pub fn get_impl_or_trait_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> Option> { + let item_doc = self.entry(id); + let family = self.item_family(item_doc); + + match family { + Family::AssociatedConst | + Family::Method | + Family::AssociatedType => {} + + _ => return None + } + + let def_id = self.local_def_id(id); + + let container_id = self.item_parent_item(item_doc).unwrap(); + let container = match self.item_family(self.entry(container_id.index)) { + Family::Trait => TraitContainer(container_id), + _ => ImplContainer(container_id), + }; + + let name = self.item_name(item_doc); + let vis = self.item_visibility(item_doc); + + let (defaultness, has_body) = match self.entry_data(item_doc) { + EntryData::TraitAssociated(data) => { + (hir::Defaultness::Default, data.has_default) + } + EntryData::ImplAssociated(data) => { + (data.defaultness, true) + } + _ => bug!() + }; + + Some(match family { + Family::AssociatedConst => { + ty::ConstTraitItem(Rc::new(ty::AssociatedConst { + name: name, + ty: self.doc_type(item_doc, tcx), + vis: vis, + defaultness: defaultness, + def_id: def_id, + container: container, + has_value: has_body, + })) + } + Family::Method => { + let generics = self.doc_generics(item_doc, tcx); + let predicates = self.doc_predicates(item_doc, tcx, item_tag::predicates); + 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 = match self.entry_typed_data(item_doc, tcx) { + EntryTypedData::Method(data) => data.explicit_self, + _ => bug!() + }; + ty::MethodTraitItem(Rc::new(ty::Method { + name: name, + generics: generics, + predicates: predicates, + fty: fty, + explicit_self: explicit_self, + vis: vis, + defaultness: defaultness, + has_body: has_body, + def_id: def_id, + container: container, + })) + } + Family::AssociatedType => { + ty::TypeTraitItem(Rc::new(ty::AssociatedType { + name: name, + ty: self.maybe_doc_type(item_doc, tcx), + vis: vis, + defaultness: defaultness, + def_id: def_id, + container: container, + })) + } + _ => bug!() + }) + } + + pub fn get_item_variances(&self, id: DefIndex) -> Vec { + let item_doc = self.entry(id); + self.get(item_doc, item_tag::variances).decode() + } + + pub fn get_struct_ctor_def_id(&self, node_id: DefIndex) -> Option { + let data = match self.entry_data(self.entry(node_id)) { + EntryData::Variant(data) => data, + _ => bug!() + }; + + data.struct_ctor.map(|index| self.local_def_id(index)) + } + + pub fn get_item_attrs(&self, node_id: DefIndex) -> Vec { + // 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 = self.item_def_key(item); + if def_key.disambiguated_data.data == DefPathData::StructCtor { + item = self.entry(def_key.parent.unwrap()); + } + self.get_attributes(item) + } + + pub fn get_struct_field_names(&self, id: DefIndex) -> Vec { + self.get(self.entry(id), item_tag::children).seq().map(|index| { + self.item_name(self.entry(index)) }).collect() - } else{ - let (variant, struct_ctor) = get_variant(cdata, doc, item_id); - ctor_index = struct_ctor; - vec![variant] - }; - let kind = match family { - Family::Enum => ty::AdtKind::Enum, - Family::Struct => ty::AdtKind::Struct, - Family::Union => ty::AdtKind::Union, - _ => bug!("get_adt_def called on a non-ADT {:?} - {:?}", - family, did) - }; - - 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(cdata.local_def_id(ctor_index), adt); } - // 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 = get_type(cdata, field.did.index, tcx); - field.fulfill_ty(ty); - debug!("evaluating the type of {:?}::{:?}: {:?}", - variant.name, field.name, ty); - } - } + fn get_attributes(&self, md: rbml::Doc) -> Vec { + self.maybe_get(md, item_tag::attributes).map_or(vec![], |mut dcx| { + let mut attrs = dcx.decode::>(); - 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, item_tag::predicates) -} - -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, item_tag::super_predicates) -} - -pub fn get_generics<'a, 'tcx>(cdata: Cmd, - item_id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> &'tcx ty::Generics<'tcx> -{ - let item_doc = cdata.lookup_item(item_id); - doc_generics(item_doc, tcx, cdata) -} - -pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Ty<'tcx> -{ - let item_doc = cdata.lookup_item(id); - doc_type(item_doc, tcx, cdata) -} - -pub fn get_stability(cdata: Cmd, id: DefIndex) -> Option { - let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, item_tag::stability).map(|doc| { - doc.decoder().decode() - }) -} - -pub fn get_deprecation(cdata: Cmd, id: DefIndex) -> Option { - let item = cdata.lookup_item(id); - reader::maybe_get_doc(item, item_tag::deprecation).map(|doc| { - doc.decoder().decode() - }) -} - -pub fn get_visibility(cdata: Cmd, id: DefIndex) -> ty::Visibility { - item_visibility(cdata.lookup_item(id)) -} - -fn get_impl_data(cdata: Cmd, id: DefIndex) -> ImplData { - match entry_data(cdata.lookup_item(id), cdata) { - EntryData::Impl(data) => data, - _ => bug!() - } -} - -pub fn get_parent_impl(cdata: Cmd, id: DefIndex) -> Option { - get_impl_data(cdata, id).parent_impl -} - -pub fn get_impl_polarity(cdata: Cmd, id: DefIndex) -> hir::ImplPolarity { - get_impl_data(cdata, id).polarity -} - -pub fn get_custom_coerce_unsized_kind( - cdata: Cmd, - id: DefIndex) - -> Option -{ - get_impl_data(cdata, id).coerce_unsized_kind -} - -pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd, - id: DefIndex, - tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option> -{ - match entry_typed_data(cdata.lookup_item(id), tcx, cdata) { - EntryTypedData::Impl(data) => data.trait_ref, - _ => bug!() - } -} - -/// Iterates over the language items in the given crate. -pub fn get_lang_items(cdata: Cmd) -> Vec<(DefIndex, usize)> { - rbml::Doc::new(cdata.data()).get(root_tag::lang_items).decoder().decode() -} - - -/// Iterates over each child of the given item. -pub fn each_child_of_item(cdata: Cmd, id: DefIndex, - mut get_crate_data: &mut G, - mut callback: &mut F) - where F: FnMut(Def, ast::Name, ty::Visibility), - G: FnMut(CrateNum) -> Rc, -{ - // Find the item. - let item_doc = match cdata.get_item(id) { - None => return, - Some(item_doc) => item_doc, - }; - - let mut dcx = match reader::maybe_get_doc(item_doc, item_tag::children) { - Some(doc) => doc.decoder(), - None => return - }; - dcx.cdata = Some(cdata); - - // Iterate over all children. - for child_index in dcx.seq::() { - // Get the item. - if let Some(child) = cdata.get_item(child_index) { - // Hand off the item to the callback. - let family = item_family(child); - if let Family::ForeignMod = family { - each_child_of_item(cdata, child_index, get_crate_data, callback); - } else if let Some(def) = family.to_def(cdata.local_def_id(child_index)) { - callback(def, item_name(child), item_visibility(child)); + // Need new unique IDs: old thread-local IDs won't map to new threads. + for attr in attrs.iter_mut() { + attr.node.id = attr::mk_attr_id(); } - } + + attrs + }) } - let reexports = match entry_data(item_doc, cdata) { - EntryData::Mod(data) => data.reexports, - _ => return - }; - for exp in reexports { - // This reexport may be in yet another crate. - let crate_data = if exp.def_id.krate == cdata.cnum { - None - } else { - Some(get_crate_data(exp.def_id.krate)) - }; - let crate_data = match crate_data { - Some(ref cdata) => &**cdata, - None => cdata - }; - - // Get the item. - if let Some(child) = crate_data.get_item(exp.def_id.index) { - // Hand off the item to the callback. - if let Some(def) = item_family(child).to_def(exp.def_id) { - // These items have a public visibility because they're part of - // a public re-export. - callback(def, exp.name, ty::Visibility::Public); - } - } - } -} - -pub fn maybe_get_item_name(cdata: Cmd, id: DefIndex) -> Option { - maybe_item_name(cdata.lookup_item(id)) -} - -pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex) - -> Option<&'tcx InlinedItem> { - debug!("Looking up item: {:?}", id); - let item_doc = cdata.lookup_item(id); - let item_did = cdata.local_def_id(id); - let parent_def_id = cdata.local_def_id(def_key(cdata, id).parent.unwrap()); - let mut parent_def_path = def_path(cdata, id).unwrap(); - parent_def_path.data.pop(); - reader::maybe_get_doc(item_doc, item_tag::ast).map(|ast_doc| { - decode_inlined_item(cdata, tcx, parent_def_path, parent_def_id, ast_doc, item_did) - }) -} - -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, item_tag::mir as usize).is_some(); - } - - false -} - -pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - id: DefIndex) - -> Option> { - let item_doc = cdata.lookup_item(id); - - reader::maybe_get_doc(item_doc, item_tag::mir).map(|mir_doc| { - let mut dcx = mir_doc.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() - }) -} - -pub fn get_impl_or_trait_item<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> Option> { - let item_doc = cdata.lookup_item(id); - let family = item_family(item_doc); - - match family { - Family::AssociatedConst | - Family::Method | - Family::AssociatedType => {} - - _ => return None - } - - let def_id = cdata.local_def_id(id); - - let container_id = item_parent_item(cdata, item_doc).unwrap(); - let container = match item_family(cdata.lookup_item(container_id.index)) { - Family::Trait => TraitContainer(container_id), - _ => ImplContainer(container_id), - }; - - let name = item_name(item_doc); - let vis = item_visibility(item_doc); - - let (defaultness, has_body) = match entry_data(item_doc, cdata) { - EntryData::TraitAssociated(data) => { - (hir::Defaultness::Default, data.has_default) - } - EntryData::ImplAssociated(data) => { - (data.defaultness, true) - } - _ => bug!() - }; - - Some(match family { - Family::AssociatedConst => { - 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: has_body, - })) - } - Family::Method => { - let generics = doc_generics(item_doc, tcx, cdata); - let predicates = doc_predicates(item_doc, tcx, cdata, item_tag::predicates); - 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 = match entry_typed_data(item_doc, tcx, cdata) { - EntryTypedData::Method(data) => data.explicit_self, - _ => bug!() - }; - ty::MethodTraitItem(Rc::new(ty::Method { - name: name, - generics: generics, - predicates: predicates, - fty: fty, - explicit_self: explicit_self, - vis: vis, - defaultness: defaultness, - has_body: has_body, - def_id: def_id, - container: container, - })) - } - Family::AssociatedType => { - 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, - })) - } - _ => bug!() - }) -} - -pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> Vec { - let item_doc = cdata.lookup_item(id); - item_doc.get(item_tag::variances).decoder().decode() -} - -pub fn get_struct_ctor_def_id(cdata: Cmd, node_id: DefIndex) -> Option -{ - let data = match entry_data(cdata.lookup_item(node_id), cdata) { - EntryData::Variant(data) => data, - _ => bug!() - }; - - data.struct_ctor.map(|index| cdata.local_def_id(index)) -} - -pub fn get_item_attrs(cdata: Cmd, - node_id: DefIndex) - -> Vec { - // 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 = cdata.lookup_item(node_id); - let def_key = item_def_key(item); - if def_key.disambiguated_data.data == DefPathData::StructCtor { - item = cdata.lookup_item(def_key.parent.unwrap()); - } - get_attributes(item) -} - -pub fn get_struct_field_names(cdata: Cmd, id: DefIndex) -> Vec { - let mut dcx = cdata.lookup_item(id).get(item_tag::children).decoder(); - dcx.cdata = Some(cdata); - - dcx.seq().map(|index| item_name(cdata.lookup_item(index))).collect() -} - -fn get_attributes(md: rbml::Doc) -> Vec { - reader::maybe_get_doc(md, item_tag::attributes).map_or(vec![], |attrs_doc| { - let mut attrs = attrs_doc.decoder().decode::>(); - - // Need new unique IDs: old thread-local IDs won't map to new threads. - for attr in attrs.iter_mut() { - attr.node.id = attr::mk_attr_id(); - } - - attrs - }) -} - -#[derive(Clone)] -pub struct CrateDep { - pub cnum: CrateNum, - pub name: String, - pub hash: Svh, - pub explicitly_linked: bool, -} - -pub fn get_crate_deps(data: &[u8]) -> Vec { - let dcx = rbml::Doc::new(data).get(root_tag::crate_deps).decoder(); - - dcx.seq().enumerate().map(|(crate_num, (name, hash, explicitly_linked))| { - CrateDep { - cnum: CrateNum::new(crate_num + 1), - name: name, - hash: hash, - explicitly_linked: explicitly_linked, - } - }).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)?; - } - write!(out, "\n")?; - Ok(()) -} - -pub fn get_crate_info(data: &[u8]) -> CrateInfo { - rbml::Doc::new(data).get(root_tag::crate_info).decoder().decode() -} - -pub fn list_crate_metadata(bytes: &[u8], out: &mut io::Write) -> io::Result<()> { - list_crate_deps(bytes, out) -} - -// 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 { - for (local, &global) in cdata.cnum_map.borrow().iter_enumerated() { - if global == did.krate { - return Some(DefId { krate: local, index: did.index }); - } - } - - None -} - -pub fn each_inherent_implementation_for_type(cdata: Cmd, - id: DefIndex, - mut callback: F) - where F: FnMut(DefId), -{ - let item_doc = cdata.lookup_item(id); - let mut dcx = item_doc.get(item_tag::inherent_impls).decoder(); - dcx.cdata = Some(cdata); - - for impl_def_id in dcx.seq() { - callback(impl_def_id); - } -} - -pub fn each_implementation_for_trait(cdata: Cmd, - filter: Option, - mut callback: F) where - F: FnMut(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| reverse_translate_def_id(cdata, def_id)) { - Some(Some(def_id)) => Some(def_id), - Some(None) => return, - None => None - }; - - // FIXME(eddyb) Make this O(1) instead of O(n). - for trait_doc in rbml::Doc::new(cdata.data()).get(root_tag::impls).children() { - let mut dcx = trait_doc.decoder(); - dcx.cdata = Some(cdata); - - let (krate, index) = dcx.decode(); - if let Some(local_did) = filter { - if (local_did.krate.as_u32(), local_did.index) != (krate, index) { - continue; + // Translate a DefId from the current compilation environment to a DefId + // for an external crate. + fn reverse_translate_def_id(&self, did: DefId) -> Option { + for (local, &global) in self.cnum_map.borrow().iter_enumerated() { + if global == did.krate { + return Some(DefId { krate: local, index: did.index }); } } - for impl_def_id in dcx.seq() { + None + } + + pub fn each_inherent_implementation_for_type(&self, id: DefIndex, mut callback: F) + where F: FnMut(DefId), + { + for impl_def_id in self.get(self.entry(id), item_tag::inherent_impls).seq() { callback(impl_def_id); } } -} -pub fn get_trait_of_item(cdata: Cmd, id: DefIndex) -> Option { - 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, - }; - match item_family(cdata.lookup_item(parent_item_id.index)) { - Family::Trait => Some(parent_item_id), - _ => None - } -} + pub fn each_implementation_for_trait(&self, + filter: Option, + mut callback: F) where + F: FnMut(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), + Some(None) => return, + None => None + }; + // FIXME(eddyb) Make this O(1) instead of O(n). + for trait_doc in self.data.root().children_of(root_tag::impls) { + let mut dcx = DecodeContext::new(trait_doc, Some(self)); -pub fn get_native_libraries(cdata: Cmd) - -> Vec<(cstore::NativeLibraryKind, String)> { - rbml::Doc::new(cdata.data()).get(root_tag::native_libraries).decoder().decode() -} - -pub fn each_exported_macro(data: &[u8], mut f: F) where - F: FnMut(ast::Name, Vec, Span, String) -> bool, -{ - let dcx = rbml::Doc::new(data).get(root_tag::macro_defs).decoder(); - for (name, attrs, span, body) in dcx.seq() { - if !f(name, attrs, span, body) { - break; - } - } -} - -pub fn get_dylib_dependency_formats(cdata: Cmd) - -> Vec<(CrateNum, LinkagePreference)> -{ - let dcx = rbml::Doc::new(cdata.data()).get(root_tag::dylib_dependency_formats).decoder(); - - dcx.seq::>().enumerate().flat_map(|(i, link)| { - let cnum = CrateNum::new(i + 1); - link.map(|link| (cdata.cnum_map.borrow()[cnum], link)) - }).collect() -} - -pub fn get_missing_lang_items(cdata: Cmd) -> Vec { - rbml::Doc::new(cdata.data()).get(root_tag::lang_items_missing).decoder().decode() -} - -pub fn get_fn_arg_names(cdata: Cmd, id: DefIndex) -> Vec { - let method_doc = cdata.lookup_item(id); - match reader::maybe_get_doc(method_doc, item_tag::fn_arg_names) { - Some(args_doc) => args_doc.decoder().decode(), - None => vec![], - } -} - -pub fn get_reachable_ids(cdata: Cmd) -> Vec { - let dcx = rbml::Doc::new(cdata.data()).get(root_tag::reachable_ids).decoder(); - - dcx.seq().map(|index| cdata.local_def_id(index)).collect() -} - -pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool { - let constness = match entry_data(cdata.lookup_item(id), cdata) { - EntryData::ImplAssociated(data) => data.constness, - EntryData::Fn(data) => data.constness, - _ => hir::Constness::NotConst - }; - constness == hir::Constness::Const -} - -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) { - Family::ImmStatic | - Family::MutStatic | - Family::ForeignImmStatic | - Family::ForeignMutStatic => true, - - Family::Fn | Family::ForeignFn => { - get_generics(cdata, id, tcx).types.is_empty() - } - - _ => false, - }; - - if applicable { - attr::contains_extern_indicator(tcx.sess.diagnostic(), - &get_attributes(item_doc)) - } else { - false - } -} - -pub fn is_foreign_item(cdata: Cmd, id: DefIndex) -> bool { - match item_family(cdata.lookup_item(id)) { - Family::ForeignImmStatic | - Family::ForeignMutStatic | - Family::ForeignFn => true, - _ => false - } -} - -fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: Cmd) - -> &'tcx ty::Generics<'tcx> -{ - let mut dcx = base_doc.get(item_tag::generics).decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - tcx.alloc_generics(dcx.decode()) -} - -fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc, - tcx: TyCtxt<'a, 'tcx, 'tcx>, - cdata: Cmd, - tag: usize) - -> ty::GenericPredicates<'tcx> -{ - let mut dcx = base_doc.get(tag).decoder(); - dcx.cdata = Some(cdata); - dcx.tcx = Some(tcx); - - ty::GenericPredicates { - parent: dcx.decode(), - predicates: (0..dcx.decode::()).map(|_| { - // Handle shorthands first, if we have an usize > 0x80. - if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 { - let pos = dcx.decode::(); - assert!(pos >= SHORTHAND_OFFSET); - let pos = pos - SHORTHAND_OFFSET; - - let mut dcx = rbml::Doc { - data: cdata.data(), - start: pos, - end: cdata.data().len(), - }.decoder(); - dcx.tcx = Some(tcx); - dcx.cdata = Some(cdata); - dcx.decode() - } else { - dcx.decode() + let (krate, index) = dcx.decode(); + if let Some(local_did) = filter { + if (local_did.krate.as_u32(), local_did.index) != (krate, index) { + continue; + } } + + for impl_def_id in dcx.seq() { + callback(impl_def_id); + } + } + } + + pub fn get_trait_of_item(&self, id: DefIndex) -> Option { + let item_doc = self.entry(id); + let parent_item_id = match self.item_parent_item(item_doc) { + None => return None, + Some(item_id) => item_id, + }; + match self.item_family(self.entry(parent_item_id.index)) { + Family::Trait => Some(parent_item_id), + _ => None + } + } + + + pub fn get_native_libraries(&self) -> Vec<(NativeLibraryKind, String)> { + self.get(self.data.root(), root_tag::native_libraries).decode() + } + + pub fn get_dylib_dependency_formats(&self) -> Vec<(CrateNum, LinkagePreference)> { + let dcx = self.get(self.data.root(), root_tag::dylib_dependency_formats); + + dcx.seq::>().enumerate().flat_map(|(i, link)| { + let cnum = CrateNum::new(i + 1); + link.map(|link| (self.cnum_map.borrow()[cnum], link)) }).collect() } -} -pub fn is_defaulted_trait(cdata: Cmd, trait_id: DefIndex) -> bool { - match entry_data(cdata.lookup_item(trait_id), cdata) { - EntryData::Trait(data) => data.has_default_impl, - _ => bug!() - } -} - -pub fn is_default_impl(cdata: Cmd, impl_id: DefIndex) -> bool { - item_family(cdata.lookup_item(impl_id)) == Family::DefaultImpl -} - -pub fn get_imported_filemaps(metadata: &[u8]) -> Vec { - rbml::Doc::new(metadata).get(root_tag::codemap).decoder().decode() -} - -pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind { - match entry_data(cdata.lookup_item(closure_id), cdata) { - EntryData::Closure(data) => data.kind, - _ => bug!() - } -} - -pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) - -> ty::ClosureTy<'tcx> { - match entry_typed_data(cdata.lookup_item(closure_id), tcx, cdata) { - EntryTypedData::Closure(data) => data.ty, - _ => bug!() - } -} - -pub fn def_key(cdata: Cmd, id: DefIndex) -> hir_map::DefKey { - debug!("def_key: id={:?}", id); - item_def_key(cdata.lookup_item(id)) -} - -fn item_def_key(item_doc: rbml::Doc) -> hir_map::DefKey { - item_doc.get(item_tag::def_key).decoder().decode() -} - -// 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(cdata: Cmd, id: DefIndex) -> Option { - debug!("def_path(id={:?})", id); - if cdata.get_item(id).is_some() { - Some(hir_map::DefPath::make(cdata.cnum, id, |parent| def_key(cdata, parent))) - } else { - None + pub fn get_missing_lang_items(&self) -> Vec { + self.get(self.data.root(), root_tag::lang_items_missing).decode() + } + + pub fn get_fn_arg_names(&self, id: DefIndex) -> Vec { + self.maybe_get(self.entry(id), item_tag::fn_arg_names) + .map_or(vec![], |mut dcx| dcx.decode()) + } + + pub fn get_reachable_ids(&self) -> Vec { + let dcx = self.get(self.data.root(), root_tag::reachable_ids); + + dcx.seq().map(|index| self.local_def_id(index)).collect() + } + + pub fn is_const_fn(&self, id: DefIndex) -> bool { + let constness = match self.entry_data(self.entry(id)) { + EntryData::ImplAssociated(data) => data.constness, + EntryData::Fn(data) => data.constness, + _ => hir::Constness::NotConst + }; + constness == hir::Constness::Const + } + + pub fn is_extern_item(&self, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool { + let item_doc = match self.maybe_entry(id) { + Some(doc) => doc, + None => return false, + }; + let applicable = match self.item_family(item_doc) { + Family::ImmStatic | + Family::MutStatic | + Family::ForeignImmStatic | + Family::ForeignMutStatic => true, + + Family::Fn | Family::ForeignFn => { + self.get_generics(id, tcx).types.is_empty() + } + + _ => false, + }; + + if applicable { + attr::contains_extern_indicator(tcx.sess.diagnostic(), + &self.get_attributes(item_doc)) + } else { + false + } + } + + pub fn is_foreign_item(&self, id: DefIndex) -> bool { + match self.item_family(self.entry(id)) { + Family::ForeignImmStatic | + Family::ForeignMutStatic | + Family::ForeignFn => true, + _ => false + } + } + + fn doc_generics(&self, base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> &'tcx ty::Generics<'tcx> { + let generics = self.get(base_doc, item_tag::generics).typed(tcx).decode(); + tcx.alloc_generics(generics) + } + + fn doc_predicates(&self, base_doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, tag: usize) + -> ty::GenericPredicates<'tcx> { + let mut dcx = self.get(base_doc, tag).typed(tcx); + + ty::GenericPredicates { + parent: dcx.decode(), + predicates: (0..dcx.decode::()).map(|_| { + // Handle shorthands first, if we have an usize > 0x80. + if dcx.opaque.data[dcx.opaque.position()] & 0x80 != 0 { + let pos = dcx.decode::(); + assert!(pos >= SHORTHAND_OFFSET); + let pos = pos - SHORTHAND_OFFSET; + + let data = self.data.as_slice(); + let doc = rbml::Doc { + data: data, + start: pos, + end: data.len(), + }; + DecodeContext::new(doc, Some(self)).typed(tcx).decode() + } else { + dcx.decode() + } + }).collect() + } + } + + pub fn is_defaulted_trait(&self, trait_id: DefIndex) -> bool { + match self.entry_data(self.entry(trait_id)) { + EntryData::Trait(data) => data.has_default_impl, + _ => bug!() + } + } + + pub fn is_default_impl(&self, impl_id: DefIndex) -> bool { + self.item_family(self.entry(impl_id)) == Family::DefaultImpl + } + + pub fn closure_kind(&self, closure_id: DefIndex) -> ty::ClosureKind { + match self.entry_data(self.entry(closure_id)) { + EntryData::Closure(data) => data.kind, + _ => bug!() + } + } + + pub fn closure_ty(&self, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>) + -> ty::ClosureTy<'tcx> { + match self.entry_typed_data(self.entry(closure_id), tcx) { + EntryTypedData::Closure(data) => data.ty, + _ => bug!() + } + } + + pub fn def_key(&self, id: DefIndex) -> hir_map::DefKey { + debug!("def_key: id={:?}", id); + self.item_def_key(self.entry(id)) + } + + // 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 { + 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 + } } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 637228725e0b..e345129b327e 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -11,7 +11,6 @@ // Metadata encoding #![allow(unused_must_use)] // everything is just a MemWriter, can't fail -#![allow(non_camel_case_types)] use astencode::encode_inlined_item; use common::*; @@ -226,9 +225,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { struct_ctor: struct_ctor }) } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { /// 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 @@ -249,8 +246,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_visibility(enum_vis); let attrs = tcx.get_attrs(vid); - encode_attributes(self, &attrs); - encode_stability(self, vid); + self.encode_attributes(&attrs); + self.encode_stability(vid); let data = self.encode_variant(variant, None); @@ -264,9 +261,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_bounds_and_type_for_item(vid); } -} -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_mod(&mut self, FromId(id, (md, attrs, vis)): FromId<(&hir::Mod, &[ast::Attribute], &hir::Visibility)>) { @@ -276,8 +271,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_def_key(def_id); self.encode_family(Family::Mod); self.encode_visibility(vis); - encode_stability(self, def_id); - encode_attributes(self, attrs); + self.encode_stability(def_id); + self.encode_attributes(attrs); debug!("(encoding info for module) encoding info for module ID {}", id); // Encode info about all the module children. @@ -371,8 +366,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let variant_id = tcx.map.as_local_node_id(variant.did).unwrap(); let variant_data = tcx.map.expect_variant_data(variant_id); - encode_attributes(self, &variant_data.fields()[field_index].attrs); - encode_stability(self, field.did); + self.encode_attributes(&variant_data.fields()[field_index].attrs); + self.encode_stability(field.did); } fn encode_struct_ctor(&mut self, ctor_def_id: DefId) { @@ -380,7 +375,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_family(Family::Struct); self.encode_bounds_and_type_for_item(ctor_def_id); - encode_stability(self, ctor_def_id); + self.encode_stability(ctor_def_id); } fn encode_generics(&mut self, @@ -445,8 +440,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_family(family); self.encode_visibility(trait_item.vis()); - encode_stability(self, def_id); - encode_attributes(self, &ast_item.attrs); + self.encode_stability(def_id); + self.encode_attributes(&ast_item.attrs); if let hir::MethodTraitItem(ref sig, _) = ast_item.node { self.encode_fn_arg_names(&sig.decl); }; @@ -499,8 +494,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_def_key(def_id); self.encode_family(family); self.encode_visibility(impl_item.vis()); - encode_attributes(self, &ast_item.attrs); - encode_stability(self, def_id); + self.encode_attributes(&ast_item.attrs); + self.encode_stability(def_id); let constness = if let hir::ImplItemKind::Method(ref sig, _) = ast_item.node { if sig.constness == hir::Constness::Const { @@ -555,33 +550,30 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); } } -} -// Encodes the inherent implementations of a structure, enumeration, or trait. -fn encode_inherent_implementations(ecx: &mut EncodeContext, - def_id: DefId) { - ecx.start_tag(item_tag::inherent_impls); - match ecx.tcx.inherent_impls.borrow().get(&def_id) { - None => <[DefId]>::encode(&[], ecx).unwrap(), - Some(implementations) => implementations.encode(ecx).unwrap() + // Encodes the inherent implementations of a structure, enumeration, or trait. + fn encode_inherent_implementations(&mut self, def_id: DefId) { + self.start_tag(item_tag::inherent_impls); + match self.tcx.inherent_impls.borrow().get(&def_id) { + None => <[DefId]>::encode(&[], self).unwrap(), + Some(implementations) => implementations.encode(self).unwrap() + } + self.end_tag(); } - ecx.end_tag(); -} -fn encode_stability(ecx: &mut EncodeContext, def_id: DefId) { - ecx.tcx.lookup_stability(def_id).map(|stab| { - ecx.start_tag(item_tag::stability); - stab.encode(ecx).unwrap(); - ecx.end_tag(); - }); - ecx.tcx.lookup_deprecation(def_id).map(|depr| { - ecx.start_tag(item_tag::deprecation); - depr.encode(ecx).unwrap(); - ecx.end_tag(); - }); -} + fn encode_stability(&mut self, def_id: DefId) { + self.tcx.lookup_stability(def_id).map(|stab| { + self.start_tag(item_tag::stability); + stab.encode(self).unwrap(); + self.end_tag(); + }); + self.tcx.lookup_deprecation(def_id).map(|depr| { + self.start_tag(item_tag::deprecation); + depr.encode(self).unwrap(); + self.end_tag(); + }); + } -impl<'a, 'tcx> EncodeContext<'a, 'tcx> { fn encode_info_for_item(&mut self, (def_id, item): (DefId, &hir::Item)) { let tcx = self.tcx; @@ -652,7 +644,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); // Encode inherent implementations for self enumeration. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Enum, EntryData::Other, EntryTypedData::Other) } @@ -675,7 +667,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = self.encode_variant(variant, struct_ctor); // Encode inherent implementations for self structure. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Struct, data, EntryTypedData::Other) } @@ -691,7 +683,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let data = self.encode_variant(def.struct_variant(), None); // Encode inherent implementations for self union. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Union, data, EntryTypedData::Other) } @@ -752,7 +744,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.end_tag(); // Encode inherent implementations for self trait. - encode_inherent_implementations(self, def_id); + self.encode_inherent_implementations(def_id); (Family::Trait, EntryData::Trait(TraitData { @@ -772,8 +764,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_family(family); self.encode_def_key(def_id); self.encode_visibility(&item.vis); - encode_attributes(self, &item.attrs); - encode_stability(self, def_id); + self.encode_attributes(&item.attrs); + self.encode_stability(def_id); self.start_tag(item_tag::data); data.encode(self).unwrap(); @@ -883,8 +875,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { EntryTypedData::Other.encode(self).unwrap(); self.end_tag(); - encode_attributes(self, &nitem.attrs); - encode_stability(self, def_id); + self.encode_attributes(&nitem.attrs); + self.encode_stability(def_id); } } @@ -970,152 +962,153 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { assert!(self.mir_map.map.contains_key(&def_id)); self.encode_mir(def_id); } -} -fn encode_info_for_items(ecx: &mut EncodeContext) -> IndexData { - let krate = ecx.tcx.map.krate(); + fn encode_info_for_items(&mut self) -> IndexData { + let krate = self.tcx.map.krate(); - // FIXME(eddyb) Avoid wrapping the items in a doc. - ecx.start_tag(0).unwrap(); + // FIXME(eddyb) Avoid wrapping the items in a doc. + self.start_tag(0).unwrap(); - let items = { - let mut index = IndexBuilder::new(ecx); - index.record(DefId::local(CRATE_DEF_INDEX), - EncodeContext::encode_info_for_mod, - FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); - let mut visitor = EncodeVisitor { - index: index, + let items = { + let mut index = IndexBuilder::new(self); + index.record(DefId::local(CRATE_DEF_INDEX), + EncodeContext::encode_info_for_mod, + FromId(CRATE_NODE_ID, (&krate.module, &krate.attrs, &hir::Public))); + let mut visitor = EncodeVisitor { + index: index, + }; + krate.visit_all_items(&mut visitor); + visitor.index.into_items() }; - krate.visit_all_items(&mut visitor); - visitor.index.into_items() - }; - ecx.end_tag(); + self.end_tag(); - items -} - -fn encode_item_index(ecx: &mut EncodeContext, index: IndexData) { - ecx.start_tag(root_tag::index); - index.write_index(&mut ecx.opaque.cursor); - ecx.end_tag(); -} - -fn encode_attributes(ecx: &mut EncodeContext, attrs: &[ast::Attribute]) { - ecx.start_tag(item_tag::attributes); - attrs.encode(ecx).unwrap(); - ecx.end_tag(); -} - -fn encode_crate_deps(ecx: &mut EncodeContext, cstore: &cstore::CStore) { - fn get_ordered_deps(cstore: &cstore::CStore) - -> Vec<(CrateNum, Rc)> { - // Pull the cnums and name,vers,hash out of cstore - let mut deps = Vec::new(); - cstore.iter_crate_data(|cnum, val| { - deps.push((cnum, val.clone())); - }); - - // Sort by cnum - deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0)); - - // Sanity-check the crate numbers - let mut expected_cnum = 1; - for &(n, _) in &deps { - assert_eq!(n, CrateNum::new(expected_cnum)); - expected_cnum += 1; - } - - deps + items } - // We're just going to write a list of crate 'name-hash-version's, with - // 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. - ecx.start_tag(root_tag::crate_deps); - ecx.seq(&get_ordered_deps(cstore), |_, &(_, ref dep)| { - (dep.name(), dep.hash(), dep.explicitly_linked.get()) - }); - ecx.end_tag(); -} + fn encode_item_index(&mut self, index: IndexData) { + self.start_tag(root_tag::index); + index.write_index(&mut self.opaque.cursor); + self.end_tag(); + } -fn encode_lang_items(ecx: &mut EncodeContext) { - let tcx = ecx.tcx; - let lang_items = || { - tcx.lang_items.items().iter().enumerate().filter_map(|(i, &opt_def_id)| { - if let Some(def_id) = opt_def_id { - if def_id.is_local() { - return Some((def_id.index, i)); - } + fn encode_attributes(&mut self, attrs: &[ast::Attribute]) { + self.start_tag(item_tag::attributes); + attrs.encode(self).unwrap(); + self.end_tag(); + } + + fn encode_crate_deps(&mut self) { + fn get_ordered_deps(cstore: &cstore::CStore) + -> Vec<(CrateNum, Rc)> { + // Pull the cnums and name,vers,hash out of cstore + let mut deps = Vec::new(); + cstore.iter_crate_data(|cnum, val| { + deps.push((cnum, val.clone())); + }); + + // Sort by cnum + deps.sort_by(|kv1, kv2| kv1.0.cmp(&kv2.0)); + + // Sanity-check the crate numbers + let mut expected_cnum = 1; + for &(n, _) in &deps { + assert_eq!(n, CrateNum::new(expected_cnum)); + expected_cnum += 1; } - None - }) - }; - let count = lang_items().count(); - let mut lang_items = lang_items(); + deps + } - ecx.start_tag(root_tag::lang_items); - ecx.seq(0..count, |_, _| lang_items.next().unwrap()); - ecx.end_tag(); + // We're just going to write a list of crate 'name-hash-version's, with + // 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.start_tag(root_tag::crate_deps); + let deps = get_ordered_deps(self.cstore); + self.seq(&deps, |_, &(_, ref dep)| { + (dep.name(), dep.hash(), dep.explicitly_linked.get()) + }); + self.end_tag(); + } - ecx.start_tag(root_tag::lang_items_missing); - tcx.lang_items.missing.encode(ecx).unwrap(); - ecx.end_tag(); -} - -fn encode_native_libraries(ecx: &mut EncodeContext) { - let used_libraries = ecx.tcx.sess.cstore.used_libraries(); - let libs = || { - used_libraries.iter().filter_map(|&(ref lib, kind)| { - match kind { - cstore::NativeStatic => None, // these libraries are not propagated - cstore::NativeFramework | cstore::NativeUnknown => { - Some((kind, lib)) + fn encode_lang_items(&mut self) { + let tcx = self.tcx; + let lang_items = || { + tcx.lang_items.items().iter().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)); + } } - } - }) - }; + None + }) + }; - let count = libs().count(); - let mut libs = libs(); + let count = lang_items().count(); + let mut lang_items = lang_items(); - ecx.start_tag(root_tag::native_libraries); - ecx.seq(0..count, |_, _| libs.next().unwrap()); - ecx.end_tag(); -} + self.start_tag(root_tag::lang_items); + self.seq(0..count, |_, _| lang_items.next().unwrap()); + self.end_tag(); -fn encode_codemap(ecx: &mut EncodeContext) { - let codemap = ecx.tcx.sess.codemap(); - let all_filemaps = codemap.files.borrow(); - let filemaps = || { - // No need to export empty filemaps, as they can't contain spans - // that need translation. - // Also no need to re-export imported filemaps, as any downstream - // crate will import them from their original source. - all_filemaps.iter().filter(|filemap| { - !filemap.lines.borrow().is_empty() && !filemap.is_imported() - }) - }; + self.start_tag(root_tag::lang_items_missing); + tcx.lang_items.missing.encode(self).unwrap(); + self.end_tag(); + } - let count = filemaps().count(); - let mut filemaps = filemaps(); + fn encode_native_libraries(&mut self) { + let used_libraries = self.tcx.sess.cstore.used_libraries(); + let libs = || { + used_libraries.iter().filter_map(|&(ref lib, kind)| { + match kind { + cstore::NativeStatic => None, // these libraries are not propagated + cstore::NativeFramework | cstore::NativeUnknown => { + Some((kind, lib)) + } + } + }) + }; - ecx.start_tag(root_tag::codemap); - ecx.seq(0..count, |_, _| filemaps.next().unwrap()); - ecx.end_tag(); -} + let count = libs().count(); + let mut libs = libs(); -/// Serialize the text of the exported macros -fn encode_macro_defs(ecx: &mut EncodeContext) { - let tcx = ecx.tcx; - ecx.start_tag(root_tag::macro_defs); - ecx.seq(&tcx.map.krate().exported_macros, |_, def| { - let body = ::syntax::print::pprust::tts_to_string(&def.body); - (def.name, &def.attrs, def.span, body) - }); - ecx.end_tag(); + self.start_tag(root_tag::native_libraries); + self.seq(0..count, |_, _| libs.next().unwrap()); + self.end_tag(); + } + + fn encode_codemap(&mut self) { + let codemap = self.tcx.sess.codemap(); + let all_filemaps = codemap.files.borrow(); + let filemaps = || { + // No need to export empty filemaps, as they can't contain spans + // that need translation. + // Also no need to re-export imported filemaps, as any downstream + // crate will import them from their original source. + all_filemaps.iter().filter(|filemap| { + !filemap.lines.borrow().is_empty() && !filemap.is_imported() + }) + }; + + let count = filemaps().count(); + let mut filemaps = filemaps(); + + self.start_tag(root_tag::codemap); + self.seq(0..count, |_, _| filemaps.next().unwrap()); + self.end_tag(); + } + + /// Serialize the text of the exported macros + fn encode_macro_defs(&mut self) { + let tcx = self.tcx; + self.start_tag(root_tag::macro_defs); + self.seq(&tcx.map.krate().exported_macros, |_, def| { + let body = ::syntax::print::pprust::tts_to_string(&def.body); + (def.name, &def.attrs, def.span, body) + }); + self.end_tag(); + } } struct ImplVisitor<'a, 'tcx:'a> { @@ -1136,59 +1129,61 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'tcx> { } } -/// Encodes an index, mapping each trait to its (local) implementations. -fn encode_impls(ecx: &mut EncodeContext) { - let mut visitor = ImplVisitor { - tcx: ecx.tcx, - impls: FnvHashMap() - }; - ecx.tcx.map.krate().visit_all_items(&mut visitor); +impl<'a, 'tcx> EncodeContext<'a, 'tcx> { + /// Encodes an index, mapping each trait to its (local) implementations. + fn encode_impls(&mut self) { + let mut visitor = ImplVisitor { + tcx: self.tcx, + impls: FnvHashMap() + }; + self.tcx.map.krate().visit_all_items(&mut visitor); - ecx.start_tag(root_tag::impls); - for (trait_def_id, trait_impls) in visitor.impls { - // FIXME(eddyb) Avoid wrapping the entries in docs. - ecx.start_tag(0); - (trait_def_id.krate.as_u32(), trait_def_id.index).encode(ecx).unwrap(); - trait_impls.encode(ecx).unwrap(); - ecx.end_tag(); - } - ecx.end_tag(); -} - -// Encodes all reachable symbols in this crate into the metadata. -// -// This pass is seeded off the reachability list calculated in the -// middle::reachable module but filters out items that either don't have a -// 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_reachable(ecx: &mut EncodeContext) { - ecx.start_tag(root_tag::reachable_ids); - - let reachable = ecx.reachable; - ecx.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); - - ecx.end_tag(); -} - -fn encode_dylib_dependency_formats(ecx: &mut EncodeContext) { - ecx.start_tag(root_tag::dylib_dependency_formats); - match ecx.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { - Some(arr) => { - ecx.seq(arr, |_, slot| { - match *slot { - Linkage::NotLinked | - Linkage::IncludedFromDylib => None, - - Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), - Linkage::Static => Some(LinkagePreference::RequireStatic), - } - }); - } - None => { - <[Option]>::encode(&[], ecx).unwrap(); + self.start_tag(root_tag::impls); + for (trait_def_id, trait_impls) in visitor.impls { + // FIXME(eddyb) Avoid wrapping the entries in docs. + self.start_tag(0); + (trait_def_id.krate.as_u32(), trait_def_id.index).encode(self).unwrap(); + trait_impls.encode(self).unwrap(); + self.end_tag(); } + self.end_tag(); + } + + // Encodes all reachable symbols in this crate into the metadata. + // + // This pass is seeded off the reachability list calculated in the + // middle::reachable module but filters out items that either don't have a + // 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_reachable(&mut self) { + self.start_tag(root_tag::reachable_ids); + + let reachable = self.reachable; + self.seq(reachable, |ecx, &id| ecx.tcx.map.local_def_id(id).index); + + self.end_tag(); + } + + fn encode_dylib_dependency_formats(&mut self) { + self.start_tag(root_tag::dylib_dependency_formats); + match self.tcx.sess.dependency_formats.borrow().get(&config::CrateTypeDylib) { + Some(arr) => { + self.seq(arr, |_, slot| { + match *slot { + Linkage::NotLinked | + Linkage::IncludedFromDylib => None, + + Linkage::Dynamic => Some(LinkagePreference::RequireDynamic), + Linkage::Static => Some(LinkagePreference::RequireStatic), + } + }); + } + None => { + <[Option]>::encode(&[], self).unwrap(); + } + } + self.end_tag(); } - ecx.end_tag(); } pub fn encode_metadata<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, @@ -1281,47 +1276,47 @@ fn encode_metadata_inner(ecx: &mut EncodeContext) { ecx.end_tag(); let mut i = ecx.position(); - encode_crate_deps(ecx, ecx.cstore); - encode_dylib_dependency_formats(ecx); + ecx.encode_crate_deps(); + ecx.encode_dylib_dependency_formats(); let dep_bytes = ecx.position() - i; // Encode the language items. i = ecx.position(); - encode_lang_items(ecx); + ecx.encode_lang_items(); let lang_item_bytes = ecx.position() - i; // Encode the native libraries used i = ecx.position(); - encode_native_libraries(ecx); + ecx.encode_native_libraries(); let native_lib_bytes = ecx.position() - i; // Encode codemap i = ecx.position(); - encode_codemap(ecx); + ecx.encode_codemap(); let codemap_bytes = ecx.position() - i; // Encode macro definitions i = ecx.position(); - encode_macro_defs(ecx); + ecx.encode_macro_defs(); let macro_defs_bytes = ecx.position() - i; // Encode the def IDs of impls, for coherence checking. i = ecx.position(); - encode_impls(ecx); + ecx.encode_impls(); let impl_bytes = ecx.position() - i; // Encode reachability info. i = ecx.position(); - encode_reachable(ecx); + ecx.encode_reachable(); let reachable_bytes = ecx.position() - i; // Encode and index the items. i = ecx.position(); - let items = encode_info_for_items(ecx); + let items = ecx.encode_info_for_items(); let item_bytes = ecx.position() - i; i = ecx.position(); - encode_item_index(ecx, items); + ecx.encode_item_index(items); let index_bytes = ecx.position() - i; let total_bytes = ecx.position(); diff --git a/src/librustc_metadata/loader.rs b/src/librustc_metadata/loader.rs index 47bf65bead9a..883004b8486f 100644 --- a/src/librustc_metadata/loader.rs +++ b/src/librustc_metadata/loader.rs @@ -214,7 +214,6 @@ use cstore::{MetadataBlob, MetadataVec, MetadataArchive}; use common::{metadata_encoding_version, rustc_version}; -use decoder; use rustc::hir::svh::Svh; use rustc::session::Session; @@ -511,7 +510,7 @@ impl<'a> Context<'a> { if let Some((ref p, _)) = lib.rlib { err.note(&format!("path: {}", p.display())); } - let crate_info = decoder::get_crate_info(lib.metadata.as_slice()); + let crate_info = lib.metadata.get_crate_info(); note_crate_name(&mut err, &crate_info.name); } err.emit(); @@ -550,7 +549,7 @@ impl<'a> Context<'a> { info!("{} reading metadata from: {}", flavor, lib.display()); let (hash, metadata) = match get_metadata_section(self.target, flavor, &lib) { Ok(blob) => { - if let Some(h) = self.crate_matches(blob.as_slice(), &lib) { + if let Some(h) = self.crate_matches(&blob, &lib) { (h, blob) } else { info!("metadata mismatch"); @@ -597,8 +596,8 @@ impl<'a> Context<'a> { } } - fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> Option { - let crate_rustc_version = decoder::crate_rustc_version(crate_data); + fn crate_matches(&mut self, metadata: &MetadataBlob, libpath: &Path) -> Option { + let crate_rustc_version = metadata.crate_rustc_version(); if crate_rustc_version != Some(rustc_version()) { let message = crate_rustc_version.unwrap_or(format!("an unknown compiler")); info!("Rejecting via version: expected {} got {}", rustc_version(), message); @@ -609,7 +608,7 @@ impl<'a> Context<'a> { return None; } - let crate_info = decoder::get_crate_info(crate_data); + let crate_info = metadata.get_crate_info(); if self.should_match_name { if self.crate_name != crate_info.name { info!("Rejecting via crate name"); return None; @@ -895,7 +894,7 @@ pub fn list_file_metadata(target: &Target, path: &Path, let filename = path.file_name().unwrap().to_str().unwrap(); let flavor = if filename.ends_with(".rlib") { CrateFlavor::Rlib } else { CrateFlavor::Dylib }; match get_metadata_section(target, flavor, path) { - Ok(bytes) => decoder::list_crate_metadata(bytes.as_slice(), out), + Ok(metadata) => metadata.list_crate_metadata(out), Err(msg) => { write!(out, "{}\n", msg) } diff --git a/src/librustc_metadata/rbml/reader.rs b/src/librustc_metadata/rbml/reader.rs index 24a0329602be..c4cfc32d6330 100644 --- a/src/librustc_metadata/rbml/reader.rs +++ b/src/librustc_metadata/rbml/reader.rs @@ -52,6 +52,15 @@ use test::Bencher; use std::fmt; use std::str; +macro_rules! try_or { + ($e:expr, $r:expr) => ( + match $e { + Ok(x) => x, + Err(_) => return $r + } + ) +} + #[derive(Clone, Copy)] pub struct Doc<'a> { pub data: &'a [u8], @@ -79,17 +88,34 @@ impl<'doc> Doc<'doc> { } } - pub fn get(&self, tag: usize) -> Doc<'doc> { - match maybe_get_doc(*self, tag) { + pub fn maybe_child(&self, tag: usize) -> Option> { + let mut pos = self.start; + while pos < self.end { + let elt_tag = try_or!(tag_at(self.data, pos), None); + let elt_size = try_or!(tag_len_at(self.data, elt_tag.next), None); + pos = elt_size.next + elt_size.val; + if elt_tag.val == tag { + return Some(Doc { + data: self.data, + start: elt_size.next, + end: pos, + }); + } + } + None + } + + pub fn child(&self, tag: usize) -> Doc<'doc> { + match self.maybe_child(tag) { Some(d) => d, None => { - bug!("failed to find block with tag {:?}", tag); + bug!("failed to find child with tag {:?}", tag); } } } - pub fn children(self) -> DocsIterator<'doc> { - DocsIterator { d: self } + pub fn children_of(&self, tag: usize) -> DocsIterator<'doc> { + DocsIterator { d: self.child(tag) } } } @@ -106,24 +132,10 @@ impl fmt::Display for Error { } } -// rbml reading - -macro_rules! try_or { - ($e:expr, $r:expr) => ( - match $e { - Ok(e) => e, - Err(e) => { - debug!("ignored error: {:?}", e); - return $r - } - } - ) -} - #[derive(Copy, Clone)] -pub struct Res { - pub val: usize, - pub next: usize, +struct Res { + val: usize, + next: usize, } fn tag_at(data: &[u8], start: usize) -> Result { @@ -235,23 +247,6 @@ fn tag_len_at(data: &[u8], next: usize) -> Result { vuint_at(data, next) } -pub fn maybe_get_doc<'a>(d: Doc<'a>, tg: usize) -> Option> { - let mut pos = d.start; - while pos < d.end { - let elt_tag = try_or!(tag_at(d.data, pos), None); - let elt_size = try_or!(tag_len_at(d.data, elt_tag.next), None); - pos = elt_size.next + elt_size.val; - if elt_tag.val == tg { - return Some(Doc { - data: d.data, - start: elt_size.next, - end: pos, - }); - } - } - None -} - pub struct DocsIterator<'a> { d: Doc<'a>, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 43a9b4e49e39..0acf211a27c5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -237,8 +237,8 @@ pub struct ExternalCrate { impl Clean for CrateNum { fn clean(&self, cx: &DocContext) -> ExternalCrate { let mut primitives = Vec::new(); + let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; cx.tcx_opt().map(|tcx| { - let root = DefId { krate: self.0, index: CRATE_DEF_INDEX }; for item in tcx.sess.cstore.item_children(root) { let did = match item.def { Def::Mod(did) => did, @@ -250,7 +250,7 @@ impl Clean for CrateNum { }); ExternalCrate { name: (&cx.sess().cstore.crate_name(self.0)[..]).to_owned(), - attrs: cx.sess().cstore.crate_attrs(self.0).clean(cx), + attrs: cx.sess().cstore.item_attrs(root).clean(cx), primitives: primitives, } }