]>
Commit | Line | Data |
---|---|---|
3b2f2976 XL |
1 | //! the rustc crate store interface. This also includes types that |
2 | //! are *mostly* used as a part of that interface, but these should | |
3 | //! probably get a better home if someone can find one. | |
92a42be0 | 4 | |
dfeec247 | 5 | use crate::ty::TyCtxt; |
32a655c1 | 6 | |
3dfed10e | 7 | use rustc_ast as ast; |
74b04a01 | 8 | use rustc_ast::expand::allocator::AllocatorKind; |
dfeec247 XL |
9 | use rustc_data_structures::svh::Svh; |
10 | use rustc_data_structures::sync::{self, MetadataRef}; | |
29967ef6 | 11 | use rustc_hir::def::DefKind; |
dfeec247 | 12 | use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; |
3dfed10e | 13 | use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; |
dfeec247 | 14 | use rustc_macros::HashStable; |
ba9703b0 | 15 | use rustc_session::search_paths::PathKind; |
f9f354fc | 16 | use rustc_session::utils::NativeLibKind; |
ba9703b0 | 17 | use rustc_session::CrateDisambiguator; |
dfeec247 XL |
18 | use rustc_span::symbol::Symbol; |
19 | use rustc_span::Span; | |
20 | use rustc_target::spec::Target; | |
ba9703b0 | 21 | |
8bb4bdeb | 22 | use std::any::Any; |
7cac9316 | 23 | use std::path::{Path, PathBuf}; |
92a42be0 | 24 | |
92a42be0 SL |
25 | // lonely orphan structs and enums looking for a better home |
26 | ||
3b2f2976 XL |
27 | /// Where a crate came from on the local filesystem. One of these three options |
28 | /// must be non-None. | |
3dfed10e | 29 | #[derive(PartialEq, Clone, Debug, HashStable, Encodable, Decodable)] |
92a42be0 SL |
30 | pub struct CrateSource { |
31 | pub dylib: Option<(PathBuf, PathKind)>, | |
32 | pub rlib: Option<(PathBuf, PathKind)>, | |
476ff2be SL |
33 | pub rmeta: Option<(PathBuf, PathKind)>, |
34 | } | |
35 | ||
e74abb32 XL |
36 | impl CrateSource { |
37 | pub fn paths(&self) -> impl Iterator<Item = &PathBuf> { | |
38 | self.dylib.iter().chain(self.rlib.iter()).chain(self.rmeta.iter()).map(|p| &p.0) | |
39 | } | |
40 | } | |
41 | ||
3dfed10e | 42 | #[derive(Encodable, Decodable, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Debug)] |
ba9703b0 | 43 | #[derive(HashStable)] |
3dfed10e | 44 | pub enum CrateDepKind { |
476ff2be SL |
45 | /// A dependency that is only used for its macros. |
46 | MacrosOnly, | |
47 | /// A dependency that is always injected into the dependency list and so | |
0731742a | 48 | /// doesn't need to be linked to an rlib, e.g., the injected allocator. |
476ff2be SL |
49 | Implicit, |
50 | /// A dependency that is required by an rlib version of this crate. | |
51 | /// Ordinary `extern crate`s result in `Explicit` dependencies. | |
52 | Explicit, | |
53 | } | |
54 | ||
3dfed10e | 55 | impl CrateDepKind { |
476ff2be SL |
56 | pub fn macros_only(self) -> bool { |
57 | match self { | |
3dfed10e XL |
58 | CrateDepKind::MacrosOnly => true, |
59 | CrateDepKind::Implicit | CrateDepKind::Explicit => false, | |
476ff2be SL |
60 | } |
61 | } | |
62 | } | |
63 | ||
3dfed10e | 64 | #[derive(PartialEq, Clone, Debug, Encodable, Decodable)] |
476ff2be SL |
65 | pub enum LibSource { |
66 | Some(PathBuf), | |
67 | MetadataOnly, | |
68 | None, | |
69 | } | |
70 | ||
71 | impl LibSource { | |
72 | pub fn is_some(&self) -> bool { | |
1b1a35ee | 73 | matches!(self, LibSource::Some(_)) |
476ff2be SL |
74 | } |
75 | ||
76 | pub fn option(&self) -> Option<PathBuf> { | |
77 | match *self { | |
78 | LibSource::Some(ref p) => Some(p.clone()), | |
79 | LibSource::MetadataOnly | LibSource::None => None, | |
80 | } | |
81 | } | |
92a42be0 SL |
82 | } |
83 | ||
3dfed10e | 84 | #[derive(Copy, Debug, PartialEq, Clone, Encodable, Decodable, HashStable)] |
92a42be0 SL |
85 | pub enum LinkagePreference { |
86 | RequireDynamic, | |
87 | RequireStatic, | |
88 | } | |
89 | ||
3dfed10e | 90 | #[derive(Clone, Debug, Encodable, Decodable, HashStable)] |
f9f354fc XL |
91 | pub struct NativeLib { |
92 | pub kind: NativeLibKind, | |
8faf50e0 | 93 | pub name: Option<Symbol>, |
476ff2be | 94 | pub cfg: Option<ast::MetaItem>, |
0531ce1d | 95 | pub foreign_module: Option<DefId>, |
8faf50e0 | 96 | pub wasm_import_module: Option<Symbol>, |
0531ce1d XL |
97 | } |
98 | ||
3dfed10e | 99 | #[derive(Clone, TyEncodable, TyDecodable, HashStable)] |
0531ce1d | 100 | pub struct ForeignModule { |
ea8adc8c | 101 | pub foreign_items: Vec<DefId>, |
0531ce1d | 102 | pub def_id: DefId, |
476ff2be SL |
103 | } |
104 | ||
532ac7d7 | 105 | #[derive(Copy, Clone, Debug, HashStable)] |
54a0048b | 106 | pub struct ExternCrate { |
83c7162d | 107 | pub src: ExternCrateSource, |
54a0048b SL |
108 | |
109 | /// span of the extern crate that caused this to be loaded | |
110 | pub span: Span, | |
111 | ||
83c7162d XL |
112 | /// Number of links to reach the extern; |
113 | /// used to select the extern with the shortest path | |
114 | pub path_len: usize, | |
115 | ||
e74abb32 XL |
116 | /// Crate that depends on this crate |
117 | pub dependency_of: CrateNum, | |
118 | } | |
119 | ||
120 | impl ExternCrate { | |
54a0048b SL |
121 | /// If true, then this crate is the crate named by the extern |
122 | /// crate referenced above. If false, then this crate is a dep | |
123 | /// of the crate. | |
e74abb32 XL |
124 | pub fn is_direct(&self) -> bool { |
125 | self.dependency_of == LOCAL_CRATE | |
126 | } | |
60c5eb7d XL |
127 | |
128 | pub fn rank(&self) -> impl PartialOrd { | |
129 | // Prefer: | |
130 | // - direct extern crate to indirect | |
131 | // - shorter paths to longer | |
132 | (self.is_direct(), !self.path_len) | |
133 | } | |
83c7162d | 134 | } |
54a0048b | 135 | |
532ac7d7 | 136 | #[derive(Copy, Clone, Debug, HashStable)] |
83c7162d XL |
137 | pub enum ExternCrateSource { |
138 | /// Crate is loaded by `extern crate`. | |
139 | Extern( | |
140 | /// def_id of the item in the current crate that caused | |
141 | /// this crate to be loaded; note that there could be multiple | |
142 | /// such ids | |
143 | DefId, | |
144 | ), | |
e74abb32 | 145 | /// Crate is implicitly loaded by a path resolving through extern prelude. |
83c7162d | 146 | Path, |
54a0048b SL |
147 | } |
148 | ||
3dfed10e | 149 | #[derive(Encodable, Decodable)] |
cc61c64b | 150 | pub struct EncodedMetadata { |
dfeec247 | 151 | pub raw_data: Vec<u8>, |
7cac9316 XL |
152 | } |
153 | ||
154 | impl EncodedMetadata { | |
155 | pub fn new() -> EncodedMetadata { | |
dfeec247 | 156 | EncodedMetadata { raw_data: Vec::new() } |
7cac9316 | 157 | } |
cc61c64b XL |
158 | } |
159 | ||
7cac9316 XL |
160 | /// The backend's way to give the crate store access to the metadata in a library. |
161 | /// Note that it returns the raw metadata bytes stored in the library file, whether | |
162 | /// it is compressed, uncompressed, some weird mix, etc. | |
163 | /// rmeta files are backend independent and not handled here. | |
164 | /// | |
165 | /// At the time of this writing, there is only one backend and one way to store | |
166 | /// metadata in library -- this trait just serves to decouple rustc_metadata from | |
167 | /// the archive reader, which depends on LLVM. | |
168 | pub trait MetadataLoader { | |
dfeec247 XL |
169 | fn get_rlib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>; |
170 | fn get_dylib_metadata(&self, target: &Target, filename: &Path) -> Result<MetadataRef, String>; | |
7cac9316 XL |
171 | } |
172 | ||
e74abb32 XL |
173 | pub type MetadataLoaderDyn = dyn MetadataLoader + Sync; |
174 | ||
e1599b0c | 175 | /// A store of Rust crates, through which their metadata can be accessed. |
ea8adc8c XL |
176 | /// |
177 | /// Note that this trait should probably not be expanding today. All new | |
178 | /// functionality should be driven through queries instead! | |
179 | /// | |
180 | /// If you find a method on this trait named `{name}_untracked` it signifies | |
181 | /// that it's *not* tracked for dependency information throughout compilation | |
182 | /// (it'd break incremental compilation) and should only be called pre-HIR (e.g. | |
183 | /// during resolve) | |
8bb4bdeb | 184 | pub trait CrateStore { |
60c5eb7d | 185 | fn as_any(&self) -> &dyn Any; |
8bb4bdeb | 186 | |
92a42be0 | 187 | // resolve |
32a655c1 | 188 | fn def_key(&self, def: DefId) -> DefKey; |
29967ef6 | 189 | fn def_kind(&self, def: DefId) -> DefKind; |
ba9703b0 XL |
190 | fn def_path(&self, def: DefId) -> DefPath; |
191 | fn def_path_hash(&self, def: DefId) -> DefPathHash; | |
3dfed10e XL |
192 | fn all_def_path_hashes_and_def_ids(&self, cnum: CrateNum) -> Vec<(DefPathHash, DefId)>; |
193 | fn num_def_ids(&self, cnum: CrateNum) -> usize; | |
92a42be0 | 194 | |
ea8adc8c | 195 | // "queries" used in resolve that aren't tracked for incremental compilation |
ea8adc8c | 196 | fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; |
48663c56 | 197 | fn crate_is_private_dep_untracked(&self, cnum: CrateNum) -> bool; |
abe05a73 | 198 | fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; |
ea8adc8c | 199 | fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; |
7453a54e | 200 | |
92a42be0 SL |
201 | // This is basically a 1-based range of ints, which is a little |
202 | // silly - I may fix that. | |
ea8adc8c | 203 | fn crates_untracked(&self) -> Vec<CrateNum>; |
92a42be0 SL |
204 | |
205 | // utility functions | |
416331ca | 206 | fn encode_metadata(&self, tcx: TyCtxt<'_>) -> EncodedMetadata; |
92a42be0 | 207 | fn metadata_encoding_version(&self) -> &[u8]; |
60c5eb7d | 208 | fn allocator_kind(&self) -> Option<AllocatorKind>; |
92a42be0 SL |
209 | } |
210 | ||
8faf50e0 | 211 | pub type CrateStoreDyn = dyn CrateStore + sync::Sync; |
94b46f34 | 212 | |
ea8adc8c XL |
213 | // This method is used when generating the command line to pass through to |
214 | // system linker. The linker expects undefined symbols on the left of the | |
215 | // command line to be defined in libraries on the right, not the other way | |
216 | // around. For more info, see some comments in the add_used_library function | |
217 | // below. | |
218 | // | |
219 | // In order to get this left-to-right dependency ordering, we perform a | |
220 | // topological sort of all crates putting the leaves at the right-most | |
221 | // positions. | |
dc9dc135 | 222 | pub fn used_crates(tcx: TyCtxt<'_>, prefer: LinkagePreference) -> Vec<(CrateNum, LibSource)> { |
dfeec247 XL |
223 | let mut libs = tcx |
224 | .crates() | |
ea8adc8c XL |
225 | .iter() |
226 | .cloned() | |
227 | .filter_map(|cnum| { | |
228 | if tcx.dep_kind(cnum).macros_only() { | |
dfeec247 | 229 | return None; |
ea8adc8c XL |
230 | } |
231 | let source = tcx.used_crate_source(cnum); | |
232 | let path = match prefer { | |
233 | LinkagePreference::RequireDynamic => source.dylib.clone().map(|p| p.0), | |
234 | LinkagePreference::RequireStatic => source.rlib.clone().map(|p| p.0), | |
235 | }; | |
236 | let path = match path { | |
237 | Some(p) => LibSource::Some(p), | |
238 | None => { | |
239 | if source.rmeta.is_some() { | |
240 | LibSource::MetadataOnly | |
241 | } else { | |
242 | LibSource::None | |
243 | } | |
244 | } | |
245 | }; | |
246 | Some((cnum, path)) | |
247 | }) | |
248 | .collect::<Vec<_>>(); | |
dc9dc135 XL |
249 | let mut ordering = tcx.postorder_cnums(LOCAL_CRATE).to_owned(); |
250 | ordering.reverse(); | |
dfeec247 | 251 | libs.sort_by_cached_key(|&(a, _)| ordering.iter().position(|x| *x == a)); |
ea8adc8c XL |
252 | libs |
253 | } |