Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_metadata: Privatize more things #66496

Merged
merged 10 commits into from
Nov 20, 2019
132 changes: 51 additions & 81 deletions src/librustc_metadata/creader.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,17 @@
//! Validates all used crates and extern libraries and loads their metadata

use crate::cstore::{self, CStore, MetadataBlob};
use crate::locator::{self, CratePaths};
use crate::rmeta::{CrateRoot, CrateDep};
use rustc_data_structures::sync::{Lock, Once, AtomicCell};
use crate::cstore::CStore;
use crate::locator::{CrateLocator, CratePaths};
use crate::rmeta::{CrateMetadata, CrateNumMap, CrateRoot, CrateDep, MetadataBlob};

use rustc::hir::def_id::CrateNum;
use rustc_data_structures::svh::Svh;
use rustc::dep_graph::DepNodeIndex;
use rustc::middle::cstore::DepKind;
use rustc::mir::interpret::AllocDecodingState;
use rustc::session::{Session, CrateDisambiguator};
use rustc::session::config::{Sanitizer, self};
use rustc_target::spec::{PanicStrategy, TargetTriple};
use rustc::session::search_paths::PathKind;
use rustc::middle::cstore::{CrateSource, ExternCrate, ExternCrateSource, MetadataLoaderDyn};
use rustc::util::common::record_time;
use rustc::util::nodemap::FxHashSet;
use rustc::hir::map::Definitions;
use rustc::hir::def_id::LOCAL_CRATE;
Expand Down Expand Up @@ -50,9 +46,9 @@ pub struct CrateLoader<'a> {

fn dump_crates(cstore: &CStore) {
info!("resolved crates:");
cstore.iter_crate_data(|_, data| {
cstore.iter_crate_data(|cnum, data| {
info!(" name: {}", data.root.name);
info!(" cnum: {}", data.cnum);
info!(" cnum: {}", cnum);
info!(" hash: {}", data.root.hash);
info!(" reqd: {:?}", *data.dep_kind.lock());
let CrateSource { dylib, rlib, rmeta } = data.source.clone();
Expand All @@ -68,13 +64,13 @@ enum LoadResult {
}

enum LoadError<'a> {
LocatorError(locator::Context<'a>),
LocatorError(CrateLocator<'a>),
}

impl<'a> LoadError<'a> {
fn report(self) -> ! {
match self {
LoadError::LocatorError(locate_ctxt) => locate_ctxt.report_errs(),
LoadError::LocatorError(locator) => locator.report_errs(),
}
}
}
Expand Down Expand Up @@ -145,7 +141,7 @@ impl<'a> CrateLoader<'a> {
let prev_kind = source.dylib.as_ref().or(source.rlib.as_ref())
.or(source.rmeta.as_ref())
.expect("No sources for crate").1;
if ret.is_none() && (prev_kind == kind || prev_kind == PathKind::All) {
if kind.matches(prev_kind) {
ret = Some(cnum);
}
});
Expand Down Expand Up @@ -211,71 +207,52 @@ impl<'a> CrateLoader<'a> {
let root = if let Some(root) = root {
root
} else {
crate_paths = CratePaths { name: crate_root.name, source: source.clone() };
crate_paths = CratePaths::new(crate_root.name, source.clone());
&crate_paths
};

let cnum_map = self.resolve_crate_deps(root, &crate_root, &metadata, cnum, span, dep_kind);

let dependencies: Vec<CrateNum> = cnum_map.iter().cloned().collect();

let raw_proc_macros = crate_root.proc_macro_data.map(|_| {
let raw_proc_macros = if crate_root.is_proc_macro_crate() {
let temp_root;
let (dlsym_source, dlsym_root) = match &host_lib {
Some(host_lib) =>
(&host_lib.source, { temp_root = host_lib.metadata.get_root(); &temp_root }),
None => (&source, &crate_root),
};
let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate");
self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator, span)
});

let interpret_alloc_index: Vec<u32> = crate_root.interpret_alloc_index
.decode(&metadata)
.collect();
let trait_impls = crate_root
.impls
.decode((&metadata, self.sess))
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls))
.collect();

let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || {
crate_root.def_path_table.decode((&metadata, self.sess))
});
Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator, span))
} else {
None
};

self.cstore.set_crate_data(cnum, cstore::CrateMetadata {
extern_crate: Lock::new(None),
def_path_table,
trait_impls,
root: crate_root,
host_hash,
blob: metadata,
cnum_map,
self.cstore.set_crate_data(cnum, CrateMetadata::new(
self.sess,
metadata,
crate_root,
raw_proc_macros,
cnum,
dependencies: Lock::new(dependencies),
source_map_import_info: Once::new(),
alloc_decoding_state: AllocDecodingState::new(interpret_alloc_index),
dep_kind: Lock::new(dep_kind),
cnum_map,
dep_kind,
source,
private_dep,
raw_proc_macros,
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
});
host_hash,
));

cnum
}

