Rollup merge of #66496 - petrochenkov:metapriv2, r=eddyb

rustc_metadata: Privatize more things

Continuation of https://github.com/rust-lang/rust/pull/66056.

The most notable change here is that `CrateMetadata` is moved from `cstore.rs` to `decoder.rs`.
Most of uses of `CrateMetadata` fields are in the decoder and uses of `root: CrateRoot` and other fields are so intertwined with each other that it would be hard to move a part of them into `cstore.rs` to privatize `CrateMetadata` fields, so we are going the other way round.

`cstore.rs` can probably be dismantled now, but I'll leave this to some other day.
Similarly, remaining `CrateMetadata` fields can be privatized by introducing some getter/setter methods, but not today.

r? @eddyb
This commit is contained in:
Mazdak Farrokhzad 2019-11-20 18:32:09 +01:00 committed by GitHub
commit 5a84f9b86e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 343 additions and 282 deletions

View file

@ -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;
@ -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();
@ -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(),
}
}
}
@ -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);
}
});
@ -211,15 +207,13 @@ 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) =>
@ -227,55 +221,38 @@ impl<'a> CrateLoader<'a> {
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)
});
Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator, span))
} else {
None
};
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))
});
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);
@ -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)
};
@ -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| {
@ -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
@ -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);
}
@ -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 {
@ -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.

View file

@ -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 {

View file

@ -212,9 +212,8 @@
//! no means all of the necessary details. Take a look at the rest of
//! metadata::locator or metadata::creader for all the juicy details!
use crate::cstore::MetadataBlob;
use crate::creader::Library;
use crate::rmeta::{METADATA_HEADER, rustc_version};
use crate::rmeta::{METADATA_HEADER, rustc_version, MetadataBlob};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::svh::Svh;
@ -249,37 +248,47 @@ use log::{debug, info, warn};
use rustc_error_codes::*;
#[derive(Clone)]
crate struct CrateMismatch {
struct CrateMismatch {
path: PathBuf,
got: String,
}
#[derive(Clone)]
crate struct Context<'a> {
pub sess: &'a Session,
pub span: Span,
pub crate_name: Symbol,
crate struct CrateLocator<'a> {
// Immutable per-session configuration.
sess: &'a Session,
metadata_loader: &'a dyn MetadataLoader,
// Immutable per-search configuration.
crate_name: Symbol,
exact_paths: Vec<PathBuf>,
pub hash: Option<&'a Svh>,
pub host_hash: Option<&'a Svh>,
pub extra_filename: Option<&'a str>,
// points to either self.sess.target.target or self.sess.host, must match triple
extra_filename: Option<&'a str>,
pub target: &'a Target,
pub triple: TargetTriple,
pub filesearch: FileSearch<'a>,
pub root: Option<&'a CratePaths>,
pub rejected_via_hash: Vec<CrateMismatch>,
pub rejected_via_triple: Vec<CrateMismatch>,
pub rejected_via_kind: Vec<CrateMismatch>,
pub rejected_via_version: Vec<CrateMismatch>,
pub rejected_via_filename: Vec<CrateMismatch>,
pub should_match_name: bool,
span: Span,
root: Option<&'a CratePaths>,
pub is_proc_macro: Option<bool>,
pub metadata_loader: &'a dyn MetadataLoader,
// Mutable in-progress state or output.
rejected_via_hash: Vec<CrateMismatch>,
rejected_via_triple: Vec<CrateMismatch>,
rejected_via_kind: Vec<CrateMismatch>,
rejected_via_version: Vec<CrateMismatch>,
rejected_via_filename: Vec<CrateMismatch>,
}
crate struct CratePaths {
pub name: Symbol,
pub source: CrateSource,
name: Symbol,
source: CrateSource,
}
impl CratePaths {
crate fn new(name: Symbol, source: CrateSource) -> CratePaths {
CratePaths { name, source }
}
}
#[derive(Copy, Clone, PartialEq)]
@ -299,7 +308,58 @@ impl fmt::Display for CrateFlavor {
}
}
impl<'a> Context<'a> {
impl<'a> CrateLocator<'a> {
crate fn new(
sess: &'a Session,
metadata_loader: &'a dyn MetadataLoader,
crate_name: Symbol,
hash: Option<&'a Svh>,
host_hash: Option<&'a Svh>,
extra_filename: Option<&'a str>,
is_host: bool,
path_kind: PathKind,
span: Span,
root: Option<&'a CratePaths>,
is_proc_macro: Option<bool>,
) -> CrateLocator<'a> {
CrateLocator {
sess,
metadata_loader,
crate_name,
exact_paths: if hash.is_none() {
sess.opts.externs.get(&crate_name.as_str()).into_iter()
.flat_map(|entry| entry.locations.iter())
.filter_map(|location| location.clone().map(PathBuf::from)).collect()
} else {
// SVH being specified means this is a transitive dependency,
// so `--extern` options do not apply.
Vec::new()
},
hash,
host_hash,
extra_filename,
target: if is_host { &sess.host } else { &sess.target.target },
triple: if is_host {
TargetTriple::from_triple(config::host_triple())
} else {
sess.opts.target_triple.clone()
},
filesearch: if is_host {
sess.host_filesearch(path_kind)
} else {
sess.target_filesearch(path_kind)
},
span,
root,
is_proc_macro,
rejected_via_hash: Vec::new(),
rejected_via_triple: Vec::new(),
rejected_via_kind: Vec::new(),
rejected_via_version: Vec::new(),
rejected_via_filename: Vec::new(),
}
}
crate fn reset(&mut self) {
self.rejected_via_hash.clear();
self.rejected_via_triple.clear();
@ -309,6 +369,9 @@ impl<'a> Context<'a> {
}
crate fn maybe_load_library_crate(&mut self) -> Option<Library> {
if !self.exact_paths.is_empty() {
return self.find_commandline_library();
}
let mut seen_paths = FxHashSet::default();
match self.extra_filename {
Some(s) => self.find_library_crate(s, &mut seen_paths)
@ -434,21 +497,6 @@ impl<'a> Context<'a> {
extra_prefix: &str,
seen_paths: &mut FxHashSet<PathBuf>)
-> Option<Library> {
// If an SVH is specified, then this is a transitive dependency that
// must be loaded via -L plus some filtering.
if self.hash.is_none() {
self.should_match_name = false;
if let Some(entry) = self.sess.opts.externs.get(&self.crate_name.as_str()) {
// Only use `--extern crate_name=path` here, not `--extern crate_name`.
if entry.locations.iter().any(|l| l.is_some()) {
return self.find_commandline_library(
entry.locations.iter().filter_map(|l| l.as_ref()),
);
}
}
self.should_match_name = true;
}
let dypair = self.dylibname();
let staticpair = self.staticlibname();
@ -716,15 +764,16 @@ impl<'a> Context<'a> {
}
let root = metadata.get_root();
if let Some(is_proc_macro) = self.is_proc_macro {
if root.proc_macro_data.is_some() != is_proc_macro {
if let Some(expected_is_proc_macro) = self.is_proc_macro {
let is_proc_macro = root.is_proc_macro_crate();
if is_proc_macro != expected_is_proc_macro {
info!("Rejecting via proc macro: expected {} got {}",
is_proc_macro, root.proc_macro_data.is_some());
expected_is_proc_macro, is_proc_macro);
return None;
}
}
if self.should_match_name {
if self.exact_paths.is_empty() {
if self.crate_name != root.name {
info!("Rejecting via crate name");
return None;
@ -771,9 +820,7 @@ impl<'a> Context<'a> {
(t.options.staticlib_prefix.clone(), t.options.staticlib_suffix.clone())
}
fn find_commandline_library<'b, LOCS>(&mut self, locs: LOCS) -> Option<Library>
where LOCS: Iterator<Item = &'b String>
{
fn find_commandline_library(&mut self) -> Option<Library> {
// First, filter out all libraries that look suspicious. We only accept
// files which actually exist that have the correct naming scheme for
// rlibs/dylibs.
@ -783,10 +830,12 @@ impl<'a> Context<'a> {
let mut rmetas = FxHashMap::default();
let mut dylibs = FxHashMap::default();
{
let locs = locs.map(|l| PathBuf::from(l)).filter(|loc| {
let crate_name = self.crate_name;
let rejected_via_filename = &mut self.rejected_via_filename;
let locs = self.exact_paths.iter().filter(|loc| {
if !loc.exists() {
sess.err(&format!("extern location for {} does not exist: {}",
self.crate_name,
crate_name,
loc.display()));
return false;
}
@ -794,7 +843,7 @@ impl<'a> Context<'a> {
Some(file) => file,
None => {
sess.err(&format!("extern location for {} is not a file: {}",
self.crate_name,
crate_name,
loc.display()));
return false;
}
@ -809,8 +858,8 @@ impl<'a> Context<'a> {
}
}
self.rejected_via_filename.push(CrateMismatch {
path: loc.clone(),
rejected_via_filename.push(CrateMismatch {
path: (*loc).clone(),
got: String::new(),
});
@ -907,7 +956,7 @@ fn get_metadata_section_imp(target: &Target,
rustc_erase_owner!(OwningRef::new(StableDerefMmap(mmap)).map_owner_box())
}
};
let blob = MetadataBlob(raw_bytes);
let blob = MetadataBlob::new(raw_bytes);
if blob.is_compatible() {
Ok(blob)
} else {
@ -927,28 +976,21 @@ pub fn find_plugin_registrar(
let host_triple = TargetTriple::from_triple(config::host_triple());
let is_cross = target_triple != host_triple;
let mut target_only = false;
let mut locate_ctxt = Context {
let mut locator = CrateLocator::new(
sess,
span,
crate_name: name,
hash: None,
host_hash: None,
extra_filename: None,
filesearch: sess.host_filesearch(PathKind::Crate),
target: &sess.host,
triple: host_triple,
root: None,
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: None,
metadata_loader,
};
name,
None, // hash
None, // host_hash
None, // extra_filename
true, // is_host
PathKind::Crate,
span,
None, // root
None, // is_proc_macro
);
let library = locate_ctxt.maybe_load_library_crate().or_else(|| {
let library = locator.maybe_load_library_crate().or_else(|| {
if !is_cross {
return None
}
@ -956,15 +998,15 @@ pub fn find_plugin_registrar(
// try to load a plugin registrar function,
target_only = true;
locate_ctxt.target = &sess.target.target;
locate_ctxt.triple = target_triple;
locate_ctxt.filesearch = sess.target_filesearch(PathKind::Crate);
locator.target = &sess.target.target;
locator.triple = target_triple;
locator.filesearch = sess.target_filesearch(PathKind::Crate);
locate_ctxt.maybe_load_library_crate()
locator.maybe_load_library_crate()
});
let library = match library {
Some(l) => l,
None => locate_ctxt.report_errs(),
None => locator.report_errs(),
};
if target_only {

View file

@ -1,27 +1,30 @@
// Decoding metadata from a single crate's metadata
use crate::cstore::{self, CrateMetadata, MetadataBlob};
use crate::rmeta::*;
use crate::rmeta::table::{FixedSizeEncoding, PerDefTable};
use rustc_index::vec::IndexVec;
use rustc_data_structures::sync::Lrc;
use rustc_data_structures::sync::{Lrc, Lock, Once, AtomicCell};
use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash};
use rustc::hir::map::definitions::DefPathTable;
use rustc::hir;
use rustc::middle::cstore::{CrateSource, ExternCrate};
use rustc::middle::cstore::{LinkagePreference, NativeLibrary, ForeignModule};
use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel};
use rustc::hir::def::{self, Res, DefKind, CtorOf, CtorKind};
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, LocalDefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc::dep_graph::{DepNodeIndex, DepKind};
use rustc_data_structures::svh::Svh;
use rustc::dep_graph::{self, DepNodeIndex};
use rustc::middle::lang_items;
use rustc::mir::{self, interpret};
use rustc::mir::interpret::AllocDecodingSession;
use rustc::mir::interpret::{AllocDecodingSession, AllocDecodingState};
use rustc::session::Session;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::codec::TyDecoder;
use rustc::mir::{Body, Promoted};
use rustc::util::common::record_time;
use rustc::util::captures::Captures;
use std::io;
@ -44,7 +47,86 @@ pub use cstore_impl::{provide, provide_extern};
mod cstore_impl;
crate struct DecodeContext<'a, 'tcx> {
crate struct MetadataBlob(MetadataRef);
// 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 CrateMetadata {
/// The primary crate data - binary metadata blob.
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: 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.
def_path_table: DefPathTable,
/// Trait impl data.
/// FIXME: Used only from queries and can use query cache,
/// so pre-decoding can probably be avoided.
trait_impls: FxHashMap<(u32, DefIndex), Lazy<[DefIndex]>>,
/// Proc macro descriptions for this crate, if it's a proc macro crate.
raw_proc_macros: Option<&'static [ProcMacro]>,
/// Source maps for code from the crate.
source_map_import_info: Once<Vec<ImportedSourceFile>>,
/// Used for decoding interpret::AllocIds in a cached & thread-safe manner.
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`.
dep_node_index: AtomicCell<DepNodeIndex>,
// --- Other significant crate properties ---
/// ID of this crate, from the current compilation session's point of view.
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.
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
private_dep: bool,
/// The hash for the host proc macro. Used to support `-Z dual-proc-macro`.
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>>,
}
/// Holds information about a syntax_pos::SourceFile imported from another crate.
/// See `imported_source_files()` for more information.
struct ImportedSourceFile {
/// This SourceFile's byte-offset within the source_map of its original crate
original_start_pos: syntax_pos::BytePos,
/// The end of this SourceFile within the source_map of its original crate
original_end_pos: syntax_pos::BytePos,
/// The imported SourceFile's representation within the local source_map
translated_source_file: Lrc<syntax_pos::SourceFile>,
}
pub(super) struct DecodeContext<'a, 'tcx> {
opaque: opaque::Decoder<'a>,
cdata: Option<&'a CrateMetadata>,
sess: Option<&'tcx Session>,
@ -60,7 +142,7 @@ crate struct DecodeContext<'a, 'tcx> {
}
/// Abstract over the various ways one can create metadata decoders.
crate trait Metadata<'a, 'tcx>: Copy {
pub(super) trait Metadata<'a, 'tcx>: Copy {
fn raw_bytes(self) -> &'a [u8];
fn cdata(self) -> Option<&'a CrateMetadata> { None }
fn sess(self) -> Option<&'tcx Session> { None }
@ -136,7 +218,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadata, TyCtxt<'tcx>) {
}
impl<'a, 'tcx, T: Encodable + Decodable> Lazy<T> {
crate fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
let mut dcx = metadata.decoder(self.position.get());
dcx.lazy_state = LazyState::NodeStart(self.position);
T::decode(&mut dcx).unwrap()
@ -144,7 +226,7 @@ impl<'a, 'tcx, T: Encodable + Decodable> Lazy<T> {
}
impl<'a: 'x, 'tcx: 'x, 'x, T: Encodable + Decodable> Lazy<[T]> {
crate fn decode<M: Metadata<'a, 'tcx>>(
fn decode<M: Metadata<'a, 'tcx>>(
self,
metadata: M,
) -> impl ExactSizeIterator<Item = T> + Captures<'a> + Captures<'tcx> + 'x {
@ -393,7 +475,11 @@ for DecodeContext<'a, 'tcx> {
implement_ty_decoder!( DecodeContext<'a, 'tcx> );
impl<'tcx> MetadataBlob {
impl MetadataBlob {
crate fn new(metadata_ref: MetadataRef) -> MetadataBlob {
MetadataBlob(metadata_ref)
}
crate fn is_compatible(&self) -> bool {
self.raw_bytes().starts_with(METADATA_HEADER)
}
@ -467,14 +553,62 @@ impl<'tcx> EntryKind<'tcx> {
}
}
impl CrateRoot<'_> {
crate fn is_proc_macro_crate(&self) -> bool {
self.proc_macro_data.is_some()
}
crate fn decode_crate_deps(
&self,
metadata: &'a MetadataBlob,
) -> impl ExactSizeIterator<Item = CrateDep> + Captures<'a> {
self.crate_deps.decode(metadata)
}
}
impl<'a, 'tcx> CrateMetadata {
fn is_proc_macro_crate(&self) -> bool {
self.root.proc_macro_decls_static.is_some()
crate fn new(
sess: &Session,
blob: MetadataBlob,
root: CrateRoot<'static>,
raw_proc_macros: Option<&'static [ProcMacro]>,
cnum: CrateNum,
cnum_map: CrateNumMap,
dep_kind: DepKind,
source: CrateSource,
private_dep: bool,
host_hash: Option<Svh>,
) -> CrateMetadata {
let def_path_table = record_time(&sess.perf_stats.decode_def_path_tables_time, || {
root.def_path_table.decode((&blob, sess))
});
let trait_impls = root.impls.decode((&blob, sess))
.map(|trait_impls| (trait_impls.trait_id, trait_impls.impls)).collect();
let alloc_decoding_state =
AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect());
let dependencies = Lock::new(cnum_map.iter().cloned().collect());
CrateMetadata {
blob,
root,
def_path_table,
trait_impls,
raw_proc_macros,
source_map_import_info: Once::new(),
alloc_decoding_state,
dep_node_index: AtomicCell::new(DepNodeIndex::INVALID),
cnum,
cnum_map,
dependencies,
dep_kind: Lock::new(dep_kind),
source,
private_dep,
host_hash,
extern_crate: Lock::new(None),
}
}
fn is_proc_macro(&self, id: DefIndex) -> bool {
self.is_proc_macro_crate() &&
self.root.proc_macro_data.unwrap().decode(self).find(|x| *x == id).is_some()
self.root.proc_macro_data.and_then(|data| data.decode(self).find(|x| *x == id)).is_some()
}
fn maybe_kind(&self, item_id: DefIndex) -> Option<EntryKind<'tcx>> {
@ -757,7 +891,7 @@ impl<'a, 'tcx> CrateMetadata {
/// Iterates over the language items in the given crate.
fn get_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, usize)] {
if self.is_proc_macro_crate() {
if self.root.is_proc_macro_crate() {
// Proc macro crates do not export any lang-items to the target.
&[]
} else {
@ -773,7 +907,7 @@ impl<'a, 'tcx> CrateMetadata {
&self,
tcx: TyCtxt<'tcx>,
) -> &'tcx FxHashMap<Symbol, DefId> {
tcx.arena.alloc(if self.is_proc_macro_crate() {
tcx.arena.alloc(if self.root.is_proc_macro_crate() {
// Proc macro crates do not export any diagnostic-items to the target.
Default::default()
} else {
@ -1081,7 +1215,7 @@ impl<'a, 'tcx> CrateMetadata {
tcx: TyCtxt<'tcx>,
filter: Option<DefId>,
) -> &'tcx [DefId] {
if self.is_proc_macro_crate() {
if self.root.is_proc_macro_crate() {
// proc-macro crates export no trait impls.
return &[]
}
@ -1125,7 +1259,7 @@ impl<'a, 'tcx> CrateMetadata {
fn get_native_libraries(&self, sess: &Session) -> Vec<NativeLibrary> {
if self.is_proc_macro_crate() {
if self.root.is_proc_macro_crate() {
// Proc macro crates do not have any *target* native libraries.
vec![]
} else {
@ -1134,7 +1268,7 @@ impl<'a, 'tcx> CrateMetadata {
}
fn get_foreign_modules(&self, tcx: TyCtxt<'tcx>) -> &'tcx [ForeignModule] {
if self.is_proc_macro_crate() {
if self.root.is_proc_macro_crate() {
// Proc macro crates do not have any *target* foreign modules.
&[]
} else {
@ -1157,7 +1291,7 @@ impl<'a, 'tcx> CrateMetadata {
}
fn get_missing_lang_items(&self, tcx: TyCtxt<'tcx>) -> &'tcx [lang_items::LangItem] {
if self.is_proc_macro_crate() {
if self.root.is_proc_macro_crate() {
// Proc macro crates do not depend on any target weak lang-items.
&[]
} else {
@ -1181,7 +1315,7 @@ impl<'a, 'tcx> CrateMetadata {
&self,
tcx: TyCtxt<'tcx>,
) -> Vec<(ExportedSymbol<'tcx>, SymbolExportLevel)> {
if self.is_proc_macro_crate() {
if self.root.is_proc_macro_crate() {
// If this crate is a custom derive crate, then we're not even going to
// link those in so we skip those crates.
vec![]
@ -1296,7 +1430,7 @@ impl<'a, 'tcx> CrateMetadata {
fn imported_source_files(
&'a self,
local_source_map: &source_map::SourceMap,
) -> &[cstore::ImportedSourceFile] {
) -> &[ImportedSourceFile] {
self.source_map_import_info.init_locking(|| {
let external_source_map = self.root.source_map.decode(self);
@ -1351,7 +1485,7 @@ impl<'a, 'tcx> CrateMetadata {
local_version.name, start_pos, end_pos,
local_version.start_pos, local_version.end_pos);
cstore::ImportedSourceFile {
ImportedSourceFile {
original_start_pos: start_pos,
original_end_pos: end_pos,
translated_source_file: local_version,
@ -1374,7 +1508,7 @@ impl<'a, 'tcx> CrateMetadata {
// would always write the same value.
let def_path_hash = self.def_path_hash(CRATE_DEF_INDEX);
let dep_node = def_path_hash.to_dep_node(DepKind::CrateMetadata);
let dep_node = def_path_hash.to_dep_node(dep_graph::DepKind::CrateMetadata);
dep_node_index = tcx.dep_graph.dep_node_index_of(&dep_node);
assert!(dep_node_index != DepNodeIndex::INVALID);

View file

@ -52,7 +52,7 @@ macro_rules! provide {
assert!(!$def_id.is_local());
let $cdata = $tcx.crate_data_as_any($def_id.krate);
let $cdata = $cdata.downcast_ref::<cstore::CrateMetadata>()
let $cdata = $cdata.downcast_ref::<rmeta::CrateMetadata>()
.expect("CrateStore created data is not a CrateMetadata");
if $tcx.dep_graph.is_fully_enabled() {
@ -410,7 +410,7 @@ impl cstore::CStore {
let _prof_timer = sess.prof.generic_activity("metadata_load_macro");
let data = self.get_crate_data(id.krate);
if data.is_proc_macro_crate() {
if data.root.is_proc_macro_crate() {
return LoadedMacro::ProcMacro(data.load_proc_macro(id.index, sess));
}

View file

@ -14,6 +14,7 @@ use rustc::ty::{self, Ty, ReprOptions};
use rustc_target::spec::{PanicStrategy, TargetTriple};
use rustc_index::vec::IndexVec;
use rustc_data_structures::svh::Svh;
use rustc_data_structures::sync::MetadataRef;
use rustc_serialize::Encodable;
use syntax::{ast, attr};
use syntax::edition::Edition;
@ -24,6 +25,7 @@ use std::marker::PhantomData;
use std::num::NonZeroUsize;
pub use decoder::{provide, provide_extern};
crate use decoder::{CrateMetadata, CrateNumMap, MetadataBlob};
mod decoder;
mod encoder;
@ -49,7 +51,7 @@ crate const METADATA_HEADER: &[u8; 8] =
/// Additional metadata for a `Lazy<T>` where `T` may not be `Sized`,
/// e.g. for `Lazy<[T]>`, this is the length (count of `T` values).
crate trait LazyMeta {
trait LazyMeta {
type Meta: Copy + 'static;
/// Returns the minimum encoded size.
@ -103,7 +105,7 @@ impl<T: Encodable> LazyMeta for [T] {
#[must_use]
// FIXME(#59875) the `Meta` parameter only exists to dodge
// invariance wrt `T` (coming from the `meta: T::Meta` field).
crate struct Lazy<T, Meta = <T as LazyMeta>::Meta>
struct Lazy<T, Meta = <T as LazyMeta>::Meta>
where T: ?Sized + LazyMeta<Meta = Meta>,
Meta: 'static + Copy,
{
@ -186,7 +188,7 @@ crate struct CrateRoot<'tcx> {
proc_macro_decls_static: Option<DefIndex>,
proc_macro_stability: Option<attr::Stability>,
pub crate_deps: Lazy<[CrateDep]>,
crate_deps: Lazy<[CrateDep]>,
dylib_dependency_formats: Lazy<[Option<LinkagePreference>]>,
lib_features: Lazy<[(Symbol, Option<Symbol>)]>,
lang_items: Lazy<[(DefIndex, usize)]>,
@ -195,16 +197,15 @@ crate struct CrateRoot<'tcx> {
native_libraries: Lazy<[NativeLibrary]>,
foreign_modules: Lazy<[ForeignModule]>,
source_map: Lazy<[syntax_pos::SourceFile]>,
pub def_path_table: Lazy<hir::map::definitions::DefPathTable>,
pub impls: Lazy<[TraitImpls]>,
def_path_table: Lazy<hir::map::definitions::DefPathTable>,
impls: Lazy<[TraitImpls]>,
exported_symbols: Lazy!([(ExportedSymbol<'tcx>, SymbolExportLevel)]),
pub interpret_alloc_index: Lazy<[u32]>,
interpret_alloc_index: Lazy<[u32]>,
per_def: LazyPerDefTables<'tcx>,
/// The DefIndex's of any proc macros delcared by
/// this crate
pub proc_macro_data: Option<Lazy<[DefIndex]>>,
/// The DefIndex's of any proc macros delcared by this crate.
proc_macro_data: Option<Lazy<[DefIndex]>>,
compiler_builtins: bool,
pub needs_allocator: bool,
@ -227,8 +228,8 @@ crate struct CrateDep {
#[derive(RustcEncodable, RustcDecodable)]
crate struct TraitImpls {
pub trait_id: (u32, DefIndex),
pub impls: Lazy<[DefIndex]>,
trait_id: (u32, DefIndex),
impls: Lazy<[DefIndex]>,
}
#[derive(RustcEncodable, RustcDecodable)]