1 //! Validates all used crates and extern libraries and loads their metadata
3 use crate::locator
::{CrateLocator, CratePaths}
;
4 use crate::rmeta
::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob}
;
6 use rustc
::hir
::map
::Definitions
;
7 use rustc
::middle
::cstore
::DepKind
;
8 use rustc
::middle
::cstore
::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn}
;
9 use rustc
::session
::config
;
10 use rustc
::session
::search_paths
::PathKind
;
11 use rustc
::session
::{CrateDisambiguator, Session}
;
12 use rustc
::ty
::TyCtxt
;
15 use rustc_ast
::expand
::allocator
::{global_allocator_spans, AllocatorKind}
;
16 use rustc_data_structures
::svh
::Svh
;
17 use rustc_data_structures
::sync
::Lrc
;
18 use rustc_errors
::struct_span_err
;
19 use rustc_expand
::base
::SyntaxExtension
;
20 use rustc_hir
::def_id
::{CrateNum, LOCAL_CRATE}
;
21 use rustc_index
::vec
::IndexVec
;
22 use rustc_span
::edition
::Edition
;
23 use rustc_span
::symbol
::{sym, Symbol}
;
24 use rustc_span
::{Span, DUMMY_SP}
;
25 use rustc_target
::spec
::{PanicStrategy, TargetTriple}
;
27 use log
::{debug, info, log_enabled}
;
28 use proc_macro
::bridge
::client
::ProcMacro
;
34 metas
: IndexVec
<CrateNum
, Option
<Lrc
<CrateMetadata
>>>,
35 injected_panic_runtime
: Option
<CrateNum
>,
36 /// This crate needs an allocator and either provides it itself, or finds it in a dependency.
37 /// If the above is true, then this field denotes the kind of the found allocator.
38 allocator_kind
: Option
<AllocatorKind
>,
39 /// This crate has a `#[global_allocator]` item.
40 has_global_allocator
: bool
,
43 pub struct CrateLoader
<'a
> {
44 // Immutable configuration.
46 metadata_loader
: &'a MetadataLoaderDyn
,
47 local_crate_name
: Symbol
,
52 pub enum LoadedMacro
{
53 MacroDef(ast
::Item
, Edition
),
54 ProcMacro(SyntaxExtension
),
57 crate struct Library
{
58 pub source
: CrateSource
,
59 pub metadata
: MetadataBlob
,
68 LocatorError(CrateLocator
<'a
>),
71 impl<'a
> LoadError
<'a
> {
72 fn report(self) -> ! {
74 LoadError
::LocatorError(locator
) => locator
.report_errs(),
79 /// A reference to `CrateMetadata` that can also give access to whole crate store when necessary.
80 #[derive(Clone, Copy)]
81 crate struct CrateMetadataRef
<'a
> {
82 pub cdata
: &'a CrateMetadata
,
83 pub cstore
: &'a CStore
,
86 impl std
::ops
::Deref
for CrateMetadataRef
<'_
> {
87 type Target
= CrateMetadata
;
89 fn deref(&self) -> &Self::Target
{
94 fn dump_crates(cstore
: &CStore
) {
95 info
!("resolved crates:");
96 cstore
.iter_crate_data(|cnum
, data
| {
97 info
!(" name: {}", data
.name());
98 info
!(" cnum: {}", cnum
);
99 info
!(" hash: {}", data
.hash());
100 info
!(" reqd: {:?}", data
.dep_kind());
101 let CrateSource { dylib, rlib, rmeta }
= data
.source();
102 dylib
.as_ref().map(|dl
| info
!(" dylib: {}", dl
.0.display()));
103 rlib
.as_ref().map(|rl
| info
!(" rlib: {}", rl
.0.display()));
104 rmeta
.as_ref().map(|rl
| info
!(" rmeta: {}", rl
.0.display()));
109 crate fn from_tcx(tcx
: TyCtxt
<'_
>) -> &CStore
{
110 tcx
.cstore_as_any().downcast_ref
::<CStore
>().expect("`tcx.cstore` is not a `CStore`")
113 fn alloc_new_crate_num(&mut self) -> CrateNum
{
114 self.metas
.push(None
);
115 CrateNum
::new(self.metas
.len() - 1)
118 crate fn get_crate_data(&self, cnum
: CrateNum
) -> CrateMetadataRef
<'_
> {
119 let cdata
= self.metas
[cnum
]
121 .unwrap_or_else(|| panic
!("Failed to get crate data for {:?}", cnum
));
122 CrateMetadataRef { cdata, cstore: self }
125 fn set_crate_data(&mut self, cnum
: CrateNum
, data
: CrateMetadata
) {
126 assert
!(self.metas
[cnum
].is_none(), "Overwriting crate metadata entry");
127 self.metas
[cnum
] = Some(Lrc
::new(data
));
130 crate fn iter_crate_data(&self, mut f
: impl FnMut(CrateNum
, &CrateMetadata
)) {
131 for (cnum
, data
) in self.metas
.iter_enumerated() {
132 if let Some(data
) = data
{
138 fn push_dependencies_in_postorder(&self, deps
: &mut Vec
<CrateNum
>, cnum
: CrateNum
) {
139 if !deps
.contains(&cnum
) {
140 let data
= self.get_crate_data(cnum
);
141 for &dep
in data
.dependencies().iter() {
143 self.push_dependencies_in_postorder(deps
, dep
);
151 crate fn crate_dependencies_in_postorder(&self, cnum
: CrateNum
) -> Vec
<CrateNum
> {
152 let mut deps
= Vec
::new();
153 if cnum
== LOCAL_CRATE
{
154 self.iter_crate_data(|cnum
, _
| self.push_dependencies_in_postorder(&mut deps
, cnum
));
156 self.push_dependencies_in_postorder(&mut deps
, cnum
);
161 fn crate_dependencies_in_reverse_postorder(&self, cnum
: CrateNum
) -> Vec
<CrateNum
> {
162 let mut deps
= self.crate_dependencies_in_postorder(cnum
);
167 crate fn injected_panic_runtime(&self) -> Option
<CrateNum
> {
168 self.injected_panic_runtime
171 crate fn allocator_kind(&self) -> Option
<AllocatorKind
> {
175 crate fn has_global_allocator(&self) -> bool
{
176 self.has_global_allocator
180 impl<'a
> CrateLoader
<'a
> {
183 metadata_loader
: &'a MetadataLoaderDyn
,
184 local_crate_name
: &str,
189 local_crate_name
: Symbol
::intern(local_crate_name
),
191 // We add an empty entry for LOCAL_CRATE (which maps to zero) in
192 // order to make array indices in `metas` match with the
193 // corresponding `CrateNum`. This first entry will always remain
195 metas
: IndexVec
::from_elem_n(None
, 1),
196 injected_panic_runtime
: None
,
197 allocator_kind
: None
,
198 has_global_allocator
: false,
203 pub fn cstore(&self) -> &CStore
{
207 pub fn into_cstore(self) -> CStore
{
211 fn existing_match(&self, name
: Symbol
, hash
: Option
<Svh
>, kind
: PathKind
) -> Option
<CrateNum
> {
213 self.cstore
.iter_crate_data(|cnum
, data
| {
214 if data
.name() != name
{
219 Some(hash
) if hash
== data
.hash() => {
227 // When the hash is None we're dealing with a top-level dependency
228 // in which case we may have a specification on the command line for
229 // this library. Even though an upstream library may have loaded
230 // something of the same name, we have to make sure it was loaded
231 // from the exact same location as well.
233 // We're also sure to compare *paths*, not actual byte slices. The
234 // `source` stores paths which are normalized which may be different
235 // from the strings on the command line.
236 let source
= self.cstore
.get_crate_data(cnum
).cdata
.source();
237 if let Some(entry
) = self.sess
.opts
.externs
.get(&name
.as_str()) {
238 // Only use `--extern crate_name=path` here, not `--extern crate_name`.
239 if let Some(mut files
) = entry
.files() {
241 let l
= fs
::canonicalize(l
).ok();
242 source
.dylib
.as_ref().map(|p
| &p
.0) == l
.as_ref()
243 || source
.rlib
.as_ref().map(|p
| &p
.0) == l
.as_ref()
251 // Alright, so we've gotten this far which means that `data` has the
252 // right name, we don't have a hash, and we don't have a --extern
253 // pointing for ourselves. We're still not quite yet done because we
254 // have to make sure that this crate was found in the crate lookup
255 // path (this is a top-level dependency) as we don't want to
256 // implicitly load anything inside the dependency lookup path.
257 let prev_kind
= source
260 .or(source
.rlib
.as_ref())
261 .or(source
.rmeta
.as_ref())
262 .expect("No sources for crate")
264 if kind
.matches(prev_kind
) {
271 fn verify_no_symbol_conflicts(&self, span
: Span
, root
: &CrateRoot
<'_
>) {
272 // Check for (potential) conflicts with the local crate
273 if self.local_crate_name
== root
.name()
274 && self.sess
.local_crate_disambiguator() == root
.disambiguator()
280 "the current crate is indistinguishable from one of its \
281 dependencies: it has the same crate-name `{}` and was \
282 compiled with the same `-C metadata` arguments. This \
283 will result in symbol conflicts between the two.",
289 // Check for conflicts with any crate loaded so far
290 self.cstore
.iter_crate_data(|_
, other
| {
291 if other
.name() == root
.name() && // same crate-name
292 other
.disambiguator() == root
.disambiguator() && // same crate-disambiguator
293 other
.hash() != root
.hash()
300 "found two different crates with name `{}` that are \
301 not distinguished by differing `-C metadata`. This \
302 will result in symbol conflicts between the two.",
312 host_lib
: Option
<Library
>,
313 root
: Option
<&CratePaths
>,
319 let _prof_timer
= self.sess
.prof
.generic_activity("metadata_register_crate");
321 let Library { source, metadata }
= lib
;
322 let crate_root
= metadata
.get_root();
323 let host_hash
= host_lib
.as_ref().map(|lib
| lib
.metadata
.get_root().hash());
324 self.verify_no_symbol_conflicts(span
, &crate_root
);
327 self.sess
.opts
.externs
.get(&name
.as_str()).map(|e
| e
.is_private_dep
).unwrap_or(false);
329 info
!("register crate `{}` (private_dep = {})", crate_root
.name(), private_dep
);
331 // Claim this crate number and cache it
332 let cnum
= self.cstore
.alloc_new_crate_num();
334 // Maintain a reference to the top most crate.
335 // Stash paths for top-most crate locally if necessary.
337 let root
= if let Some(root
) = root
{
340 crate_paths
= CratePaths
::new(crate_root
.name(), source
.clone());
344 let cnum_map
= self.resolve_crate_deps(root
, &crate_root
, &metadata
, cnum
, span
, dep_kind
);
346 let raw_proc_macros
= if crate_root
.is_proc_macro_crate() {
348 let (dlsym_source
, dlsym_root
) = match &host_lib
{
349 Some(host_lib
) => (&host_lib
.source
, {
350 temp_root
= host_lib
.metadata
.get_root();
353 None
=> (&source
, &crate_root
),
355 let dlsym_dylib
= dlsym_source
.dylib
.as_ref().expect("no dylib for a proc-macro crate");
356 Some(self.dlsym_proc_macros(&dlsym_dylib
.0, dlsym_root
.disambiguator(), span
))
361 self.cstore
.set_crate_data(
380 fn load_proc_macro
<'b
>(
382 locator
: &mut CrateLocator
<'b
>,
384 ) -> Option
<(LoadResult
, Option
<Library
>)>
388 // Use a new crate locator so trying to load a proc macro doesn't affect the error
390 let mut proc_macro_locator
= locator
.clone();
392 // Try to load a proc macro
393 proc_macro_locator
.is_proc_macro
= Some(true);
395 // Load the proc macro crate for the target
396 let (locator
, target_result
) = if self.sess
.opts
.debugging_opts
.dual_proc_macros
{
397 proc_macro_locator
.reset();
398 let result
= match self.load(&mut proc_macro_locator
)?
{
399 LoadResult
::Previous(cnum
) => return Some((LoadResult
::Previous(cnum
), None
)),
400 LoadResult
::Loaded(library
) => Some(LoadResult
::Loaded(library
)),
402 locator
.hash
= locator
.host_hash
;
403 // Use the locator when looking for the host proc macro crate, as that is required
404 // so we want it to affect the error message
407 (&mut proc_macro_locator
, None
)
410 // Load the proc macro crate for the host
413 locator
.is_proc_macro
= Some(true);
414 locator
.target
= &self.sess
.host
;
415 locator
.triple
= TargetTriple
::from_triple(config
::host_triple());
416 locator
.filesearch
= self.sess
.host_filesearch(path_kind
);
418 let host_result
= self.load(locator
)?
;
420 Some(if self.sess
.opts
.debugging_opts
.dual_proc_macros
{
421 let host_result
= match host_result
{
422 LoadResult
::Previous(..) => {
423 panic
!("host and target proc macros must be loaded in lock-step")
425 LoadResult
::Loaded(library
) => library
,
427 (target_result
.unwrap(), Some(host_result
))
433 fn resolve_crate
<'b
>(
438 dep
: Option
<(&'b CratePaths
, &'b CrateDep
)>,
440 self.maybe_resolve_crate(name
, span
, dep_kind
, dep
).unwrap_or_else(|err
| err
.report())
443 fn maybe_resolve_crate
<'b
>(
447 mut dep_kind
: DepKind
,
448 dep
: Option
<(&'b CratePaths
, &'b CrateDep
)>,
449 ) -> Result
<CrateNum
, LoadError
<'b
>> {
450 info
!("resolving crate `{}`", name
);
451 let (root
, hash
, host_hash
, extra_filename
, path_kind
) = match dep
{
452 Some((root
, dep
)) => (
456 Some(&dep
.extra_filename
[..]),
457 PathKind
::Dependency
,
459 None
=> (None
, None
, None
, None
, PathKind
::Crate
),
461 let result
= if let Some(cnum
) = self.existing_match(name
, hash
, path_kind
) {
462 (LoadResult
::Previous(cnum
), None
)
464 info
!("falling back to a load");
465 let mut locator
= CrateLocator
::new(
467 self.metadata_loader
,
476 Some(false), // is_proc_macro
479 self.load(&mut locator
)
482 dep_kind
= DepKind
::MacrosOnly
;
483 self.load_proc_macro(&mut locator
, path_kind
)
485 .ok_or_else(move || LoadError
::LocatorError(locator
))?
489 (LoadResult
::Previous(cnum
), None
) => {
490 let data
= self.cstore
.get_crate_data(cnum
);
491 if data
.is_proc_macro_crate() {
492 dep_kind
= DepKind
::MacrosOnly
;
494 data
.update_dep_kind(|data_dep_kind
| cmp
::max(data_dep_kind
, dep_kind
));
497 (LoadResult
::Loaded(library
), host_library
) => {
498 Ok(self.register_crate(host_library
, root
, span
, library
, dep_kind
, name
))
504 fn load(&self, locator
: &mut CrateLocator
<'_
>) -> Option
<LoadResult
> {
505 let library
= locator
.maybe_load_library_crate()?
;
507 // In the case that we're loading a crate, but not matching
508 // against a hash, we could load a crate which has the same hash
509 // as an already loaded crate. If this is the case prevent
510 // duplicates by just using the first crate.
512 // Note that we only do this for target triple crates, though, as we
513 // don't want to match a host crate against an equivalent target one
515 let root
= library
.metadata
.get_root();
516 if locator
.triple
== self.sess
.opts
.target_triple
{
517 let mut result
= LoadResult
::Loaded(library
);
518 self.cstore
.iter_crate_data(|cnum
, data
| {
519 if data
.name() == root
.name() && root
.hash() == data
.hash() {
520 assert
!(locator
.hash
.is_none());
521 info
!("load success, going to previous cnum: {}", cnum
);
522 result
= LoadResult
::Previous(cnum
);
527 Some(LoadResult
::Loaded(library
))
531 fn update_extern_crate(&self, cnum
: CrateNum
, extern_crate
: ExternCrate
) {
532 let cmeta
= self.cstore
.get_crate_data(cnum
);
533 if cmeta
.update_extern_crate(extern_crate
) {
534 // Propagate the extern crate info to dependencies if it was updated.
535 let extern_crate
= ExternCrate { dependency_of: cnum, ..extern_crate }
;
536 for &dep_cnum
in cmeta
.dependencies().iter() {
537 self.update_extern_crate(dep_cnum
, extern_crate
);
542 // Go through the crate metadata and load any crates that it references
543 fn resolve_crate_deps(
546 crate_root
: &CrateRoot
<'_
>,
547 metadata
: &MetadataBlob
,
552 debug
!("resolving deps of external crate");
553 if crate_root
.is_proc_macro_crate() {
554 return CrateNumMap
::new();
557 // The map from crate numbers in the crate we're resolving to local crate numbers.
558 // We map 0 and all other holes in the map to our parent crate. The "additional"
559 // self-dependencies should be harmless.
560 std
::iter
::once(krate
)
561 .chain(crate_root
.decode_crate_deps(metadata
).map(|dep
| {
563 "resolving dep crate {} hash: `{}` extra filename: `{}`",
564 dep
.name
, dep
.hash
, dep
.extra_filename
566 let dep_kind
= match dep_kind
{
567 DepKind
::MacrosOnly
=> DepKind
::MacrosOnly
,
570 self.resolve_crate(dep
.name
, span
, dep_kind
, Some((root
, &dep
)))
575 fn dlsym_proc_macros(
578 disambiguator
: CrateDisambiguator
,
580 ) -> &'
static [ProcMacro
] {
581 use crate::dynamic_lib
::DynamicLibrary
;
584 // Make sure the path contains a / or the linker will search for it.
585 let path
= env
::current_dir().unwrap().join(path
);
586 let lib
= match DynamicLibrary
::open(Some(&path
)) {
588 Err(err
) => self.sess
.span_fatal(span
, &err
),
591 let sym
= self.sess
.generate_proc_macro_decls_symbol(disambiguator
);
593 let sym
= match lib
.symbol(&sym
) {
595 Err(err
) => self.sess
.span_fatal(span
, &err
),
597 *(sym
as *const &[ProcMacro
])
600 // Intentionally leak the dynamic library. We can't ever unload it
601 // since the library can make things that will live arbitrarily long.
602 std
::mem
::forget(lib
);
607 fn inject_panic_runtime(&mut self, krate
: &ast
::Crate
) {
608 // If we're only compiling an rlib, then there's no need to select a
609 // panic runtime, so we just skip this section entirely.
611 self.sess
.crate_types
.borrow().iter().any(|ct
| *ct
!= config
::CrateType
::Rlib
);
613 info
!("panic runtime injection skipped, only generating rlib");
617 // If we need a panic runtime, we try to find an existing one here. At
618 // the same time we perform some general validation of the DAG we've got
619 // going such as ensuring everything has a compatible panic strategy.
621 // The logic for finding the panic runtime here is pretty much the same
622 // as the allocator case with the only addition that the panic strategy
623 // compilation mode also comes into play.
624 let desired_strategy
= self.sess
.panic_strategy();
625 let mut runtime_found
= false;
626 let mut needs_panic_runtime
= attr
::contains_name(&krate
.attrs
, sym
::needs_panic_runtime
);
628 self.cstore
.iter_crate_data(|cnum
, data
| {
629 needs_panic_runtime
= needs_panic_runtime
|| data
.needs_panic_runtime();
630 if data
.is_panic_runtime() {
631 // Inject a dependency from all #![needs_panic_runtime] to this
632 // #![panic_runtime] crate.
633 self.inject_dependency_if(cnum
, "a panic runtime", &|data
| {
634 data
.needs_panic_runtime()
636 runtime_found
= runtime_found
|| data
.dep_kind() == DepKind
::Explicit
;
640 // If an explicitly linked and matching panic runtime was found, or if
641 // we just don't need one at all, then we're done here and there's
642 // nothing else to do.
643 if !needs_panic_runtime
|| runtime_found
{
647 // By this point we know that we (a) need a panic runtime and (b) no
648 // panic runtime was explicitly linked. Here we just load an appropriate
649 // default runtime for our panic strategy and then inject the
652 // We may resolve to an already loaded crate (as the crate may not have
653 // been explicitly linked prior to this) and we may re-inject
654 // dependencies again, but both of those situations are fine.
656 // Also note that we have yet to perform validation of the crate graph
657 // in terms of everyone has a compatible panic runtime format, that's
658 // performed later as part of the `dependency_format` module.
659 let name
= match desired_strategy
{
660 PanicStrategy
::Unwind
=> Symbol
::intern("panic_unwind"),
661 PanicStrategy
::Abort
=> Symbol
::intern("panic_abort"),
663 info
!("panic runtime not found -- loading {}", name
);
665 let cnum
= self.resolve_crate(name
, DUMMY_SP
, DepKind
::Implicit
, None
);
666 let data
= self.cstore
.get_crate_data(cnum
);
668 // Sanity check the loaded crate to ensure it is indeed a panic runtime
669 // and the panic strategy is indeed what we thought it was.
670 if !data
.is_panic_runtime() {
671 self.sess
.err(&format
!("the crate `{}` is not a panic runtime", name
));
673 if data
.panic_strategy() != desired_strategy
{
674 self.sess
.err(&format
!(
675 "the crate `{}` does not have the panic \
678 desired_strategy
.desc()
682 self.cstore
.injected_panic_runtime
= Some(cnum
);
683 self.inject_dependency_if(cnum
, "a panic runtime", &|data
| data
.needs_panic_runtime());
686 fn inject_profiler_runtime(&mut self) {
687 if self.sess
.opts
.debugging_opts
.profile
|| self.sess
.opts
.cg
.profile_generate
.enabled() {
688 info
!("loading profiler");
690 let name
= Symbol
::intern("profiler_builtins");
691 let cnum
= self.resolve_crate(name
, DUMMY_SP
, DepKind
::Implicit
, None
);
692 let data
= self.cstore
.get_crate_data(cnum
);
694 // Sanity check the loaded crate to ensure it is indeed a profiler runtime
695 if !data
.is_profiler_runtime() {
696 self.sess
.err("the crate `profiler_builtins` is not a profiler runtime");
701 fn inject_allocator_crate(&mut self, krate
: &ast
::Crate
) {
702 self.cstore
.has_global_allocator
= match &*global_allocator_spans(krate
) {
703 [span1
, span2
, ..] => {
705 .struct_span_err(*span2
, "cannot define multiple global allocators")
706 .span_label(*span2
, "cannot define a new global allocator")
707 .span_label(*span1
, "previous global allocator defined here")
711 spans
=> !spans
.is_empty(),
714 // Check to see if we actually need an allocator. This desire comes
715 // about through the `#![needs_allocator]` attribute and is typically
716 // written down in liballoc.
717 let mut needs_allocator
= attr
::contains_name(&krate
.attrs
, sym
::needs_allocator
);
718 self.cstore
.iter_crate_data(|_
, data
| {
719 needs_allocator
= needs_allocator
|| data
.needs_allocator();
721 if !needs_allocator
{
725 // At this point we've determined that we need an allocator. Let's see
726 // if our compilation session actually needs an allocator based on what
728 let all_rlib
= self.sess
.crate_types
.borrow().iter().all(|ct
| match *ct
{
729 config
::CrateType
::Rlib
=> true,
736 // Ok, we need an allocator. Not only that but we're actually going to
737 // create an artifact that needs one linked in. Let's go find the one
738 // that we're going to link in.
740 // First up we check for global allocators. Look at the crate graph here
741 // and see what's a global allocator, including if we ourselves are a
743 let mut global_allocator
=
744 self.cstore
.has_global_allocator
.then(|| Symbol
::intern("this crate"));
745 self.cstore
.iter_crate_data(|_
, data
| {
746 if !data
.has_global_allocator() {
749 match global_allocator
{
750 Some(other_crate
) => {
751 self.sess
.err(&format
!(
752 "the `#[global_allocator]` in {} \
753 conflicts with global \
759 None
=> global_allocator
= Some(data
.name()),
762 if global_allocator
.is_some() {
763 self.cstore
.allocator_kind
= Some(AllocatorKind
::Global
);
767 // Ok we haven't found a global allocator but we still need an
768 // allocator. At this point our allocator request is typically fulfilled
769 // by the standard library, denoted by the `#![default_lib_allocator]`
771 let mut has_default
= attr
::contains_name(&krate
.attrs
, sym
::default_lib_allocator
);
772 self.cstore
.iter_crate_data(|_
, data
| {
773 if data
.has_default_lib_allocator() {
780 "no global memory allocator found but one is \
781 required; link to std or \
782 add `#[global_allocator]` to a static item \
783 that implements the GlobalAlloc trait.",
786 self.cstore
.allocator_kind
= Some(AllocatorKind
::Default
);
789 fn inject_dependency_if(
793 needs_dep
: &dyn Fn(&CrateMetadata
) -> bool
,
795 // don't perform this validation if the session has errors, as one of
796 // those errors may indicate a circular dependency which could cause
797 // this to stack overflow.
798 if self.sess
.has_errors() {
802 // Before we inject any dependencies, make sure we don't inject a
803 // circular dependency by validating that this crate doesn't
804 // transitively depend on any crates satisfying `needs_dep`.
805 for dep
in self.cstore
.crate_dependencies_in_reverse_postorder(krate
) {
806 let data
= self.cstore
.get_crate_data(dep
);
807 if needs_dep(&data
) {
808 self.sess
.err(&format
!(
809 "the crate `{}` cannot depend \
810 on a crate that needs {}, but \
812 self.cstore
.get_crate_data(krate
).name(),
819 // All crates satisfying `needs_dep` do not explicitly depend on the
820 // crate provided for this compile, but in order for this compilation to
821 // be successfully linked we need to inject a dependency (to order the
822 // crates on the command line correctly).
823 self.cstore
.iter_crate_data(|cnum
, data
| {
824 if !needs_dep(data
) {
828 info
!("injecting a dep from {} to {}", cnum
, krate
);
829 data
.add_dependency(krate
);
833 pub fn postprocess(&mut self, krate
: &ast
::Crate
) {
834 self.inject_profiler_runtime();
835 self.inject_allocator_crate(krate
);
836 self.inject_panic_runtime(krate
);
838 if log_enabled
!(log
::Level
::Info
) {
839 dump_crates(&self.cstore
);
843 pub fn process_extern_crate(
846 definitions
: &Definitions
,
849 ast
::ItemKind
::ExternCrate(orig_name
) => {
851 "resolving extern crate stmt. ident: {} orig_name: {:?}",
852 item
.ident
, orig_name
854 let name
= match orig_name
{
856 crate::validate_crate_name(
863 None
=> item
.ident
.name
,
865 let dep_kind
= if attr
::contains_name(&item
.attrs
, sym
::no_link
) {
871 let cnum
= self.resolve_crate(name
, item
.span
, dep_kind
, None
);
873 let def_id
= definitions
.opt_local_def_id(item
.id
).unwrap();
874 let path_len
= definitions
.def_path(def_id
.index
).data
.len();
875 self.update_extern_crate(
878 src
: ExternCrateSource
::Extern(def_id
),
881 dependency_of
: LOCAL_CRATE
,
890 pub fn process_path_extern(&mut self, name
: Symbol
, span
: Span
) -> CrateNum
{
891 let cnum
= self.resolve_crate(name
, span
, DepKind
::Explicit
, None
);
893 self.update_extern_crate(
896 src
: ExternCrateSource
::Path
,
898 // to have the least priority in `update_extern_crate`
899 path_len
: usize::max_value(),
900 dependency_of
: LOCAL_CRATE
,
907 pub fn maybe_process_path_extern(&mut self, name
: Symbol
, span
: Span
) -> Option
<CrateNum
> {
908 self.maybe_resolve_crate(name
, span
, DepKind
::Explicit
, None
).ok()