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