]> git.lizzy.rs Git - rust.git/blob - src/librustc_metadata/cstore.rs
rustc_metadata: Remove resolutions for extern crate items from `CStore`
[rust.git] / src / librustc_metadata / cstore.rs
1 // The crate store - a central repo for information collected about external
2 // crates and libraries
3
4 use crate::schema;
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::{CrateSource, DepKind, ExternCrate, MetadataLoader};
9 use rustc::mir::interpret::AllocDecodingState;
10 use rustc_index::vec::IndexVec;
11 use rustc::util::nodemap::FxHashMap;
12 use rustc_data_structures::sync::{Lrc, RwLock, Lock, MetadataRef, AtomicCell};
13 use syntax::ast;
14 use syntax::ext::base::SyntaxExtension;
15 use syntax_pos;
16 use proc_macro::bridge::client::ProcMacro;
17
18 pub use crate::cstore_impl::{provide, provide_extern};
19
20 // A map from external crate numbers (as decoded from some crate file) to
21 // local crate numbers (as generated during this session). Each external
22 // crate may refer to types in other external crates, and each has their
23 // own crate numbers.
24 crate type CrateNumMap = IndexVec<CrateNum, CrateNum>;
25
26 crate struct MetadataBlob(pub MetadataRef);
27
28 /// Holds information about a syntax_pos::SourceFile imported from another crate.
29 /// See `imported_source_files()` for more information.
30 crate struct ImportedSourceFile {
31     /// This SourceFile's byte-offset within the source_map of its original crate
32     pub original_start_pos: syntax_pos::BytePos,
33     /// The end of this SourceFile within the source_map of its original crate
34     pub original_end_pos: syntax_pos::BytePos,
35     /// The imported SourceFile's representation within the local source_map
36     pub translated_source_file: Lrc<syntax_pos::SourceFile>,
37 }
38
39 pub struct CrateMetadata {
40     /// The primary crate data - binary metadata blob.
41     crate blob: MetadataBlob,
42
43     // --- Some data pre-decoded from the metadata blob, usually for performance ---
44
45     /// Properties of the whole crate.
46     /// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
47     /// lifetime is only used behind `Lazy`, and therefore acts like an
48     /// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
49     /// is being used to decode those values.
50     crate root: schema::CrateRoot<'static>,
51     /// For each definition in this crate, we encode a key. When the
52     /// crate is loaded, we read all the keys and put them in this
53     /// hashmap, which gives the reverse mapping. This allows us to
54     /// quickly retrace a `DefPath`, which is needed for incremental
55     /// compilation support.
56     crate def_path_table: Lrc<DefPathTable>,
57     /// Trait impl data.
58     /// FIXME: Used only from queries and can use query cache,
59     /// so pre-decoding can probably be avoided.
60     crate trait_impls: FxHashMap<(u32, DefIndex), schema::Lazy<[DefIndex]>>,
61     /// Proc macro descriptions for this crate, if it's a proc macro crate.
62     crate raw_proc_macros: Option<&'static [ProcMacro]>,
63     /// Source maps for code from the crate.
64     crate source_map_import_info: RwLock<Vec<ImportedSourceFile>>,
65     /// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
66     crate alloc_decoding_state: AllocDecodingState,
67     /// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
68     /// It is initialized on the first access in `get_crate_dep_node_index()`.
69     /// Do not access the value directly, as it might not have been initialized yet.
70     /// The field must always be initialized to `DepNodeIndex::INVALID`.
71     crate dep_node_index: AtomicCell<DepNodeIndex>,
72
73     // --- Other significant crate properties ---
74
75     /// ID of this crate, from the current compilation session's point of view.
76     crate cnum: CrateNum,
77     /// Maps crate IDs as they are were seen from this crate's compilation sessions into
78     /// IDs as they are seen from the current compilation session.
79     crate cnum_map: CrateNumMap,
80     /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
81     crate dependencies: Lock<Vec<CrateNum>>,
82     /// How to link (or not link) this crate to the currently compiled crate.
83     crate dep_kind: Lock<DepKind>,
84     /// Filesystem location of this crate.
85     crate source: CrateSource,
86     /// Whether or not this crate should be consider a private dependency
87     /// for purposes of the 'exported_private_dependencies' lint
88     crate private_dep: bool,
89
90     // --- Data used only for improving diagnostics ---
91
92     /// Information about the `extern crate` item or path that caused this crate to be loaded.
93     /// If this is `None`, then the crate was injected (e.g., by the allocator).
94     crate extern_crate: Lock<Option<ExternCrate>>,
95 }
96
97 pub struct CStore {
98     metas: RwLock<IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>>,
99     crate metadata_loader: Box<dyn MetadataLoader + Sync>,
100 }
101
102 pub enum LoadedMacro {
103     MacroDef(ast::Item),
104     ProcMacro(SyntaxExtension),
105 }
106
107 impl CStore {
108     pub fn new(metadata_loader: Box<dyn MetadataLoader + Sync>) -> CStore {
109         CStore {
110             // We add an empty entry for LOCAL_CRATE (which maps to zero) in
111             // order to make array indices in `metas` match with the
112             // corresponding `CrateNum`. This first entry will always remain
113             // `None`.
114             metas: RwLock::new(IndexVec::from_elem_n(None, 1)),
115             metadata_loader,
116         }
117     }
118
119     crate fn alloc_new_crate_num(&self) -> CrateNum {
120         let mut metas = self.metas.borrow_mut();
121         let cnum = CrateNum::new(metas.len());
122         metas.push(None);
123         cnum
124     }
125
126     crate fn get_crate_data(&self, cnum: CrateNum) -> Lrc<CrateMetadata> {
127         self.metas.borrow()[cnum].clone()
128             .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum))
129     }
130
131     crate fn set_crate_data(&self, cnum: CrateNum, data: Lrc<CrateMetadata>) {
132         let mut metas = self.metas.borrow_mut();
133         assert!(metas[cnum].is_none(), "Overwriting crate metadata entry");
134         metas[cnum] = Some(data);
135     }
136
137     crate fn iter_crate_data<I>(&self, mut i: I)
138         where I: FnMut(CrateNum, &Lrc<CrateMetadata>)
139     {
140         for (k, v) in self.metas.borrow().iter_enumerated() {
141             if let &Some(ref v) = v {
142                 i(k, v);
143             }
144         }
145     }
146
147     crate fn crate_dependencies_in_rpo(&self, krate: CrateNum) -> Vec<CrateNum> {
148         let mut ordering = Vec::new();
149         self.push_dependencies_in_postorder(&mut ordering, krate);
150         ordering.reverse();
151         ordering
152     }
153
154     crate fn push_dependencies_in_postorder(&self, ordering: &mut Vec<CrateNum>, krate: CrateNum) {
155         if ordering.contains(&krate) {
156             return;
157         }
158
159         let data = self.get_crate_data(krate);
160         for &dep in data.dependencies.borrow().iter() {
161             if dep != krate {
162                 self.push_dependencies_in_postorder(ordering, dep);
163             }
164         }
165
166         ordering.push(krate);
167     }
168
169     crate fn do_postorder_cnums_untracked(&self) -> Vec<CrateNum> {
170         let mut ordering = Vec::new();
171         for (num, v) in self.metas.borrow().iter_enumerated() {
172             if let &Some(_) = v {
173                 self.push_dependencies_in_postorder(&mut ordering, num);
174             }
175         }
176         return ordering
177     }
178 }