fn load_proc_macro<'b>(
&self,
locate_ctxt: &mut locator::Context<'b>,
locator: &mut CrateLocator<'b>,
path_kind: PathKind,
) -> Option<(LoadResult, Option<Library>)>
where
'a: 'b,
{
// Use a new locator Context so trying to load a proc macro doesn't affect the error
// Use a new crate locator so trying to load a proc macro doesn't affect the error
// message we emit
let mut proc_macro_locator = locate_ctxt.clone();
let mut proc_macro_locator = locator.clone();

// Try to load a proc macro
proc_macro_locator.is_proc_macro = Some(true);
Expand All @@ -287,10 +264,10 @@ impl<'a> CrateLoader<'a> {
LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)),
LoadResult::Loaded(library) => Some(LoadResult::Loaded(library))
};
locate_ctxt.hash = locate_ctxt.host_hash;
// Use the locate_ctxt when looking for the host proc macro crate, as that is required
locator.hash = locator.host_hash;
// Use the locator when looking for the host proc macro crate, as that is required
// so we want it to affect the error message
(locate_ctxt, result)
(locator, result)
} else {
(&mut proc_macro_locator, None)
};
Expand Down Expand Up @@ -350,37 +327,30 @@ impl<'a> CrateLoader<'a> {
(LoadResult::Previous(cnum), None)
} else {
info!("falling back to a load");
let mut locate_ctxt = locator::Context {
sess: self.sess,
span,
crate_name: name,
let mut locator = CrateLocator::new(
self.sess,
self.metadata_loader,
name,
hash,
host_hash,
extra_filename,
filesearch: self.sess.target_filesearch(path_kind),
target: &self.sess.target.target,
triple: self.sess.opts.target_triple.clone(),
false, // is_host
path_kind,
span,
root,
rejected_via_hash: vec![],
rejected_via_triple: vec![],
rejected_via_kind: vec![],
rejected_via_version: vec![],
rejected_via_filename: vec![],
should_match_name: true,
is_proc_macro: Some(false),
metadata_loader: self.metadata_loader,
};
Some(false), // is_proc_macro
);

self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| {
self.load(&mut locator).map(|r| (r, None)).or_else(|| {
dep_kind = DepKind::UnexportedMacrosOnly;
self.load_proc_macro(&mut locate_ctxt, path_kind)
}).ok_or_else(move || LoadError::LocatorError(locate_ctxt))?
self.load_proc_macro(&mut locator, path_kind)
}).ok_or_else(move || LoadError::LocatorError(locator))?
};

