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