1 // The crate store - a central repo for information collected about external
2 // crates and libraries
5 use rustc::dep_graph::DepNodeIndex;
6 use rustc::hir::def_id::{CrateNum, DefIndex};
7 use rustc::hir::map::definitions::DefPathTable;
8 use rustc::middle::cstore::{DepKind, ExternCrate, MetadataLoader};
9 use rustc::mir::interpret::AllocDecodingState;
10 use rustc_index::vec::IndexVec;
11 use rustc::util::nodemap::{FxHashMap, NodeMap};
13 use rustc_data_structures::sync::{Lrc, RwLock, Lock, AtomicCell};
15 use syntax::ext::base::SyntaxExtension;
18 pub use rustc::middle::cstore::{NativeLibrary, NativeLibraryKind, LinkagePreference};
19 pub use rustc::middle::cstore::NativeLibraryKind::*;
20 pub use rustc::middle::cstore::{CrateSource, LibSource, ForeignModule};
22 pub use crate::cstore_impl::{provide, provide_extern};
24 // A map from external crate numbers (as decoded from some crate file) to
25 // local crate numbers (as generated during this session). Each external
26 // crate may refer to types in other external crates, and each has their
28 pub type CrateNumMap = IndexVec<CrateNum, CrateNum>;
30 pub use rustc_data_structures::sync::MetadataRef;
32 use proc_macro::bridge::client::ProcMacro;
34 pub struct MetadataBlob(pub MetadataRef);
36 /// Holds information about a syntax_pos::SourceFile imported from another crate.
37 /// See `imported_source_files()` for more information.
38 pub struct ImportedSourceFile {
39 /// This SourceFile's byte-offset within the source_map of its original crate
40 pub original_start_pos: syntax_pos::BytePos,
41 /// The end of this SourceFile within the source_map of its original crate
42 pub original_end_pos: syntax_pos::BytePos,
43 /// The imported SourceFile's representation within the local source_map
44 pub translated_source_file: Lrc<syntax_pos::SourceFile>,
47 pub struct CrateMetadata {
48 /// Information about the extern crate that caused this crate to
49 /// be loaded. If this is `None`, then the crate was injected
50 /// (e.g., by the allocator)
51 pub extern_crate: Lock<Option<ExternCrate>>,
53 pub blob: MetadataBlob,
54 pub cnum_map: CrateNumMap,
56 pub dependencies: Lock<Vec<CrateNum>>,
57 pub source_map_import_info: RwLock<Vec<ImportedSourceFile>>,
59 /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
60 pub alloc_decoding_state: AllocDecodingState,
62 // NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
63 // lifetime is only used behind `Lazy`, and therefore acts like an
64 // universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
65 // is being used to decode those values.
66 pub root: schema::CrateRoot<'static>,
68 /// For each definition in this crate, we encode a key. When the
69 /// crate is loaded, we read all the keys and put them in this
70 /// hashmap, which gives the reverse mapping. This allows us to
71 /// quickly retrace a `DefPath`, which is needed for incremental
72 /// compilation support.
73 pub def_path_table: Lrc<DefPathTable>,
75 pub trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>,
77 pub dep_kind: Lock<DepKind>,
78 pub source: CrateSource,
80 /// Whether or not this crate should be consider a private dependency
81 /// for purposes of the 'exported_private_dependencies' lint
82 pub private_dep: bool,
86 pub raw_proc_macros: Option<&'static [ProcMacro]>,
88 /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
89 /// It is initialized on the first access in `get_crate_dep_node_index()`.
90 /// Do not access the value directly, as it might not have been initialized
92 /// The field must always be initialized to `DepNodeIndex::INVALID`.
93 pub(super) dep_node_index: AtomicCell<DepNodeIndex>,
97 metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
98 /// Map from NodeId's of local extern crate statements to crate numbers
99 extern_mod_crate_map: Lock<NodeMap<CrateNum>>,
100 pub metadata_loader: Box<dyn MetadataLoader + Sync>,
103 pub enum LoadedMacro {
105 ProcMacro(SyntaxExtension),
109 pub fn new(metadata_loader: Box<dyn MetadataLoader + Sync>) -> CStore {
111 // We add an empty entry for LOCAL_CRATE (which maps to zero) in
112 // order to make array indices in `metas` match with the
113 // corresponding `CrateNum`. This first entry will always remain
115 metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
116 extern_mod_crate_map: Default::default(),
121 pub(super) fn alloc_new_crate_num(&self) -> CrateNum {
122 let mut metas = self.metas.borrow_mut();
123 let cnum = CrateNum::new(metas.len());
128 pub(super) fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
129 self.metas.borrow()[cnum].clone()
130 .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
133 pub(super) fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
134 let mut metas = self.metas.borrow_mut();
135 assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
136 metas[cnum] = Some(data);
139 pub(super) fn iter_crate_data<I>(&self, mut i: I)
140 where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
142 for (k, v) in self.metas.borrow().iter_enumerated() {
143 if let &Some(ref v) = v {
149 pub(super) fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
150 let mut ordering = Vec::new();
151 self.push_dependencies_in_postorder(&mut ordering, krate);
156 pub(super) fn push_dependencies_in_postorder(&self,
157 ordering: &mut Vec<CrateNum>,
159 if ordering.contains(&krate) {
163 let data = self.get_crate_data(krate);
164 for &dep in data.dependencies.borrow().iter() {
166 self.push_dependencies_in_postorder(ordering, dep);
170 ordering.push(krate);
173 pub(super) fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
174 let mut ordering = Vec::new();
175 for (num, v) in self.metas.borrow().iter_enumerated() {
176 if let &Some(_) = v {
177 self.push_dependencies_in_postorder(&mut ordering, num);
183 pub(super) fn add_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId, cnum: CrateNum) {
184 self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
187 pub(super) fn do_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<CrateNum> {
188 self.extern_mod_crate_map.borrow().get(&emod_id).cloned()