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