]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | //! Validates all used crates and extern libraries and loads their metadata |
223e47cc | 2 | |
3dfed10e XL |
3 | use crate::dynamic_lib::DynamicLibrary; |
4 | use crate::locator::{CrateError, CrateLocator, CratePaths}; | |
dfeec247 | 5 | use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}; |
92a42be0 | 6 | |
3dfed10e XL |
7 | use rustc_ast::expand::allocator::AllocatorKind; |
8 | use rustc_ast::{self as ast, *}; | |
f9f354fc | 9 | use rustc_data_structures::fx::FxHashSet; |
b7449926 | 10 | use rustc_data_structures::svh::Svh; |
60c5eb7d | 11 | use rustc_data_structures::sync::Lrc; |
dfeec247 | 12 | use rustc_expand::base::SyntaxExtension; |
f035d41b | 13 | use rustc_hir::def_id::{CrateNum, LocalDefId, LOCAL_CRATE}; |
ba9703b0 | 14 | use rustc_hir::definitions::Definitions; |
60c5eb7d | 15 | use rustc_index::vec::IndexVec; |
3dfed10e XL |
16 | use rustc_middle::middle::cstore::{CrateDepKind, CrateSource, ExternCrate}; |
17 | use rustc_middle::middle::cstore::{ExternCrateSource, MetadataLoaderDyn}; | |
ba9703b0 | 18 | use rustc_middle::ty::TyCtxt; |
f035d41b | 19 | use rustc_session::config::{self, CrateType, ExternLocation}; |
f9f354fc | 20 | use rustc_session::lint; |
ba9703b0 XL |
21 | use rustc_session::output::validate_crate_name; |
22 | use rustc_session::search_paths::PathKind; | |
23 | use rustc_session::{CrateDisambiguator, Session}; | |
dfeec247 XL |
24 | use rustc_span::edition::Edition; |
25 | use rustc_span::symbol::{sym, Symbol}; | |
26 | use rustc_span::{Span, DUMMY_SP}; | |
83c7162d | 27 | use rustc_target::spec::{PanicStrategy, TargetTriple}; |
dfeec247 | 28 | |
e1599b0c | 29 | use proc_macro::bridge::client::ProcMacro; |
dfeec247 | 30 | use std::path::Path; |
3dfed10e XL |
31 | use std::{cmp, env, fs}; |
32 | use tracing::{debug, info}; | |
60c5eb7d XL |
33 | |
34 | #[derive(Clone)] | |
35 | pub struct CStore { | |
36 | metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>, | |
37 | injected_panic_runtime: Option<CrateNum>, | |
38 | /// This crate needs an allocator and either provides it itself, or finds it in a dependency. | |
39 | /// If the above is true, then this field denotes the kind of the found allocator. | |
40 | allocator_kind: Option<AllocatorKind>, | |
41 | /// This crate has a `#[global_allocator]` item. | |
42 | has_global_allocator: bool, | |
e9174d1e SL |
43 | } |
44 | ||
c30ab7b3 | 45 | pub struct CrateLoader<'a> { |
e74abb32 XL |
46 | // Immutable configuration. |
47 | sess: &'a Session, | |
48 | metadata_loader: &'a MetadataLoaderDyn, | |
476ff2be | 49 | local_crate_name: Symbol, |
e74abb32 XL |
50 | // Mutable output. |
51 | cstore: CStore, | |
f9f354fc | 52 | used_extern_options: FxHashSet<Symbol>, |
223e47cc LB |
53 | } |
54 | ||
60c5eb7d XL |
55 | pub enum LoadedMacro { |
56 | MacroDef(ast::Item, Edition), | |
57 | ProcMacro(SyntaxExtension), | |
58 | } | |
59 | ||
60 | crate struct Library { | |
61 | pub source: CrateSource, | |
62 | pub metadata: MetadataBlob, | |
1a4d82fc | 63 | } |
e9174d1e | 64 | |
a7813a04 | 65 | enum LoadResult { |
9e0c209e | 66 | Previous(CrateNum), |
c30ab7b3 | 67 | Loaded(Library), |
a7813a04 XL |
68 | } |
69 | ||
74b04a01 XL |
70 | /// A reference to `CrateMetadata` that can also give access to whole crate store when necessary. |
71 | #[derive(Clone, Copy)] | |
72 | crate struct CrateMetadataRef<'a> { | |
73 | pub cdata: &'a CrateMetadata, | |
74 | pub cstore: &'a CStore, | |
75 | } | |
76 | ||
77 | impl std::ops::Deref for CrateMetadataRef<'_> { | |
78 | type Target = CrateMetadata; | |
79 | ||
80 | fn deref(&self) -> &Self::Target { | |
81 | self.cdata | |
82 | } | |
83 | } | |
84 | ||
3dfed10e XL |
85 | struct CrateDump<'a>(&'a CStore); |
86 | ||
87 | impl<'a> std::fmt::Debug for CrateDump<'a> { | |
88 | fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | |
89 | writeln!(fmt, "resolved crates:")?; | |
90 | // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here | |
91 | // that aggregates the value (and any errors that could happen). | |
92 | let mut res = Ok(()); | |
93 | self.0.iter_crate_data(|cnum, data| { | |
94 | res = res.and( | |
95 | try { | |
96 | writeln!(fmt, " name: {}", data.name())?; | |
97 | writeln!(fmt, " cnum: {}", cnum)?; | |
98 | writeln!(fmt, " hash: {}", data.hash())?; | |
99 | writeln!(fmt, " reqd: {:?}", data.dep_kind())?; | |
100 | let CrateSource { dylib, rlib, rmeta } = data.source(); | |
101 | if let Some(dylib) = dylib { | |
102 | writeln!(fmt, " dylib: {}", dylib.0.display())?; | |
103 | } | |
104 | if let Some(rlib) = rlib { | |
105 | writeln!(fmt, " rlib: {}", rlib.0.display())?; | |
106 | } | |
107 | if let Some(rmeta) = rmeta { | |
108 | writeln!(fmt, " rmeta: {}", rmeta.0.display())?; | |
109 | } | |
110 | }, | |
111 | ); | |
112 | }); | |
113 | res | |
114 | } | |
60c5eb7d XL |
115 | } |
116 | ||
117 | impl CStore { | |
118 | crate fn from_tcx(tcx: TyCtxt<'_>) -> &CStore { | |
119 | tcx.cstore_as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`") | |
120 | } | |
121 | ||
122 | fn alloc_new_crate_num(&mut self) -> CrateNum { | |
123 | self.metas.push(None); | |
124 | CrateNum::new(self.metas.len() - 1) | |
125 | } | |
126 | ||
74b04a01 XL |
127 | crate fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> { |
128 | let cdata = self.metas[cnum] | |
dfeec247 | 129 | .as_ref() |
74b04a01 XL |
130 | .unwrap_or_else(|| panic!("Failed to get crate data for {:?}", cnum)); |
131 | CrateMetadataRef { cdata, cstore: self } | |
60c5eb7d XL |
132 | } |
133 | ||
134 | fn set_crate_data(&mut self, cnum: CrateNum, data: CrateMetadata) { | |
135 | assert!(self.metas[cnum].is_none(), "Overwriting crate metadata entry"); | |
136 | self.metas[cnum] = Some(Lrc::new(data)); | |
137 | } | |
138 | ||
139 | crate fn iter_crate_data(&self, mut f: impl FnMut(CrateNum, &CrateMetadata)) { | |
140 | for (cnum, data) in self.metas.iter_enumerated() { | |
141 | if let Some(data) = data { | |
142 | f(cnum, data); | |
143 | } | |
144 | } | |
145 | } | |
146 | ||
147 | fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) { | |
148 | if !deps.contains(&cnum) { | |
149 | let data = self.get_crate_data(cnum); | |
150 | for &dep in data.dependencies().iter() { | |
151 | if dep != cnum { | |
152 | self.push_dependencies_in_postorder(deps, dep); | |
153 | } | |
154 | } | |
155 | ||
156 | deps.push(cnum); | |
157 | } | |
158 | } | |
159 | ||
160 | crate fn crate_dependencies_in_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> { | |
161 | let mut deps = Vec::new(); | |
162 | if cnum == LOCAL_CRATE { | |
163 | self.iter_crate_data(|cnum, _| self.push_dependencies_in_postorder(&mut deps, cnum)); | |
164 | } else { | |
165 | self.push_dependencies_in_postorder(&mut deps, cnum); | |
166 | } | |
167 | deps | |
168 | } | |
169 | ||
170 | fn crate_dependencies_in_reverse_postorder(&self, cnum: CrateNum) -> Vec<CrateNum> { | |
171 | let mut deps = self.crate_dependencies_in_postorder(cnum); | |
172 | deps.reverse(); | |
173 | deps | |
174 | } | |
175 | ||
176 | crate fn injected_panic_runtime(&self) -> Option<CrateNum> { | |
177 | self.injected_panic_runtime | |
178 | } | |
179 | ||
180 | crate fn allocator_kind(&self) -> Option<AllocatorKind> { | |
181 | self.allocator_kind | |
182 | } | |
183 | ||
184 | crate fn has_global_allocator(&self) -> bool { | |
185 | self.has_global_allocator | |
186 | } | |
187 | } | |
188 | ||
c30ab7b3 | 189 | impl<'a> CrateLoader<'a> { |
e74abb32 XL |
190 | pub fn new( |
191 | sess: &'a Session, | |
192 | metadata_loader: &'a MetadataLoaderDyn, | |
193 | local_crate_name: &str, | |
194 | ) -> Self { | |
c30ab7b3 | 195 | CrateLoader { |
3b2f2976 | 196 | sess, |
e74abb32 | 197 | metadata_loader, |
476ff2be | 198 | local_crate_name: Symbol::intern(local_crate_name), |
60c5eb7d XL |
199 | cstore: CStore { |
200 | // We add an empty entry for LOCAL_CRATE (which maps to zero) in | |
201 | // order to make array indices in `metas` match with the | |
202 | // corresponding `CrateNum`. This first entry will always remain | |
203 | // `None`. | |
204 | metas: IndexVec::from_elem_n(None, 1), | |
205 | injected_panic_runtime: None, | |
206 | allocator_kind: None, | |
207 | has_global_allocator: false, | |
dfeec247 | 208 | }, |
f9f354fc | 209 | used_extern_options: Default::default(), |
223e47cc | 210 | } |
223e47cc | 211 | } |
223e47cc | 212 | |
e74abb32 XL |
213 | pub fn cstore(&self) -> &CStore { |
214 | &self.cstore | |
215 | } | |
216 | ||
217 | pub fn into_cstore(self) -> CStore { | |
218 | self.cstore | |
219 | } | |
220 | ||
60c5eb7d | 221 | fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> { |
1a4d82fc | 222 | let mut ret = None; |
92a42be0 | 223 | self.cstore.iter_crate_data(|cnum, data| { |
dfeec247 | 224 | if data.name() != name { |
1b1a35ee | 225 | tracing::trace!("{} did not match {}", data.name(), name); |
dfeec247 XL |
226 | return; |
227 | } | |
223e47cc | 228 | |
1a4d82fc | 229 | match hash { |
dfeec247 XL |
230 | Some(hash) if hash == data.hash() => { |
231 | ret = Some(cnum); | |
232 | return; | |
233 | } | |
1b1a35ee XL |
234 | Some(hash) => { |
235 | debug!("actual hash {} did not match expected {}", hash, data.hash()); | |
236 | return; | |
237 | } | |
1a4d82fc JJ |
238 | None => {} |
239 | } | |
223e47cc | 240 | |
85aaf69f SL |
241 | // When the hash is None we're dealing with a top-level dependency |
242 | // in which case we may have a specification on the command line for | |
243 | // this library. Even though an upstream library may have loaded | |
244 | // something of the same name, we have to make sure it was loaded | |
245 | // from the exact same location as well. | |
1a4d82fc JJ |
246 | // |
247 | // We're also sure to compare *paths*, not actual byte slices. The | |
248 | // `source` stores paths which are normalized which may be different | |
249 | // from the strings on the command line. | |
74b04a01 | 250 | let source = self.cstore.get_crate_data(cnum).cdata.source(); |
60c5eb7d | 251 | if let Some(entry) = self.sess.opts.externs.get(&name.as_str()) { |
b7449926 | 252 | // Only use `--extern crate_name=path` here, not `--extern crate_name`. |
60c5eb7d XL |
253 | if let Some(mut files) = entry.files() { |
254 | if files.any(|l| { | |
3dfed10e XL |
255 | let l = fs::canonicalize(l).unwrap_or(l.clone().into()); |
256 | source.dylib.as_ref().map(|p| &p.0) == Some(&l) | |
257 | || source.rlib.as_ref().map(|p| &p.0) == Some(&l) | |
60c5eb7d XL |
258 | }) { |
259 | ret = Some(cnum); | |
260 | } | |
1a4d82fc | 261 | } |
dfeec247 | 262 | return; |
85aaf69f SL |
263 | } |
264 | ||
265 | // Alright, so we've gotten this far which means that `data` has the | |
266 | // right name, we don't have a hash, and we don't have a --extern | |
267 | // pointing for ourselves. We're still not quite yet done because we | |
268 | // have to make sure that this crate was found in the crate lookup | |
269 | // path (this is a top-level dependency) as we don't want to | |
270 | // implicitly load anything inside the dependency lookup path. | |
dfeec247 XL |
271 | let prev_kind = source |
272 | .dylib | |
273 | .as_ref() | |
274 | .or(source.rlib.as_ref()) | |
275 | .or(source.rmeta.as_ref()) | |
276 | .expect("No sources for crate") | |
277 | .1; | |
60c5eb7d | 278 | if kind.matches(prev_kind) { |
85aaf69f | 279 | ret = Some(cnum); |
1b1a35ee XL |
280 | } else { |
281 | debug!( | |
282 | "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}", | |
283 | name, kind, prev_kind | |
284 | ); | |
1a4d82fc JJ |
285 | } |
286 | }); | |
ba9703b0 | 287 | ret |
1a4d82fc | 288 | } |
223e47cc | 289 | |
3dfed10e | 290 | fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { |
54a0048b | 291 | // Check for (potential) conflicts with the local crate |
dfeec247 XL |
292 | if self.local_crate_name == root.name() |
293 | && self.sess.local_crate_disambiguator() == root.disambiguator() | |
294 | { | |
3dfed10e | 295 | return Err(CrateError::SymbolConflictsCurrent(root.name())); |
54a0048b SL |
296 | } |
297 | ||
54a0048b | 298 | // Check for conflicts with any crate loaded so far |
3dfed10e | 299 | let mut res = Ok(()); |
54a0048b | 300 | self.cstore.iter_crate_data(|_, other| { |
60c5eb7d | 301 | if other.name() == root.name() && // same crate-name |
3dfed10e | 302 | other.disambiguator() == root.disambiguator() && // same crate-disambiguator |
dfeec247 XL |
303 | other.hash() != root.hash() |
304 | { | |
305 | // but different SVH | |
3dfed10e | 306 | res = Err(CrateError::SymbolConflictsOthers(root.name())); |
54a0048b SL |
307 | } |
308 | }); | |
3dfed10e XL |
309 | |
310 | res | |
54a0048b SL |
311 | } |
312 | ||
532ac7d7 XL |
313 | fn register_crate( |
314 | &mut self, | |
315 | host_lib: Option<Library>, | |
e74abb32 | 316 | root: Option<&CratePaths>, |
532ac7d7 | 317 | lib: Library, |
3dfed10e | 318 | dep_kind: CrateDepKind, |
dfeec247 | 319 | name: Symbol, |
3dfed10e | 320 | ) -> Result<CrateNum, CrateError> { |
e74abb32 XL |
321 | let _prof_timer = self.sess.prof.generic_activity("metadata_register_crate"); |
322 | ||
323 | let Library { source, metadata } = lib; | |
324 | let crate_root = metadata.get_root(); | |
60c5eb7d | 325 | let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); |
3dfed10e | 326 | self.verify_no_symbol_conflicts(&crate_root)?; |
b039eaaf | 327 | |
dfeec247 XL |
328 | let private_dep = |
329 | self.sess.opts.externs.get(&name.as_str()).map(|e| e.is_private_dep).unwrap_or(false); | |
48663c56 | 330 | |
223e47cc | 331 | // Claim this crate number and cache it |
94b46f34 | 332 | let cnum = self.cstore.alloc_new_crate_num(); |
1a4d82fc | 333 | |
3dfed10e XL |
334 | info!( |
335 | "register crate `{}` (cnum = {}. private_dep = {})", | |
336 | crate_root.name(), | |
337 | cnum, | |
338 | private_dep | |
339 | ); | |
340 | ||
e74abb32 | 341 | // Maintain a reference to the top most crate. |
1a4d82fc | 342 | // Stash paths for top-most crate locally if necessary. |
e74abb32 XL |
343 | let crate_paths; |
344 | let root = if let Some(root) = root { | |
345 | root | |
1a4d82fc | 346 | } else { |
60c5eb7d | 347 | crate_paths = CratePaths::new(crate_root.name(), source.clone()); |
e74abb32 | 348 | &crate_paths |
1a4d82fc | 349 | }; |
1a4d82fc | 350 | |
3dfed10e | 351 | let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, dep_kind)?; |
1a4d82fc | 352 | |
60c5eb7d | 353 | let raw_proc_macros = if crate_root.is_proc_macro_crate() { |
e74abb32 XL |
354 | let temp_root; |
355 | let (dlsym_source, dlsym_root) = match &host_lib { | |
dfeec247 XL |
356 | Some(host_lib) => (&host_lib.source, { |
357 | temp_root = host_lib.metadata.get_root(); | |
358 | &temp_root | |
359 | }), | |
e74abb32 XL |
360 | None => (&source, &crate_root), |
361 | }; | |
362 | let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); | |
3dfed10e | 363 | Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?) |
60c5eb7d XL |
364 | } else { |
365 | None | |
366 | }; | |
e1599b0c | 367 | |
3dfed10e XL |
368 | let crate_metadata = CrateMetadata::new( |
369 | self.sess, | |
370 | metadata, | |
371 | crate_root, | |
372 | raw_proc_macros, | |
3b2f2976 | 373 | cnum, |
3dfed10e XL |
374 | cnum_map, |
375 | dep_kind, | |
376 | source, | |
377 | private_dep, | |
378 | host_hash, | |
dfeec247 | 379 | ); |
1a4d82fc | 380 | |
3dfed10e XL |
381 | self.cstore.set_crate_data(cnum, crate_metadata); |
382 | ||
383 | Ok(cnum) | |
1a4d82fc JJ |
384 | } |
385 | ||
dc9dc135 | 386 | fn load_proc_macro<'b>( |
e74abb32 | 387 | &self, |
60c5eb7d | 388 | locator: &mut CrateLocator<'b>, |
532ac7d7 | 389 | path_kind: PathKind, |
3dfed10e | 390 | ) -> Result<Option<(LoadResult, Option<Library>)>, CrateError> |
532ac7d7 | 391 | where |
dc9dc135 | 392 | 'a: 'b, |
532ac7d7 | 393 | { |
60c5eb7d | 394 | // Use a new crate locator so trying to load a proc macro doesn't affect the error |
532ac7d7 | 395 | // message we emit |
60c5eb7d | 396 | let mut proc_macro_locator = locator.clone(); |
532ac7d7 XL |
397 | |
398 | // Try to load a proc macro | |
399 | proc_macro_locator.is_proc_macro = Some(true); | |
400 | ||
401 | // Load the proc macro crate for the target | |
402 | let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros { | |
403 | proc_macro_locator.reset(); | |
404 | let result = match self.load(&mut proc_macro_locator)? { | |
3dfed10e XL |
405 | Some(LoadResult::Previous(cnum)) => { |
406 | return Ok(Some((LoadResult::Previous(cnum), None))); | |
407 | } | |
408 | Some(LoadResult::Loaded(library)) => Some(LoadResult::Loaded(library)), | |
409 | None => return Ok(None), | |
532ac7d7 | 410 | }; |
60c5eb7d XL |
411 | locator.hash = locator.host_hash; |
412 | // Use the locator when looking for the host proc macro crate, as that is required | |
532ac7d7 | 413 | // so we want it to affect the error message |
60c5eb7d | 414 | (locator, result) |
532ac7d7 XL |
415 | } else { |
416 | (&mut proc_macro_locator, None) | |
417 | }; | |
418 | ||
419 | // Load the proc macro crate for the host | |
420 | ||
421 | locator.reset(); | |
422 | locator.is_proc_macro = Some(true); | |
423 | locator.target = &self.sess.host; | |
424 | locator.triple = TargetTriple::from_triple(config::host_triple()); | |
425 | locator.filesearch = self.sess.host_filesearch(path_kind); | |
426 | ||
3dfed10e XL |
427 | let host_result = match self.load(locator)? { |
428 | Some(host_result) => host_result, | |
429 | None => return Ok(None), | |
430 | }; | |
532ac7d7 | 431 | |
3dfed10e | 432 | Ok(Some(if self.sess.opts.debugging_opts.dual_proc_macros { |
532ac7d7 XL |
433 | let host_result = match host_result { |
434 | LoadResult::Previous(..) => { | |
435 | panic!("host and target proc macros must be loaded in lock-step") | |
436 | } | |
dfeec247 | 437 | LoadResult::Loaded(library) => library, |
532ac7d7 XL |
438 | }; |
439 | (target_result.unwrap(), Some(host_result)) | |
440 | } else { | |
441 | (host_result, None) | |
3dfed10e | 442 | })) |
532ac7d7 XL |
443 | } |
444 | ||
b7449926 XL |
445 | fn resolve_crate<'b>( |
446 | &'b mut self, | |
b7449926 | 447 | name: Symbol, |
b7449926 | 448 | span: Span, |
3dfed10e | 449 | dep_kind: CrateDepKind, |
e74abb32 XL |
450 | dep: Option<(&'b CratePaths, &'b CrateDep)>, |
451 | ) -> CrateNum { | |
f9f354fc XL |
452 | if dep.is_none() { |
453 | self.used_extern_options.insert(name); | |
454 | } | |
3dfed10e XL |
455 | self.maybe_resolve_crate(name, dep_kind, dep) |
456 | .unwrap_or_else(|err| err.report(self.sess, span)) | |
e74abb32 XL |
457 | } |
458 | ||
459 | fn maybe_resolve_crate<'b>( | |
460 | &'b mut self, | |
461 | name: Symbol, | |
3dfed10e | 462 | mut dep_kind: CrateDepKind, |
e74abb32 | 463 | dep: Option<(&'b CratePaths, &'b CrateDep)>, |
3dfed10e | 464 | ) -> Result<CrateNum, CrateError> { |
e74abb32 | 465 | info!("resolving crate `{}`", name); |
3dfed10e XL |
466 | if !name.as_str().is_ascii() { |
467 | return Err(CrateError::NonAsciiName(name)); | |
468 | } | |
e74abb32 XL |
469 | let (root, hash, host_hash, extra_filename, path_kind) = match dep { |
470 | Some((root, dep)) => ( | |
471 | Some(root), | |
60c5eb7d XL |
472 | Some(dep.hash), |
473 | dep.host_hash, | |
e74abb32 | 474 | Some(&dep.extra_filename[..]), |
60c5eb7d | 475 | PathKind::Dependency, |
e74abb32 XL |
476 | ), |
477 | None => (None, None, None, None, PathKind::Crate), | |
478 | }; | |
476ff2be | 479 | let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { |
532ac7d7 | 480 | (LoadResult::Previous(cnum), None) |
476ff2be SL |
481 | } else { |
482 | info!("falling back to a load"); | |
60c5eb7d XL |
483 | let mut locator = CrateLocator::new( |
484 | self.sess, | |
485 | self.metadata_loader, | |
486 | name, | |
48663c56 | 487 | hash, |
e74abb32 | 488 | host_hash, |
48663c56 | 489 | extra_filename, |
60c5eb7d XL |
490 | false, // is_host |
491 | path_kind, | |
3b2f2976 | 492 | root, |
60c5eb7d XL |
493 | Some(false), // is_proc_macro |
494 | ); | |
476ff2be | 495 | |
3dfed10e XL |
496 | match self.load(&mut locator)? { |
497 | Some(res) => (res, None), | |
498 | None => { | |
499 | dep_kind = CrateDepKind::MacrosOnly; | |
500 | match self.load_proc_macro(&mut locator, path_kind)? { | |
501 | Some(res) => res, | |
502 | None => return Err(locator.into_error()), | |
503 | } | |
504 | } | |
505 | } | |
92a42be0 SL |
506 | }; |
507 | ||
508 | match result { | |
532ac7d7 | 509 | (LoadResult::Previous(cnum), None) => { |
92a42be0 | 510 | let data = self.cstore.get_crate_data(cnum); |
60c5eb7d | 511 | if data.is_proc_macro_crate() { |
3dfed10e | 512 | dep_kind = CrateDepKind::MacrosOnly; |
e9174d1e | 513 | } |
60c5eb7d | 514 | data.update_dep_kind(|data_dep_kind| cmp::max(data_dep_kind, dep_kind)); |
e74abb32 | 515 | Ok(cnum) |
92a42be0 | 516 | } |
532ac7d7 | 517 | (LoadResult::Loaded(library), host_library) => { |
3dfed10e | 518 | self.register_crate(host_library, root, library, dep_kind, name) |
1a4d82fc | 519 | } |
dfeec247 | 520 | _ => panic!(), |
1a4d82fc JJ |
521 | } |
522 | } | |
523 | ||
3dfed10e XL |
524 | fn load(&self, locator: &mut CrateLocator<'_>) -> Result<Option<LoadResult>, CrateError> { |
525 | let library = match locator.maybe_load_library_crate()? { | |
526 | Some(library) => library, | |
527 | None => return Ok(None), | |
528 | }; | |
a7813a04 XL |
529 | |
530 | // In the case that we're loading a crate, but not matching | |
531 | // against a hash, we could load a crate which has the same hash | |
532 | // as an already loaded crate. If this is the case prevent | |
533 | // duplicates by just using the first crate. | |
534 | // | |
535 | // Note that we only do this for target triple crates, though, as we | |
536 | // don't want to match a host crate against an equivalent target one | |
537 | // already loaded. | |
9e0c209e | 538 | let root = library.metadata.get_root(); |
3dfed10e | 539 | Ok(Some(if locator.triple == self.sess.opts.target_triple { |
a7813a04 XL |
540 | let mut result = LoadResult::Loaded(library); |
541 | self.cstore.iter_crate_data(|cnum, data| { | |
60c5eb7d XL |
542 | if data.name() == root.name() && root.hash() == data.hash() { |
543 | assert!(locator.hash.is_none()); | |
9e0c209e | 544 | info!("load success, going to previous cnum: {}", cnum); |
a7813a04 XL |
545 | result = LoadResult::Previous(cnum); |
546 | } | |
547 | }); | |
3dfed10e | 548 | result |
a7813a04 | 549 | } else { |
3dfed10e XL |
550 | LoadResult::Loaded(library) |
551 | })) | |
a7813a04 XL |
552 | } |
553 | ||
60c5eb7d | 554 | fn update_extern_crate(&self, cnum: CrateNum, extern_crate: ExternCrate) { |
54a0048b | 555 | let cmeta = self.cstore.get_crate_data(cnum); |
60c5eb7d XL |
556 | if cmeta.update_extern_crate(extern_crate) { |
557 | // Propagate the extern crate info to dependencies if it was updated. | |
558 | let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; | |
559 | for &dep_cnum in cmeta.dependencies().iter() { | |
560 | self.update_extern_crate(dep_cnum, extern_crate); | |
561 | } | |
54a0048b SL |
562 | } |
563 | } | |
564 | ||
1a4d82fc | 565 | // Go through the crate metadata and load any crates that it references |
dfeec247 XL |
566 | fn resolve_crate_deps( |
567 | &mut self, | |
568 | root: &CratePaths, | |
569 | crate_root: &CrateRoot<'_>, | |
570 | metadata: &MetadataBlob, | |
571 | krate: CrateNum, | |
3dfed10e XL |
572 | dep_kind: CrateDepKind, |
573 | ) -> Result<CrateNumMap, CrateError> { | |
1a4d82fc | 574 | debug!("resolving deps of external crate"); |
60c5eb7d | 575 | if crate_root.is_proc_macro_crate() { |
3dfed10e | 576 | return Ok(CrateNumMap::new()); |
476ff2be SL |
577 | } |
578 | ||
579 | // The map from crate numbers in the crate we're resolving to local crate numbers. | |
580 | // We map 0 and all other holes in the map to our parent crate. The "additional" | |
3157f602 | 581 | // self-dependencies should be harmless. |
3dfed10e XL |
582 | let deps = crate_root.decode_crate_deps(metadata); |
583 | let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len()); | |
584 | crate_num_map.push(krate); | |
585 | for dep in deps { | |
586 | info!( | |
587 | "resolving dep crate {} hash: `{}` extra filename: `{}`", | |
588 | dep.name, dep.hash, dep.extra_filename | |
589 | ); | |
590 | let dep_kind = match dep_kind { | |
591 | CrateDepKind::MacrosOnly => CrateDepKind::MacrosOnly, | |
592 | _ => dep.kind, | |
593 | }; | |
594 | let cnum = self.maybe_resolve_crate(dep.name, dep_kind, Some((root, &dep)))?; | |
595 | crate_num_map.push(cnum); | |
596 | } | |
597 | ||
598 | debug!("resolve_crate_deps: cnum_map for {:?} is {:?}", krate, crate_num_map); | |
599 | Ok(crate_num_map) | |
1a4d82fc JJ |
600 | } |
601 | ||
dfeec247 XL |
602 | fn dlsym_proc_macros( |
603 | &self, | |
604 | path: &Path, | |
605 | disambiguator: CrateDisambiguator, | |
3dfed10e | 606 | ) -> Result<&'static [ProcMacro], CrateError> { |
c30ab7b3 SL |
607 | // Make sure the path contains a / or the linker will search for it. |
608 | let path = env::current_dir().unwrap().join(path); | |
f9f354fc | 609 | let lib = match DynamicLibrary::open(&path) { |
c30ab7b3 | 610 | Ok(lib) => lib, |
3dfed10e | 611 | Err(s) => return Err(CrateError::DlOpen(s)), |
c30ab7b3 SL |
612 | }; |
613 | ||
e74abb32 | 614 | let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator); |
a1dfa0c6 | 615 | let decls = unsafe { |
c30ab7b3 SL |
616 | let sym = match lib.symbol(&sym) { |
617 | Ok(f) => f, | |
3dfed10e | 618 | Err(s) => return Err(CrateError::DlSym(s)), |
c30ab7b3 | 619 | }; |
a1dfa0c6 | 620 | *(sym as *const &[ProcMacro]) |
c30ab7b3 SL |
621 | }; |
622 | ||
c30ab7b3 SL |
623 | // Intentionally leak the dynamic library. We can't ever unload it |
624 | // since the library can make things that will live arbitrarily long. | |
e1599b0c | 625 | std::mem::forget(lib); |
a1dfa0c6 | 626 | |
3dfed10e | 627 | Ok(decls) |
1a4d82fc JJ |
628 | } |
629 | ||
a7813a04 XL |
630 | fn inject_panic_runtime(&mut self, krate: &ast::Crate) { |
631 | // If we're only compiling an rlib, then there's no need to select a | |
632 | // panic runtime, so we just skip this section entirely. | |
f9f354fc | 633 | let any_non_rlib = self.sess.crate_types().iter().any(|ct| *ct != CrateType::Rlib); |
a7813a04 XL |
634 | if !any_non_rlib { |
635 | info!("panic runtime injection skipped, only generating rlib"); | |
dfeec247 | 636 | return; |
a7813a04 XL |
637 | } |
638 | ||
639 | // If we need a panic runtime, we try to find an existing one here. At | |
640 | // the same time we perform some general validation of the DAG we've got | |
641 | // going such as ensuring everything has a compatible panic strategy. | |
642 | // | |
643 | // The logic for finding the panic runtime here is pretty much the same | |
644 | // as the allocator case with the only addition that the panic strategy | |
645 | // compilation mode also comes into play. | |
c30ab7b3 | 646 | let desired_strategy = self.sess.panic_strategy(); |
a7813a04 | 647 | let mut runtime_found = false; |
3dfed10e XL |
648 | let mut needs_panic_runtime = |
649 | self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime); | |
7cac9316 | 650 | |
a7813a04 | 651 | self.cstore.iter_crate_data(|cnum, data| { |
60c5eb7d XL |
652 | needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime(); |
653 | if data.is_panic_runtime() { | |
a7813a04 XL |
654 | // Inject a dependency from all #![needs_panic_runtime] to this |
655 | // #![panic_runtime] crate. | |
dfeec247 XL |
656 | self.inject_dependency_if(cnum, "a panic runtime", &|data| { |
657 | data.needs_panic_runtime() | |
658 | }); | |
3dfed10e | 659 | runtime_found = runtime_found || data.dep_kind() == CrateDepKind::Explicit; |
a7813a04 XL |
660 | } |
661 | }); | |
662 | ||
663 | // If an explicitly linked and matching panic runtime was found, or if | |
664 | // we just don't need one at all, then we're done here and there's | |
665 | // nothing else to do. | |
666 | if !needs_panic_runtime || runtime_found { | |
dfeec247 | 667 | return; |
a7813a04 XL |
668 | } |
669 | ||
670 | // By this point we know that we (a) need a panic runtime and (b) no | |
671 | // panic runtime was explicitly linked. Here we just load an appropriate | |
672 | // default runtime for our panic strategy and then inject the | |
673 | // dependencies. | |
674 | // | |
675 | // We may resolve to an already loaded crate (as the crate may not have | |
676 | // been explicitly linked prior to this) and we may re-inject | |
677 | // dependencies again, but both of those situations are fine. | |
678 | // | |
679 | // Also note that we have yet to perform validation of the crate graph | |
680 | // in terms of everyone has a compatible panic runtime format, that's | |
681 | // performed later as part of the `dependency_format` module. | |
682 | let name = match desired_strategy { | |
3dfed10e XL |
683 | PanicStrategy::Unwind => sym::panic_unwind, |
684 | PanicStrategy::Abort => sym::panic_abort, | |
a7813a04 XL |
685 | }; |
686 | info!("panic runtime not found -- loading {}", name); | |
687 | ||
3dfed10e | 688 | let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); |
e74abb32 | 689 | let data = self.cstore.get_crate_data(cnum); |
a7813a04 XL |
690 | |
691 | // Sanity check the loaded crate to ensure it is indeed a panic runtime | |
692 | // and the panic strategy is indeed what we thought it was. | |
60c5eb7d | 693 | if !data.is_panic_runtime() { |
dfeec247 | 694 | self.sess.err(&format!("the crate `{}` is not a panic runtime", name)); |
a7813a04 | 695 | } |
60c5eb7d | 696 | if data.panic_strategy() != desired_strategy { |
dfeec247 XL |
697 | self.sess.err(&format!( |
698 | "the crate `{}` does not have the panic \ | |
a7813a04 | 699 | strategy `{}`", |
dfeec247 XL |
700 | name, |
701 | desired_strategy.desc() | |
702 | )); | |
a7813a04 XL |
703 | } |
704 | ||
60c5eb7d | 705 | self.cstore.injected_panic_runtime = Some(cnum); |
dfeec247 | 706 | self.inject_dependency_if(cnum, "a panic runtime", &|data| data.needs_panic_runtime()); |
8bb4bdeb XL |
707 | } |
708 | ||
041b39d2 | 709 | fn inject_profiler_runtime(&mut self) { |
f035d41b XL |
710 | if (self.sess.opts.debugging_opts.instrument_coverage |
711 | || self.sess.opts.debugging_opts.profile | |
712 | || self.sess.opts.cg.profile_generate.enabled()) | |
ba9703b0 XL |
713 | && !self.sess.opts.debugging_opts.no_profiler_runtime |
714 | { | |
041b39d2 XL |
715 | info!("loading profiler"); |
716 | ||
3dfed10e XL |
717 | let name = sym::profiler_builtins; |
718 | let cnum = self.resolve_crate(name, DUMMY_SP, CrateDepKind::Implicit, None); | |
e74abb32 | 719 | let data = self.cstore.get_crate_data(cnum); |
041b39d2 XL |
720 | |
721 | // Sanity check the loaded crate to ensure it is indeed a profiler runtime | |
60c5eb7d | 722 | if !data.is_profiler_runtime() { |
74b04a01 | 723 | self.sess.err("the crate `profiler_builtins` is not a profiler runtime"); |
041b39d2 XL |
724 | } |
725 | } | |
726 | } | |
727 | ||
60c5eb7d | 728 | fn inject_allocator_crate(&mut self, krate: &ast::Crate) { |
3dfed10e | 729 | self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) { |
416331ca | 730 | [span1, span2, ..] => { |
dfeec247 XL |
731 | self.sess |
732 | .struct_span_err(*span2, "cannot define multiple global allocators") | |
60c5eb7d | 733 | .span_label(*span2, "cannot define a new global allocator") |
74b04a01 | 734 | .span_label(*span1, "previous global allocator defined here") |
60c5eb7d | 735 | .emit(); |
416331ca XL |
736 | true |
737 | } | |
dfeec247 | 738 | spans => !spans.is_empty(), |
416331ca | 739 | }; |
041b39d2 XL |
740 | |
741 | // Check to see if we actually need an allocator. This desire comes | |
742 | // about through the `#![needs_allocator]` attribute and is typically | |
743 | // written down in liballoc. | |
3dfed10e | 744 | let mut needs_allocator = self.sess.contains_name(&krate.attrs, sym::needs_allocator); |
041b39d2 | 745 | self.cstore.iter_crate_data(|_, data| { |
60c5eb7d | 746 | needs_allocator = needs_allocator || data.needs_allocator(); |
e9174d1e | 747 | }); |
041b39d2 | 748 | if !needs_allocator { |
dfeec247 | 749 | return; |
041b39d2 | 750 | } |
e9174d1e | 751 | |
041b39d2 XL |
752 | // At this point we've determined that we need an allocator. Let's see |
753 | // if our compilation session actually needs an allocator based on what | |
754 | // we're emitting. | |
29967ef6 | 755 | let all_rlib = self.sess.crate_types().iter().all(|ct| matches!(*ct, CrateType::Rlib)); |
a1dfa0c6 | 756 | if all_rlib { |
dfeec247 | 757 | return; |
041b39d2 | 758 | } |
e9174d1e | 759 | |
041b39d2 XL |
760 | // Ok, we need an allocator. Not only that but we're actually going to |
761 | // create an artifact that needs one linked in. Let's go find the one | |
762 | // that we're going to link in. | |
e9174d1e | 763 | // |
041b39d2 XL |
764 | // First up we check for global allocators. Look at the crate graph here |
765 | // and see what's a global allocator, including if we ourselves are a | |
766 | // global allocator. | |
dfeec247 XL |
767 | let mut global_allocator = |
768 | self.cstore.has_global_allocator.then(|| Symbol::intern("this crate")); | |
041b39d2 | 769 | self.cstore.iter_crate_data(|_, data| { |
60c5eb7d | 770 | if !data.has_global_allocator() { |
dfeec247 | 771 | return; |
041b39d2 XL |
772 | } |
773 | match global_allocator { | |
60c5eb7d | 774 | Some(other_crate) => { |
dfeec247 XL |
775 | self.sess.err(&format!( |
776 | "the `#[global_allocator]` in {} \ | |
60c5eb7d | 777 | conflicts with global \ |
041b39d2 | 778 | allocator in: {}", |
dfeec247 XL |
779 | other_crate, |
780 | data.name() | |
781 | )); | |
041b39d2 | 782 | } |
60c5eb7d | 783 | None => global_allocator = Some(data.name()), |
041b39d2 XL |
784 | } |
785 | }); | |
786 | if global_allocator.is_some() { | |
60c5eb7d | 787 | self.cstore.allocator_kind = Some(AllocatorKind::Global); |
dfeec247 | 788 | return; |
041b39d2 | 789 | } |
e9174d1e | 790 | |
041b39d2 | 791 | // Ok we haven't found a global allocator but we still need an |
a1dfa0c6 XL |
792 | // allocator. At this point our allocator request is typically fulfilled |
793 | // by the standard library, denoted by the `#![default_lib_allocator]` | |
794 | // attribute. | |
3dfed10e | 795 | let mut has_default = self.sess.contains_name(&krate.attrs, sym::default_lib_allocator); |
a1dfa0c6 | 796 | self.cstore.iter_crate_data(|_, data| { |
60c5eb7d | 797 | if data.has_default_lib_allocator() { |
a1dfa0c6 | 798 | has_default = true; |
041b39d2 | 799 | } |
ea8adc8c XL |
800 | }); |
801 | ||
a1dfa0c6 | 802 | if !has_default { |
dfeec247 XL |
803 | self.sess.err( |
804 | "no global memory allocator found but one is \ | |
a1dfa0c6 | 805 | required; link to std or \ |
416331ca | 806 | add `#[global_allocator]` to a static item \ |
dfeec247 XL |
807 | that implements the GlobalAlloc trait.", |
808 | ); | |
e9174d1e | 809 | } |
60c5eb7d | 810 | self.cstore.allocator_kind = Some(AllocatorKind::Default); |
e9174d1e SL |
811 | } |
812 | ||
dfeec247 XL |
813 | fn inject_dependency_if( |
814 | &self, | |
815 | krate: CrateNum, | |
816 | what: &str, | |
817 | needs_dep: &dyn Fn(&CrateMetadata) -> bool, | |
818 | ) { | |
a7813a04 XL |
819 | // don't perform this validation if the session has errors, as one of |
820 | // those errors may indicate a circular dependency which could cause | |
821 | // this to stack overflow. | |
822 | if self.sess.has_errors() { | |
dfeec247 | 823 | return; |
a7813a04 XL |
824 | } |
825 | ||
e9174d1e | 826 | // Before we inject any dependencies, make sure we don't inject a |
a7813a04 XL |
827 | // circular dependency by validating that this crate doesn't |
828 | // transitively depend on any crates satisfying `needs_dep`. | |
60c5eb7d | 829 | for dep in self.cstore.crate_dependencies_in_reverse_postorder(krate) { |
3157f602 XL |
830 | let data = self.cstore.get_crate_data(dep); |
831 | if needs_dep(&data) { | |
dfeec247 XL |
832 | self.sess.err(&format!( |
833 | "the crate `{}` cannot depend \ | |
3157f602 XL |
834 | on a crate that needs {}, but \ |
835 | it depends on `{}`", | |
dfeec247 XL |
836 | self.cstore.get_crate_data(krate).name(), |
837 | what, | |
838 | data.name() | |
839 | )); | |
3157f602 XL |
840 | } |
841 | } | |
a7813a04 XL |
842 | |
843 | // All crates satisfying `needs_dep` do not explicitly depend on the | |
844 | // crate provided for this compile, but in order for this compilation to | |
845 | // be successfully linked we need to inject a dependency (to order the | |
846 | // crates on the command line correctly). | |
92a42be0 | 847 | self.cstore.iter_crate_data(|cnum, data| { |
a7813a04 | 848 | if !needs_dep(data) { |
dfeec247 | 849 | return; |
e9174d1e SL |
850 | } |
851 | ||
a7813a04 | 852 | info!("injecting a dep from {} to {}", cnum, krate); |
60c5eb7d | 853 | data.add_dependency(krate); |
e9174d1e | 854 | }); |
e9174d1e | 855 | } |
e9174d1e | 856 | |
f9f354fc XL |
857 | fn report_unused_deps(&mut self, krate: &ast::Crate) { |
858 | // Make a point span rather than covering the whole file | |
859 | let span = krate.span.shrink_to_lo(); | |
860 | // Complain about anything left over | |
f035d41b XL |
861 | for (name, entry) in self.sess.opts.externs.iter() { |
862 | if let ExternLocation::FoundInLibrarySearchDirectories = entry.location { | |
863 | // Don't worry about pathless `--extern foo` sysroot references | |
864 | continue; | |
865 | } | |
f9f354fc XL |
866 | if !self.used_extern_options.contains(&Symbol::intern(name)) { |
867 | self.sess.parse_sess.buffer_lint( | |
868 | lint::builtin::UNUSED_CRATE_DEPENDENCIES, | |
869 | span, | |
870 | ast::CRATE_NODE_ID, | |
871 | &format!( | |
872 | "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`", | |
873 | name, | |
874 | self.local_crate_name, | |
875 | name), | |
876 | ); | |
877 | } | |
878 | } | |
879 | } | |
880 | ||
b7449926 | 881 | pub fn postprocess(&mut self, krate: &ast::Crate) { |
041b39d2 XL |
882 | self.inject_profiler_runtime(); |
883 | self.inject_allocator_crate(krate); | |
c30ab7b3 | 884 | self.inject_panic_runtime(krate); |
c34b1796 | 885 | |
3dfed10e | 886 | info!("{:?}", CrateDump(&self.cstore)); |
f9f354fc XL |
887 | |
888 | self.report_unused_deps(krate); | |
9e0c209e | 889 | } |
c34b1796 | 890 | |
b7449926 | 891 | pub fn process_extern_crate( |
e74abb32 XL |
892 | &mut self, |
893 | item: &ast::Item, | |
894 | definitions: &Definitions, | |
f035d41b | 895 | def_id: LocalDefId, |
b7449926 | 896 | ) -> CrateNum { |
e74abb32 | 897 | match item.kind { |
0531ce1d | 898 | ast::ItemKind::ExternCrate(orig_name) => { |
dfeec247 XL |
899 | debug!( |
900 | "resolving extern crate stmt. ident: {} orig_name: {:?}", | |
901 | item.ident, orig_name | |
902 | ); | |
e74abb32 | 903 | let name = match orig_name { |
0531ce1d | 904 | Some(orig_name) => { |
3dfed10e | 905 | validate_crate_name(self.sess, &orig_name.as_str(), Some(item.span)); |
0531ce1d | 906 | orig_name |
ff7c6d11 XL |
907 | } |
908 | None => item.ident.name, | |
909 | }; | |
3dfed10e XL |
910 | let dep_kind = if self.sess.contains_name(&item.attrs, sym::no_link) { |
911 | CrateDepKind::MacrosOnly | |
ff7c6d11 | 912 | } else { |
3dfed10e | 913 | CrateDepKind::Explicit |
ff7c6d11 XL |
914 | }; |
915 | ||
e74abb32 | 916 | let cnum = self.resolve_crate(name, item.span, dep_kind, None); |
476ff2be | 917 | |
ba9703b0 | 918 | let path_len = definitions.def_path(def_id).data.len(); |
83c7162d XL |
919 | self.update_extern_crate( |
920 | cnum, | |
921 | ExternCrate { | |
ba9703b0 | 922 | src: ExternCrateSource::Extern(def_id.to_def_id()), |
83c7162d XL |
923 | span: item.span, |
924 | path_len, | |
e74abb32 | 925 | dependency_of: LOCAL_CRATE, |
83c7162d | 926 | }, |
83c7162d | 927 | ); |
83c7162d | 928 | cnum |
c30ab7b3 | 929 | } |
83c7162d | 930 | _ => bug!(), |
c34b1796 | 931 | } |
c34b1796 | 932 | } |
ff7c6d11 | 933 | |
e74abb32 | 934 | pub fn process_path_extern(&mut self, name: Symbol, span: Span) -> CrateNum { |
3dfed10e | 935 | let cnum = self.resolve_crate(name, span, CrateDepKind::Explicit, None); |
83c7162d XL |
936 | |
937 | self.update_extern_crate( | |
938 | cnum, | |
939 | ExternCrate { | |
940 | src: ExternCrateSource::Path, | |
941 | span, | |
942 | // to have the least priority in `update_extern_crate` | |
f035d41b | 943 | path_len: usize::MAX, |
e74abb32 | 944 | dependency_of: LOCAL_CRATE, |
83c7162d | 945 | }, |
83c7162d XL |
946 | ); |
947 | ||
948 | cnum | |
949 | } | |
950 | ||
3dfed10e XL |
951 | pub fn maybe_process_path_extern(&mut self, name: Symbol) -> Option<CrateNum> { |
952 | self.maybe_resolve_crate(name, CrateDepKind::Explicit, None).ok() | |
953 | } | |
954 | } | |
955 | ||
956 | fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> { | |
957 | struct Finder<'a> { | |
958 | sess: &'a Session, | |
959 | name: Symbol, | |
960 | spans: Vec<Span>, | |
961 | } | |
962 | impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> { | |
963 | fn visit_item(&mut self, item: &'ast ast::Item) { | |
964 | if item.ident.name == self.name | |
965 | && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol) | |
966 | { | |
967 | self.spans.push(item.span); | |
968 | } | |
969 | visit::walk_item(self, item) | |
970 | } | |
ff7c6d11 | 971 | } |
3dfed10e XL |
972 | |
973 | let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc)); | |
974 | let mut f = Finder { sess, name, spans: Vec::new() }; | |
975 | visit::walk_crate(&mut f, krate); | |
976 | f.spans | |
c34b1796 | 977 | } |