1 //! Validates all used crates and extern libraries and loads their metadata
3 use crate::dynamic_lib
::DynamicLibrary
;
4 use crate::locator
::{CrateError, CrateLocator, CratePaths}
;
5 use crate::rmeta
::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}
;
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_session
::config
::{self, CrateType, ExternLocation}
;
20 use rustc_session
::lint
;
21 use rustc_session
::output
::validate_crate_name
;
22 use rustc_session
::search_paths
::PathKind
;
23 use rustc_session
::{CrateDisambiguator, Session}
;
24 use rustc_span
::edition
::Edition
;
25 use rustc_span
::symbol
::{sym, Symbol}
;
26 use rustc_span
::{Span, DUMMY_SP}
;
27 use rustc_target
::spec
::{PanicStrategy, TargetTriple}
;
29 use proc_macro
::bridge
::client
::ProcMacro
;
31 use std
::{cmp, env, fs}
;
32 use tracing
::{debug, info}
;
36 metas
: IndexVec
<CrateNum
, Option
<Lrc
<CrateMetadata
>>>,
37 injected_panic_runtime
: Option
<CrateNum
>,
38 /// This crate needs an allocator and either provides it itself, or finds it in a dependency.
39 /// If the above is true, then this field denotes the kind of the found allocator.
40 allocator_kind
: Option
<AllocatorKind
>,
41 /// This crate has a `#[global_allocator]` item.
42 has_global_allocator
: bool
,
45 pub struct CrateLoader
<'a
> {
46 // Immutable configuration.
48 metadata_loader
: &'a MetadataLoaderDyn
,
49 local_crate_name
: Symbol
,
52 used_extern_options
: FxHashSet
<Symbol
>,
55 pub enum LoadedMacro
{
56 MacroDef(ast
::Item
, Edition
),
57 ProcMacro(SyntaxExtension
),
60 crate struct Library
{
61 pub source
: CrateSource
,
62 pub metadata
: MetadataBlob
,
70 /// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
71 #[derive(Clone, Copy)]
72 crate struct CrateMetadataRef
<'a
> {
73 pub cdata
: &'a CrateMetadata
,
74 pub cstore
: &'a CStore
,
77 impl std
::ops
::Deref
for CrateMetadataRef
<'_
> {
78 type Target
= CrateMetadata
;
80 fn deref(&self) -> &Self::Target
{
85 struct CrateDump
<'a
>(&'a CStore
);
87 impl<'a
> std
::fmt
::Debug
for CrateDump
<'a
> {
88 fn fmt(&self, fmt
: &mut std
::fmt
::Formatter
<'_
>) -> std
::fmt
::Result
{
89 writeln
!(fmt
, "resolved crates:")?
;
90 // `iter_crate_data` does not allow returning values. Thus we use a mutable variable here
91 // that aggregates the value (and any errors that could happen).
93 self.0.iter_crate_data
(|cnum
, data
| {
96 writeln
!(fmt
, " name: {}", data
.name())?
;
97 writeln
!(fmt
, " cnum: {}", cnum
)?
;
98 writeln
!(fmt
, " hash: {}", data
.hash())?
;
99 writeln
!(fmt
, " reqd: {:?}", data
.dep_kind())?
;
100 let CrateSource { dylib, rlib, rmeta }
= data
.source();
101 if let Some(dylib
) = dylib
{
102 writeln
!(fmt
, " dylib: {}", dylib
.0.display())?
;
104 if let Some(rlib
) = rlib
{
105 writeln
!(fmt
, " rlib: {}", rlib
.0.display())?
;
107 if let Some(rmeta
) = rmeta
{
108 writeln
!(fmt
, " rmeta: {}", rmeta
.0.display())?
;
118 crate fn from_tcx(tcx
: TyCtxt
<'_
>) -> &CStore
{
119 tcx
.cstore_as_any().downcast_ref
::<CStore
>().expect("`tcx.cstore` is not a `CStore`")
122 fn alloc_new_crate_num(&mut self) -> CrateNum
{
123 self.metas
.push(None
);
124 CrateNum
::new(self.metas
.len() - 1)
127 crate fn get_crate_data(&self, cnum
: CrateNum
) -> CrateMetadataRef
<'_
> {
128 let cdata
= self.metas
[cnum
]
130 .unwrap_or_else(|| panic
!("Failed to get crate data for {:?}", cnum
));
131 CrateMetadataRef { cdata, cstore: self }
134 fn set_crate_data(&mut self, cnum
: CrateNum
, data
: CrateMetadata
) {
135 assert
!(self.metas
[cnum
].is_none(), "Overwriting crate metadata entry");
136 self.metas
[cnum
] = Some(Lrc
::new(data
));
139 crate fn iter_crate_data(&self, mut f
: impl FnMut(CrateNum
, &CrateMetadata
)) {
140 for (cnum
, data
) in self.metas
.iter_enumerated() {
141 if let Some(data
) = data
{
147 fn push_dependencies_in_postorder(&self, deps
: &mut Vec
<CrateNum
>, cnum
: CrateNum
) {
148 if !deps
.contains(&cnum
) {
149 let data
= self.get_crate_data(cnum
);
150 for &dep
in data
.dependencies().iter() {
152 self.push_dependencies_in_postorder(deps
, dep
);
160 crate fn crate_dependencies_in_postorder(&self, cnum
: CrateNum
) -> Vec
<CrateNum
> {
161 let mut deps
= Vec
::new();
162 if cnum
== LOCAL_CRATE
{
163 self.iter_crate_data(|cnum
, _
| self.push_dependencies_in_postorder(&mut deps
, cnum
));
165 self.push_dependencies_in_postorder(&mut deps
, cnum
);
170 fn crate_dependencies_in_reverse_postorder(&self, cnum
: CrateNum
) -> Vec
<CrateNum
> {
171 let mut deps
= self.crate_dependencies_in_postorder(cnum
);
176 crate fn injected_panic_runtime(&self) -> Option
<CrateNum
> {
177 self.injected_panic_runtime
180 crate fn allocator_kind(&self) -> Option
<AllocatorKind
> {
184 crate fn has_global_allocator(&self) -> bool
{
185 self.has_global_allocator
189 impl<'a
> CrateLoader
<'a
> {
192 metadata_loader
: &'a MetadataLoaderDyn
,
193 local_crate_name
: &str,
198 local_crate_name
: Symbol
::intern(local_crate_name
),
200 // We add an empty entry for LOCAL_CRATE (which maps to zero) in
201 // order to make array indices in `metas` match with the
202 // corresponding `CrateNum`. This first entry will always remain
204 metas
: IndexVec
::from_elem_n(None
, 1),
205 injected_panic_runtime
: None
,
206 allocator_kind
: None
,
207 has_global_allocator
: false,
209 used_extern_options
: Default
::default(),
213 pub fn cstore(&self) -> &CStore
{
217 pub fn into_cstore(self) -> CStore
{
221 fn existing_match(&self, name
: Symbol
, hash
: Option
<Svh
>, kind
: PathKind
) -> Option
<CrateNum
> {
223 self.cstore
.iter_crate_data(|cnum
, data
| {
224 if data
.name() != name
{
225 tracing
::trace
!("{} did not match {}", data
.name(), name
);
230 Some(hash
) if hash
== data
.hash() => {
235 debug
!("actual hash {} did not match expected {}", hash
, data
.hash());
241 // When the hash is None we're dealing with a top-level dependency
242 // in which case we may have a specification on the command line for
243 // this library. Even though an upstream library may have loaded
244 // something of the same name, we have to make sure it was loaded
245 // from the exact same location as well.
247 // We're also sure to compare *paths*, not actual byte slices. The
248 // `source` stores paths which are normalized which may be different
249 // from the strings on the command line.
250 let source
= self.cstore
.get_crate_data(cnum
).cdata
.source();
251 if let Some(entry
) = self.sess
.opts
.externs
.get(&name
.as_str()) {
252 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
253 if let Some(mut files
) = entry
.files() {
255 let l
= fs
::canonicalize(l
).unwrap_or(l
.clone().into());
256 source
.dylib
.as_ref().map(|p
| &p
.0) == Some(&l
)
257 || source
.rlib
.as_ref().map(|p
| &p
.0) == Some(&l
)
265 // Alright, so we've gotten this far which means that `data` has the
266 // right name, we don't have a hash, and we don't have a --extern
267 // pointing for ourselves. We're still not quite yet done because we
268 // have to make sure that this crate was found in the crate lookup
269 // path (this is a top-level dependency) as we don't want to
270 // implicitly load anything inside the dependency lookup path.
271 let prev_kind
= source
274 .or(source
.rlib
.as_ref())
275 .or(source
.rmeta
.as_ref())
276 .expect("No sources for crate")
278 if kind
.matches(prev_kind
) {
282 "failed to load existing crate {}; kind {:?} did not match prev_kind {:?}",
283 name
, kind
, prev_kind
290 fn verify_no_symbol_conflicts(&self, root
: &CrateRoot
<'_
>) -> Result
<(), CrateError
> {
291 // Check for (potential) conflicts with the local crate
292 if self.local_crate_name
== root
.name()
293 && self.sess
.local_crate_disambiguator() == root
.disambiguator()
295 return Err(CrateError
::SymbolConflictsCurrent(root
.name()));
298 // Check for conflicts with any crate loaded so far
299 let mut res
= Ok(());
300 self.cstore
.iter_crate_data(|_
, other
| {
301 if other
.name() == root
.name() && // same crate-name
302 other
.disambiguator() == root
.disambiguator() && // same crate-disambiguator
303 other
.hash() != root
.hash()
306 res
= Err(CrateError
::SymbolConflictsOthers(root
.name()));
315 host_lib
: Option
<Library
>,
316 root
: Option
<&CratePaths
>,
318 dep_kind
: CrateDepKind
,
320 ) -> Result
<CrateNum
, CrateError
> {
321 let _prof_timer
= self.sess
.prof
.generic_activity("metadata_register_crate");
323 let Library { source, metadata }
= lib
;
324 let crate_root
= metadata
.get_root();
325 let host_hash
= host_lib
.as_ref().map(|lib
| lib
.metadata
.get_root().hash());
326 self.verify_no_symbol_conflicts(&crate_root
)?
;
329 self.sess
.opts
.externs
.get(&name
.as_str()).map(|e
| e
.is_private_dep
).unwrap_or(false);
331 // Claim this crate number and cache it
332 let cnum
= self.cstore
.alloc_new_crate_num();
335 "register crate `{}` (cnum = {}. private_dep = {})",
341 // Maintain a reference to the top most crate.
342 // Stash paths for top-most crate locally if necessary.
344 let root
= if let Some(root
) = root
{
347 crate_paths
= CratePaths
::new(crate_root
.name(), source
.clone());
351 let cnum_map
= self.resolve_crate_deps(root
, &crate_root
, &metadata
, cnum
, dep_kind
)?
;
353 let raw_proc_macros
= if crate_root
.is_proc_macro_crate() {
355 let (dlsym_source
, dlsym_root
) = match &host_lib
{
356 Some(host_lib
) => (&host_lib
.source
, {
357 temp_root
= host_lib
.metadata
.get_root();
360 None
=> (&source
, &crate_root
),
362 let dlsym_dylib
= dlsym_source
.dylib
.as_ref().expect("no dylib for a proc-macro crate");
363 Some(self.dlsym_proc_macros(&dlsym_dylib
.0, dlsym_root
.disambiguator())?
)
368 let crate_metadata
= CrateMetadata
::new(
381 self.cstore
.set_crate_data(cnum
, crate_metadata
);
386 fn load_proc_macro
<'b
>(
388 locator
: &mut CrateLocator
<'b
>,
390 ) -> Result
<Option
<(LoadResult
, Option
<Library
>)>, CrateError
>
394 // Use a new crate locator so trying to load a proc macro doesn't affect the error
396 let mut proc_macro_locator
= locator
.clone();
398 // Try to load a proc macro
399 proc_macro_locator
.is_proc_macro
= Some(true);
401 // Load the proc macro crate for the target
402 let (locator
, target_result
) = if self.sess
.opts
.debugging_opts
.dual_proc_macros
{
403 proc_macro_locator
.reset();
404 let result
= match self.load(&mut proc_macro_locator
)?
{
405 Some(LoadResult
::Previous(cnum
)) => {
406 return Ok(Some((LoadResult
::Previous(cnum
), None
)));
408 Some(LoadResult
::Loaded(library
)) => Some(LoadResult
::Loaded(library
)),
409 None
=> return Ok(None
),
411 locator
.hash
= locator
.host_hash
;
412 // Use the locator when looking for the host proc macro crate, as that is required
413 // so we want it to affect the error message
416 (&mut proc_macro_locator
, None
)
419 // Load the proc macro crate for the host
422 locator
.is_proc_macro
= Some(true);
423 locator
.target
= &self.sess
.host
;
424 locator
.triple
= TargetTriple
::from_triple(config
::host_triple());
425 locator
.filesearch
= self.sess
.host_filesearch(path_kind
);
427 let host_result
= match self.load(locator
)?
{
428 Some(host_result
) => host_result
,
429 None
=> return Ok(None
),
432 Ok(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")
437 LoadResult
::Loaded(library
) => library
,
439 (target_result
.unwrap(), Some(host_result
))
445 fn resolve_crate
<'b
>(
449 dep_kind
: CrateDepKind
,
450 dep
: Option
<(&'b CratePaths
, &'b CrateDep
)>,
453 self.used_extern_options
.insert(name
);
455 self.maybe_resolve_crate(name
, dep_kind
, dep
)
456 .unwrap_or_else(|err
| err
.report(self.sess
, span
))
459 fn maybe_resolve_crate
<'b
>(
462 mut dep_kind
: CrateDepKind
,
463 dep
: Option
<(&'b CratePaths
, &'b CrateDep
)>,
464 ) -> Result
<CrateNum
, CrateError
> {
465 info
!("resolving crate `{}`", name
);
466 if !name
.as_str().is_ascii() {
467 return Err(CrateError
::NonAsciiName(name
));
469 let (root
, hash
, host_hash
, extra_filename
, path_kind
) = match dep
{
470 Some((root
, dep
)) => (
474 Some(&dep
.extra_filename
[..]),
475 PathKind
::Dependency
,
477 None
=> (None
, None
, None
, None
, PathKind
::Crate
),
479 let result
= if let Some(cnum
) = self.existing_match(name
, hash
, path_kind
) {
480 (LoadResult
::Previous(cnum
), None
)
482 info
!("falling back to a load");
483 let mut locator
= CrateLocator
::new(
485 self.metadata_loader
,
493 Some(false), // is_proc_macro
496 match self.load(&mut locator
)?
{
497 Some(res
) => (res
, None
),
499 dep_kind
= CrateDepKind
::MacrosOnly
;
500 match self.load_proc_macro(&mut locator
, path_kind
)?
{
502 None
=> return Err(locator
.into_error()),
509 (LoadResult
::Previous(cnum
), None
) => {
510 let data
= self.cstore
.get_crate_data(cnum
);
511 if data
.is_proc_macro_crate() {
512 dep_kind
= CrateDepKind
::MacrosOnly
;
514 data
.update_dep_kind(|data_dep_kind
| cmp
::max(data_dep_kind
, dep_kind
));
517 (LoadResult
::Loaded(library
), host_library
) => {
518 self.register_crate(host_library
, root
, library
, dep_kind
, name
)
524 fn load(&self, locator
: &mut CrateLocator
<'_
>) -> Result
<Option
<LoadResult
>, CrateError
> {
525 let library
= match locator
.maybe_load_library_crate()?
{
526 Some(library
) => library
,
527 None
=> return Ok(None
),
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.
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
538 let root
= library
.metadata
.get_root();
539 Ok(Some(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
);
550 LoadResult
::Loaded(library
)
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
);
565 // Go through the crate metadata and load any crates that it references
566 fn resolve_crate_deps(
569 crate_root
: &CrateRoot
<'_
>,
570 metadata
: &MetadataBlob
,
572 dep_kind
: CrateDepKind
,
573 ) -> Result
<CrateNumMap
, CrateError
> {
574 debug
!("resolving deps of external crate");
575 if crate_root
.is_proc_macro_crate() {
576 return Ok(CrateNumMap
::new());
579 // The map from crate numbers in the crate we're resolving to local crate numbers.
580 // We map 0 and all other holes in the map to our parent crate. The "additional"
581 // self-dependencies should be harmless.
582 let deps
= crate_root
.decode_crate_deps(metadata
);
583 let mut crate_num_map
= CrateNumMap
::with_capacity(1 + deps
.len());
584 crate_num_map
.push(krate
);
587 "resolving dep crate {} hash: `{}` extra filename: `{}`",
588 dep
.name
, dep
.hash
, dep
.extra_filename
590 let dep_kind
= match dep_kind
{
591 CrateDepKind
::MacrosOnly
=> CrateDepKind
::MacrosOnly
,
594 let cnum
= self.maybe_resolve_crate(dep
.name
, dep_kind
, Some((root
, &dep
)))?
;
595 crate_num_map
.push(cnum
);
598 debug
!("resolve_crate_deps: cnum_map for {:?} is {:?}", krate
, crate_num_map
);
602 fn dlsym_proc_macros(
605 disambiguator
: CrateDisambiguator
,
606 ) -> Result
<&'
static [ProcMacro
], CrateError
> {
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
) {
611 Err(s
) => return Err(CrateError
::DlOpen(s
)),
614 let sym
= self.sess
.generate_proc_macro_decls_symbol(disambiguator
);
616 let sym
= match lib
.symbol(&sym
) {
618 Err(s
) => return Err(CrateError
::DlSym(s
)),
620 *(sym
as *const &[ProcMacro
])
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
);
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
);
635 info
!("panic runtime injection skipped, only generating rlib");
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.
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
=
649 self.sess
.contains_name(&krate
.attrs
, sym
::needs_panic_runtime
);
651 self.cstore
.iter_crate_data(|cnum
, data
| {
652 needs_panic_runtime
= needs_panic_runtime
|| data
.needs_panic_runtime();
653 if data
.is_panic_runtime() {
654 // Inject a dependency from all #![needs_panic_runtime] to this
655 // #![panic_runtime] crate.
656 self.inject_dependency_if(cnum
, "a panic runtime", &|data
| {
657 data
.needs_panic_runtime()
659 runtime_found
= runtime_found
|| data
.dep_kind() == CrateDepKind
::Explicit
;
663 // If an explicitly linked and matching panic runtime was found, or if
664 // we just don't need one at all, then we're done here and there's
665 // nothing else to do.
666 if !needs_panic_runtime
|| runtime_found
{
670 // By this point we know that we (a) need a panic runtime and (b) no
671 // panic runtime was explicitly linked. Here we just load an appropriate
672 // default runtime for our panic strategy and then inject the
675 // We may resolve to an already loaded crate (as the crate may not have
676 // been explicitly linked prior to this) and we may re-inject
677 // dependencies again, but both of those situations are fine.
679 // Also note that we have yet to perform validation of the crate graph
680 // in terms of everyone has a compatible panic runtime format, that's
681 // performed later as part of the `dependency_format` module.
682 let name
= match desired_strategy
{
683 PanicStrategy
::Unwind
=> sym
::panic_unwind
,
684 PanicStrategy
::Abort
=> sym
::panic_abort
,
686 info
!("panic runtime not found -- loading {}", name
);
688 let cnum
= self.resolve_crate(name
, DUMMY_SP
, CrateDepKind
::Implicit
, None
);
689 let data
= self.cstore
.get_crate_data(cnum
);
691 // Sanity check the loaded crate to ensure it is indeed a panic runtime
692 // and the panic strategy is indeed what we thought it was.
693 if !data
.is_panic_runtime() {
694 self.sess
.err(&format
!("the crate `{}` is not a panic runtime", name
));
696 if data
.panic_strategy() != desired_strategy
{
697 self.sess
.err(&format
!(
698 "the crate `{}` does not have the panic \
701 desired_strategy
.desc()
705 self.cstore
.injected_panic_runtime
= Some(cnum
);
706 self.inject_dependency_if(cnum
, "a panic runtime", &|data
| data
.needs_panic_runtime());
709 fn inject_profiler_runtime(&mut self) {
710 if (self.sess
.opts
.debugging_opts
.instrument_coverage
711 || self.sess
.opts
.debugging_opts
.profile
712 || self.sess
.opts
.cg
.profile_generate
.enabled())
713 && !self.sess
.opts
.debugging_opts
.no_profiler_runtime
715 info
!("loading profiler");
717 let name
= sym
::profiler_builtins
;
718 let cnum
= self.resolve_crate(name
, DUMMY_SP
, CrateDepKind
::Implicit
, None
);
719 let data
= self.cstore
.get_crate_data(cnum
);
721 // Sanity check the loaded crate to ensure it is indeed a profiler runtime
722 if !data
.is_profiler_runtime() {
723 self.sess
.err("the crate `profiler_builtins` is not a profiler runtime");
728 fn inject_allocator_crate(&mut self, krate
: &ast
::Crate
) {
729 self.cstore
.has_global_allocator
= match &*global_allocator_spans(&self.sess
, krate
) {
730 [span1
, span2
, ..] => {
732 .struct_span_err(*span2
, "cannot define multiple global allocators")
733 .span_label(*span2
, "cannot define a new global allocator")
734 .span_label(*span1
, "previous global allocator defined here")
738 spans
=> !spans
.is_empty(),
741 // Check to see if we actually need an allocator. This desire comes
742 // about through the `#![needs_allocator]` attribute and is typically
743 // written down in liballoc.
744 let mut needs_allocator
= self.sess
.contains_name(&krate
.attrs
, sym
::needs_allocator
);
745 self.cstore
.iter_crate_data(|_
, data
| {
746 needs_allocator
= needs_allocator
|| data
.needs_allocator();
748 if !needs_allocator
{
752 // At this point we've determined that we need an allocator. Let's see
753 // if our compilation session actually needs an allocator based on what
755 let all_rlib
= self.sess
.crate_types().iter().all(|ct
| match *ct
{
756 CrateType
::Rlib
=> true,
763 // Ok, we need an allocator. Not only that but we're actually going to
764 // create an artifact that needs one linked in. Let's go find the one
765 // that we're going to link in.
767 // First up we check for global allocators. Look at the crate graph here
768 // and see what's a global allocator, including if we ourselves are a
770 let mut global_allocator
=
771 self.cstore
.has_global_allocator
.then(|| Symbol
::intern("this crate"));
772 self.cstore
.iter_crate_data(|_
, data
| {
773 if !data
.has_global_allocator() {
776 match global_allocator
{
777 Some(other_crate
) => {
778 self.sess
.err(&format
!(
779 "the `#[global_allocator]` in {} \
780 conflicts with global \
786 None
=> global_allocator
= Some(data
.name()),
789 if global_allocator
.is_some() {
790 self.cstore
.allocator_kind
= Some(AllocatorKind
::Global
);
794 // Ok we haven't found a global allocator but we still need an
795 // allocator. At this point our allocator request is typically fulfilled
796 // by the standard library, denoted by the `#![default_lib_allocator]`
798 let mut has_default
= self.sess
.contains_name(&krate
.attrs
, sym
::default_lib_allocator
);
799 self.cstore
.iter_crate_data(|_
, data
| {
800 if data
.has_default_lib_allocator() {
807 "no global memory allocator found but one is \
808 required; link to std or \
809 add `#[global_allocator]` to a static item \
810 that implements the GlobalAlloc trait.",
813 self.cstore
.allocator_kind
= Some(AllocatorKind
::Default
);
816 fn inject_dependency_if(
820 needs_dep
: &dyn Fn(&CrateMetadata
) -> bool
,
822 // don't perform this validation if the session has errors, as one of
823 // those errors may indicate a circular dependency which could cause
824 // this to stack overflow.
825 if self.sess
.has_errors() {
829 // Before we inject any dependencies, make sure we don't inject a
830 // circular dependency by validating that this crate doesn't
831 // transitively depend on any crates satisfying `needs_dep`.
832 for dep
in self.cstore
.crate_dependencies_in_reverse_postorder(krate
) {
833 let data
= self.cstore
.get_crate_data(dep
);
834 if needs_dep(&data
) {
835 self.sess
.err(&format
!(
836 "the crate `{}` cannot depend \
837 on a crate that needs {}, but \
839 self.cstore
.get_crate_data(krate
).name(),
846 // All crates satisfying `needs_dep` do not explicitly depend on the
847 // crate provided for this compile, but in order for this compilation to
848 // be successfully linked we need to inject a dependency (to order the
849 // crates on the command line correctly).
850 self.cstore
.iter_crate_data(|cnum
, data
| {
851 if !needs_dep(data
) {
855 info
!("injecting a dep from {} to {}", cnum
, krate
);
856 data
.add_dependency(krate
);
860 fn report_unused_deps(&mut self, krate
: &ast
::Crate
) {
861 // Make a point span rather than covering the whole file
862 let span
= krate
.span
.shrink_to_lo();
863 // Complain about anything left over
864 for (name
, entry
) in self.sess
.opts
.externs
.iter() {
865 if let ExternLocation
::FoundInLibrarySearchDirectories
= entry
.location
{
866 // Don't worry about pathless `--extern foo` sysroot references
869 if !self.used_extern_options
.contains(&Symbol
::intern(name
)) {
870 self.sess
.parse_sess
.buffer_lint(
871 lint
::builtin
::UNUSED_CRATE_DEPENDENCIES
,
875 "external crate `{}` unused in `{}`: remove the dependency or add `use {} as _;`",
877 self.local_crate_name
,
884 pub fn postprocess(&mut self, krate
: &ast
::Crate
) {
885 self.inject_profiler_runtime();
886 self.inject_allocator_crate(krate
);
887 self.inject_panic_runtime(krate
);
889 info
!("{:?}", CrateDump(&self.cstore
));
891 self.report_unused_deps(krate
);
894 pub fn process_extern_crate(
897 definitions
: &Definitions
,
901 ast
::ItemKind
::ExternCrate(orig_name
) => {
903 "resolving extern crate stmt. ident: {} orig_name: {:?}",
904 item
.ident
, orig_name
906 let name
= match orig_name
{
908 validate_crate_name(self.sess
, &orig_name
.as_str(), Some(item
.span
));
911 None
=> item
.ident
.name
,
913 let dep_kind
= if self.sess
.contains_name(&item
.attrs
, sym
::no_link
) {
914 CrateDepKind
::MacrosOnly
916 CrateDepKind
::Explicit
919 let cnum
= self.resolve_crate(name
, item
.span
, dep_kind
, None
);
921 let path_len
= definitions
.def_path(def_id
).data
.len();
922 self.update_extern_crate(
925 src
: ExternCrateSource
::Extern(def_id
.to_def_id()),
928 dependency_of
: LOCAL_CRATE
,
937 pub fn process_path_extern(&mut self, name
: Symbol
, span
: Span
) -> CrateNum
{
938 let cnum
= self.resolve_crate(name
, span
, CrateDepKind
::Explicit
, None
);
940 self.update_extern_crate(
943 src
: ExternCrateSource
::Path
,
945 // to have the least priority in `update_extern_crate`
946 path_len
: usize::MAX
,
947 dependency_of
: LOCAL_CRATE
,
954 pub fn maybe_process_path_extern(&mut self, name
: Symbol
) -> Option
<CrateNum
> {
955 self.maybe_resolve_crate(name
, CrateDepKind
::Explicit
, None
).ok()
959 fn global_allocator_spans(sess
: &Session
, krate
: &ast
::Crate
) -> Vec
<Span
> {
965 impl<'ast
, 'a
> visit
::Visitor
<'ast
> for Finder
<'a
> {
966 fn visit_item(&mut self, item
: &'ast ast
::Item
) {
967 if item
.ident
.name
== self.name
968 && self.sess
.contains_name(&item
.attrs
, sym
::rustc_std_internal_symbol
)
970 self.spans
.push(item
.span
);
972 visit
::walk_item(self, item
)
976 let name
= Symbol
::intern(&AllocatorKind
::Global
.fn_name(sym
::alloc
));
977 let mut f
= Finder { sess, name, spans: Vec::new() }
;
978 visit
::walk_crate(&mut f
, krate
);