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