match result {
(LoadResult::Previous(cnum), None) => {
let data = self.cstore.get_crate_data(cnum);
if data.root.proc_macro_data.is_some() {
if data.root.is_proc_macro_crate() {
dep_kind = DepKind::UnexportedMacrosOnly;
}
data.dep_kind.with_lock(|data_dep_kind| {
Expand All @@ -395,8 +365,8 @@ impl<'a> CrateLoader<'a> {
}
}

fn load(&self, locate_ctxt: &mut locator::Context<'_>) -> Option<LoadResult> {
let library = locate_ctxt.maybe_load_library_crate()?;
fn load(&self, locator: &mut CrateLocator<'_>) -> Option<LoadResult> {
let library = locator.maybe_load_library_crate()?;

// In the case that we're loading a crate, but not matching
// against a hash, we could load a crate which has the same hash
Expand All @@ -407,11 +377,11 @@ impl<'a> CrateLoader<'a> {
// don't want to match a host crate against an equivalent target one
// already loaded.
let root = library.metadata.get_root();
if locate_ctxt.triple == self.sess.opts.target_triple {
if locator.triple == self.sess.opts.target_triple {
let mut result = LoadResult::Loaded(library);
self.cstore.iter_crate_data(|cnum, data| {
if data.root.name == root.name && root.hash == data.root.hash {
assert!(locate_ctxt.hash.is_none());
assert!(locator.hash.is_none());
info!("load success, going to previous cnum: {}", cnum);
result = LoadResult::Previous(cnum);
}
Expand Down Expand Up @@ -471,16 +441,16 @@ impl<'a> CrateLoader<'a> {
krate: CrateNum,
span: Span,
dep_kind: DepKind)
-> cstore::CrateNumMap {
-> CrateNumMap {
debug!("resolving deps of external crate");
if crate_root.proc_macro_data.is_some() {
return cstore::CrateNumMap::new();
if crate_root.is_proc_macro_crate() {
return CrateNumMap::new();
}

// The map from crate numbers in the crate we're resolving to local crate numbers.
// We map 0 and all other holes in the map to our parent crate. The "additional"
// self-dependencies should be harmless.
std::iter::once(krate).chain(crate_root.crate_deps.decode(metadata).map(|dep| {
std::iter::once(krate).chain(crate_root.decode_crate_deps(metadata).map(|dep| {
info!("resolving dep crate {} hash: `{}` extra filename: `{}`", dep.name, dep.hash,
dep.extra_filename);
if dep.kind == DepKind::UnexportedMacrosOnly {
Expand Down Expand Up @@ -824,7 +794,7 @@ impl<'a> CrateLoader<'a> {
fn inject_dependency_if(&self,
krate: CrateNum,
what: &str,
needs_dep: &dyn Fn(&cstore::CrateMetadata) -> bool) {
needs_dep: &dyn Fn(&CrateMetadata) -> bool) {
// don't perform this validation if the session has errors, as one of
// those errors may indicate a circular dependency which could cause
// this to stack overflow.
Expand Down
100 changes: 7 additions & 93 deletions src/librustc_metadata/cstore.rs
Original file line number Diff line number Diff line change
@@ -1,109 +1,23 @@
// The crate store - a central repo for information collected about external
// crates and libraries

use crate::rmeta;
use rustc::dep_graph::DepNodeIndex;
use rustc::hir::def_id::{CrateNum, DefIndex};
use rustc::hir::map::definitions::DefPathTable;
use rustc::middle::cstore::{CrateSource, DepKind, ExternCrate};
use rustc::mir::interpret::AllocDecodingState;
use crate::rmeta::CrateMetadata;

use rustc_data_structures::sync::Lrc;
use rustc_index::vec::IndexVec;
use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::sync::{Lrc, Lock, MetadataRef, Once, AtomicCell};
use rustc_data_structures::svh::Svh;
use rustc::hir::def_id::CrateNum;
use syntax::ast;
use syntax::edition::Edition;
use syntax_expand::base::SyntaxExtension;
use syntax::expand::allocator::AllocatorKind;
use syntax_pos;
use proc_macro::bridge::client::ProcMacro;
use syntax_expand::base::SyntaxExtension;

pub use crate::rmeta::{provide, provide_extern};

// A map from external crate numbers (as decoded from some crate file) to
// local crate numbers (as generated during this session). Each external
// crate may refer to types in other external crates, and each has their
// own crate numbers.
crate type CrateNumMap = IndexVec<CrateNum, CrateNum>;

crate struct MetadataBlob(pub MetadataRef);

/// Holds information about a syntax_pos::SourceFile imported from another crate.
/// See `imported_source_files()` for more information.
crate struct ImportedSourceFile {
/// This SourceFile's byte-offset within the source_map of its original crate
pub original_start_pos: syntax_pos::BytePos,
/// The end of this SourceFile within the source_map of its original crate
pub original_end_pos: syntax_pos::BytePos,
/// The imported SourceFile's representation within the local source_map
pub translated_source_file: Lrc<syntax_pos::SourceFile>,
}

crate struct CrateMetadata {
/// The primary crate data - binary metadata blob.
crate blob: MetadataBlob,

// --- Some data pre-decoded from the metadata blob, usually for performance ---

/// Properties of the whole crate.
/// NOTE(eddyb) we pass `'static` to a `'tcx` parameter because this
/// lifetime is only used behind `Lazy`, and therefore acts like an
/// universal (`for<'tcx>`), that is paired up with whichever `TyCtxt`
/// is being used to decode those values.
crate root: rmeta::CrateRoot<'static>,
/// For each definition in this crate, we encode a key. When the
/// crate is loaded, we read all the keys and put them in this
/// hashmap, which gives the reverse mapping. This allows us to
/// quickly retrace a `DefPath`, which is needed for incremental
/// compilation support.
crate def_path_table: DefPathTable,
/// Trait impl data.
/// FIXME: Used only from queries and can use query cache,
/// so pre-decoding can probably be avoided.
crate trait_impls: FxHashMap<(u32, DefIndex), rmeta::Lazy<[DefIndex]>>,
/// Proc macro descriptions for this crate, if it's a proc macro crate.
crate raw_proc_macros: Option<&'static [ProcMacro]>,
/// Source maps for code from the crate.
crate source_map_import_info: Once<Vec<ImportedSourceFile>>,
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
crate alloc_decoding_state: AllocDecodingState,
/// The `DepNodeIndex` of the `DepNode` representing this upstream crate.
/// It is initialized on the first access in `get_crate_dep_node_index()`.
/// Do not access the value directly, as it might not have been initialized yet.
/// The field must always be initialized to `DepNodeIndex::INVALID`.
crate dep_node_index: AtomicCell<DepNodeIndex>,

// --- Other significant crate properties ---

/// ID of this crate, from the current compilation session's point of view.
crate cnum: CrateNum,
/// Maps crate IDs as they are were seen from this crate's compilation sessions into
/// IDs as they are seen from the current compilation session.
crate cnum_map: CrateNumMap,
/// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime.
crate dependencies: Lock<Vec<CrateNum>>,
/// How to link (or not link) this crate to the currently compiled crate.
crate dep_kind: Lock<DepKind>,
/// Filesystem location of this crate.
crate source: CrateSource,
/// Whether or not this crate should be consider a private dependency
/// for purposes of the 'exported_private_dependencies' lint
crate private_dep: bool,
/// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
crate host_hash: Option<Svh>,

// --- Data used only for improving diagnostics ---

/// Information about the `extern crate` item or path that caused this crate to be loaded.
/// If this is `None`, then the crate was injected (e.g., by the allocator).
crate extern_crate: Lock<Option<ExternCrate>>,
}

#[derive(Clone)]
pub struct CStore {
metas: IndexVec<CrateNum, Option<Lrc<CrateMetadata>>>,
pub(crate) injected_panic_runtime: Option<CrateNum>,
pub(crate) allocator_kind: Option<AllocatorKind>,
crate injected_panic_runtime: Option<CrateNum>,
crate allocator_kind: Option<AllocatorKind>,
}

pub enum LoadedMacro {
Expand Down
Loading