Auto merge of #34539 - arielb1:metadata-hash, r=alexcrichton
Make the metadata lock more robust Fixes #33778 and friends. I also needed to add a metadata encoding version to rlibs, as they did not have it before. To keep it backwards-compatible, I added 4 zeroes to the start of the metadata, which are treated as an empty length field by older rustcs. r? @alexcrichton
This commit is contained in:
commit
7a262d3034
@ -118,8 +118,6 @@ impl DepGraphThreadData {
|
||||
/// the buffer is full, this may swap.)
|
||||
#[inline]
|
||||
pub fn enqueue(&self, message: DepMessage) {
|
||||
debug!("enqueue: {:?} tasks_pushed={}", message, self.tasks_pushed.get());
|
||||
|
||||
// Regardless of whether dep graph construction is enabled, we
|
||||
// still want to check that we always have a valid task on the
|
||||
// stack when a read/write/etc event occurs.
|
||||
|
@ -15,6 +15,7 @@ use std::marker::PhantomData;
|
||||
use std::ops::{Index, IndexMut, Range};
|
||||
use std::fmt;
|
||||
use std::vec;
|
||||
use std::u32;
|
||||
|
||||
use rustc_serialize as serialize;
|
||||
|
||||
@ -31,6 +32,11 @@ impl Idx for usize {
|
||||
fn index(self) -> usize { self }
|
||||
}
|
||||
|
||||
impl Idx for u32 {
|
||||
fn new(idx: usize) -> Self { assert!(idx <= u32::MAX as usize); idx as u32 }
|
||||
fn index(self) -> usize { self as usize }
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IndexVec<I: Idx, T> {
|
||||
pub raw: Vec<T>,
|
||||
|
@ -16,6 +16,7 @@ rustc = { path = "../librustc" }
|
||||
rustc_back = { path = "../librustc_back" }
|
||||
rustc_bitflags = { path = "../librustc_bitflags" }
|
||||
rustc_const_math = { path = "../librustc_const_math" }
|
||||
rustc_data_structures = { path = "../librustc_data_structures" }
|
||||
rustc_errors = { path = "../librustc_errors" }
|
||||
rustc_llvm = { path = "../librustc_llvm" }
|
||||
serialize = { path = "../libserialize" }
|
||||
|
@ -60,7 +60,7 @@ use rustc_serialize::{Encodable, EncoderHelpers};
|
||||
|
||||
struct DecodeContext<'a, 'b, 'tcx: 'a> {
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cdata: &'b cstore::crate_metadata,
|
||||
cdata: &'b cstore::CrateMetadata,
|
||||
from_id_range: IdRange,
|
||||
to_id_range: IdRange,
|
||||
// Cache the last used filemap for translating spans as an optimization.
|
||||
@ -121,7 +121,7 @@ impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
|
||||
|
||||
/// Decodes an item from its AST in the cdata's metadata and adds it to the
|
||||
/// ast-map.
|
||||
pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::crate_metadata,
|
||||
pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata,
|
||||
tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
parent_def_path: ast_map::DefPath,
|
||||
parent_did: DefId,
|
||||
@ -246,7 +246,7 @@ impl<S:serialize::Encoder> def_id_encoder_helpers for S
|
||||
trait def_id_decoder_helpers {
|
||||
fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId;
|
||||
fn read_def_id_nodcx(&mut self,
|
||||
cdata: &cstore::crate_metadata) -> DefId;
|
||||
cdata: &cstore::CrateMetadata) -> DefId;
|
||||
}
|
||||
|
||||
impl<D:serialize::Decoder> def_id_decoder_helpers for D
|
||||
@ -258,7 +258,7 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
|
||||
}
|
||||
|
||||
fn read_def_id_nodcx(&mut self,
|
||||
cdata: &cstore::crate_metadata)
|
||||
cdata: &cstore::CrateMetadata)
|
||||
-> DefId {
|
||||
let did: DefId = Decodable::decode(self).unwrap();
|
||||
decoder::translate_def_id(cdata, did)
|
||||
@ -858,17 +858,17 @@ trait rbml_decoder_decoder_helpers<'tcx> {
|
||||
// Versions of the type reading functions that don't need the full
|
||||
// DecodeContext.
|
||||
fn read_ty_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cdata: &cstore::crate_metadata) -> Ty<'tcx>;
|
||||
cdata: &cstore::CrateMetadata) -> Ty<'tcx>;
|
||||
fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
|
||||
cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>>;
|
||||
fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
cdata: &cstore::crate_metadata)
|
||||
cdata: &cstore::CrateMetadata)
|
||||
-> subst::Substs<'tcx>;
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
fn read_ty_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
|
||||
cdata: &cstore::crate_metadata)
|
||||
cdata: &cstore::CrateMetadata)
|
||||
-> Ty<'tcx> {
|
||||
self.read_opaque(|_, doc| {
|
||||
Ok(
|
||||
@ -879,7 +879,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
}
|
||||
|
||||
fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
|
||||
cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>> {
|
||||
cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>> {
|
||||
self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
@ -887,7 +887,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
}
|
||||
|
||||
fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
|
||||
cdata: &cstore::crate_metadata)
|
||||
cdata: &cstore::CrateMetadata)
|
||||
-> subst::Substs<'tcx>
|
||||
{
|
||||
self.read_opaque(|_, doc| {
|
||||
|
@ -252,3 +252,7 @@ pub fn rustc_version() -> String {
|
||||
}
|
||||
|
||||
pub const tag_panic_strategy: usize = 0x114;
|
||||
|
||||
// NB: increment this if you change the format of metadata such that
|
||||
// rustc_version can't be found.
|
||||
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2];
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
//! Validates all used crates and extern libraries and loads their metadata
|
||||
|
||||
use common::rustc_version;
|
||||
use cstore::{self, CStore, CrateSource, MetadataBlob};
|
||||
use decoder;
|
||||
use loader::{self, CratePaths};
|
||||
@ -24,7 +23,7 @@ use rustc::session::{config, Session};
|
||||
use rustc::session::config::PanicStrategy;
|
||||
use rustc::session::search_paths::PathKind;
|
||||
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
|
||||
use rustc::util::nodemap::FnvHashMap;
|
||||
use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
|
||||
use rustc::hir::map as hir_map;
|
||||
|
||||
use std::cell::{RefCell, Cell};
|
||||
@ -132,7 +131,7 @@ struct ExtensionCrate {
|
||||
}
|
||||
|
||||
enum PMDSource {
|
||||
Registered(Rc<cstore::crate_metadata>),
|
||||
Registered(Rc<cstore::CrateMetadata>),
|
||||
Owned(MetadataBlob),
|
||||
}
|
||||
|
||||
@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
|
||||
return ret;
|
||||
}
|
||||
|
||||
fn verify_rustc_version(&self,
|
||||
name: &str,
|
||||
span: Span,
|
||||
metadata: &MetadataBlob) {
|
||||
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
|
||||
if crate_rustc_version != Some(rustc_version()) {
|
||||
let mut err = struct_span_fatal!(self.sess, span, E0514,
|
||||
"the crate `{}` has been compiled with {}, which is \
|
||||
incompatible with this version of rustc",
|
||||
name,
|
||||
crate_rustc_version
|
||||
.as_ref().map(|s| &**s)
|
||||
.unwrap_or("an old version of rustc"));
|
||||
err.help("consider removing the compiled binaries and recompiling \
|
||||
with your current version of rustc");
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
fn verify_no_symbol_conflicts(&self,
|
||||
span: Span,
|
||||
metadata: &MetadataBlob) {
|
||||
@ -294,9 +274,8 @@ impl<'a> CrateReader<'a> {
|
||||
span: Span,
|
||||
lib: loader::Library,
|
||||
explicitly_linked: bool)
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
|
||||
-> (ast::CrateNum, Rc<cstore::CrateMetadata>,
|
||||
cstore::CrateSource) {
|
||||
self.verify_rustc_version(name, span, &lib.metadata);
|
||||
self.verify_no_symbol_conflicts(span, &lib.metadata);
|
||||
|
||||
// Claim this crate number and cache it
|
||||
@ -318,10 +297,10 @@ impl<'a> CrateReader<'a> {
|
||||
|
||||
let loader::Library { dylib, rlib, metadata } = lib;
|
||||
|
||||
let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), span);
|
||||
let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span);
|
||||
let staged_api = self.is_staged_api(metadata.as_slice());
|
||||
|
||||
let cmeta = Rc::new(cstore::crate_metadata {
|
||||
let cmeta = Rc::new(cstore::CrateMetadata {
|
||||
name: name.to_string(),
|
||||
extern_crate: Cell::new(None),
|
||||
index: decoder::load_index(metadata.as_slice()),
|
||||
@ -364,7 +343,7 @@ impl<'a> CrateReader<'a> {
|
||||
span: Span,
|
||||
kind: PathKind,
|
||||
explicitly_linked: bool)
|
||||
-> (ast::CrateNum, Rc<cstore::crate_metadata>, cstore::CrateSource) {
|
||||
-> (ast::CrateNum, Rc<cstore::CrateMetadata>, cstore::CrateSource) {
|
||||
let result = match self.existing_match(name, hash, kind) {
|
||||
Some(cnum) => LoadResult::Previous(cnum),
|
||||
None => {
|
||||
@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
|
||||
rejected_via_hash: vec!(),
|
||||
rejected_via_triple: vec!(),
|
||||
rejected_via_kind: vec!(),
|
||||
rejected_via_version: vec!(),
|
||||
should_match_name: true,
|
||||
};
|
||||
match self.load(&mut load_ctxt) {
|
||||
@ -438,8 +418,11 @@ impl<'a> CrateReader<'a> {
|
||||
|
||||
fn update_extern_crate(&mut self,
|
||||
cnum: ast::CrateNum,
|
||||
mut extern_crate: ExternCrate)
|
||||
mut extern_crate: ExternCrate,
|
||||
visited: &mut FnvHashSet<(ast::CrateNum, bool)>)
|
||||
{
|
||||
if !visited.insert((cnum, extern_crate.direct)) { return }
|
||||
|
||||
let cmeta = self.cstore.get_crate_data(cnum);
|
||||
let old_extern_crate = cmeta.extern_crate.get();
|
||||
|
||||
@ -458,11 +441,10 @@ impl<'a> CrateReader<'a> {
|
||||
}
|
||||
|
||||
cmeta.extern_crate.set(Some(extern_crate));
|
||||
|
||||
// Propagate the extern crate info to dependencies.
|
||||
extern_crate.direct = false;
|
||||
for &dep_cnum in cmeta.cnum_map.borrow().values() {
|
||||
self.update_extern_crate(dep_cnum, extern_crate);
|
||||
for &dep_cnum in cmeta.cnum_map.borrow().iter() {
|
||||
self.update_extern_crate(dep_cnum, extern_crate, visited);
|
||||
}
|
||||
}
|
||||
|
||||
@ -470,12 +452,13 @@ impl<'a> CrateReader<'a> {
|
||||
fn resolve_crate_deps(&mut self,
|
||||
root: &Option<CratePaths>,
|
||||
cdata: &[u8],
|
||||
span : Span)
|
||||
-> cstore::cnum_map {
|
||||
krate: ast::CrateNum,
|
||||
span: Span)
|
||||
-> cstore::CrateNumMap {
|
||||
debug!("resolving deps of external crate");
|
||||
// The map from crate numbers in the crate we're resolving to local crate
|
||||
// numbers
|
||||
decoder::get_crate_deps(cdata).iter().map(|dep| {
|
||||
let map: FnvHashMap<_, _> = decoder::get_crate_deps(cdata).iter().map(|dep| {
|
||||
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
|
||||
let (local_cnum, _, _) = self.resolve_crate(root,
|
||||
&dep.name,
|
||||
@ -485,7 +468,13 @@ impl<'a> CrateReader<'a> {
|
||||
PathKind::Dependency,
|
||||
dep.explicitly_linked);
|
||||
(dep.cnum, local_cnum)
|
||||
}).collect()
|
||||
}).collect();
|
||||
|
||||
let max_cnum = map.values().cloned().max().unwrap_or(0);
|
||||
|
||||
// we map 0 and all other holes in the map to our parent crate. The "additional"
|
||||
// self-dependencies should be harmless.
|
||||
(0..max_cnum+1).map(|cnum| map.get(&cnum).cloned().unwrap_or(krate)).collect()
|
||||
}
|
||||
|
||||
fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate {
|
||||
@ -508,6 +497,7 @@ impl<'a> CrateReader<'a> {
|
||||
rejected_via_hash: vec!(),
|
||||
rejected_via_triple: vec!(),
|
||||
rejected_via_kind: vec!(),
|
||||
rejected_via_version: vec!(),
|
||||
should_match_name: true,
|
||||
};
|
||||
let library = self.load(&mut load_ctxt).or_else(|| {
|
||||
@ -826,7 +816,7 @@ impl<'a> CrateReader<'a> {
|
||||
fn inject_dependency_if(&self,
|
||||
krate: ast::CrateNum,
|
||||
what: &str,
|
||||
needs_dep: &Fn(&cstore::crate_metadata) -> bool) {
|
||||
needs_dep: &Fn(&cstore::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.
|
||||
@ -837,7 +827,17 @@ impl<'a> CrateReader<'a> {
|
||||
// Before we inject any dependencies, make sure we don't inject a
|
||||
// circular dependency by validating that this crate doesn't
|
||||
// transitively depend on any crates satisfying `needs_dep`.
|
||||
validate(self, krate, krate, what, needs_dep);
|
||||
for dep in self.cstore.crate_dependencies_in_rpo(krate) {
|
||||
let data = self.cstore.get_crate_data(dep);
|
||||
if needs_dep(&data) {
|
||||
self.sess.err(&format!("the crate `{}` cannot depend \
|
||||
on a crate that needs {}, but \
|
||||
it depends on `{}`",
|
||||
self.cstore.get_crate_data(krate).name(),
|
||||
what,
|
||||
data.name()));
|
||||
}
|
||||
}
|
||||
|
||||
// All crates satisfying `needs_dep` do not explicitly depend on the
|
||||
// crate provided for this compile, but in order for this compilation to
|
||||
@ -849,32 +849,8 @@ impl<'a> CrateReader<'a> {
|
||||
}
|
||||
|
||||
info!("injecting a dep from {} to {}", cnum, krate);
|
||||
let mut cnum_map = data.cnum_map.borrow_mut();
|
||||
let remote_cnum = cnum_map.len() + 1;
|
||||
let prev = cnum_map.insert(remote_cnum as ast::CrateNum, krate);
|
||||
assert!(prev.is_none());
|
||||
data.cnum_map.borrow_mut().push(krate);
|
||||
});
|
||||
|
||||
fn validate(me: &CrateReader,
|
||||
krate: ast::CrateNum,
|
||||
root: ast::CrateNum,
|
||||
what: &str,
|
||||
needs_dep: &Fn(&cstore::crate_metadata) -> bool) {
|
||||
let data = me.cstore.get_crate_data(krate);
|
||||
if needs_dep(&data) {
|
||||
let krate_name = data.name();
|
||||
let data = me.cstore.get_crate_data(root);
|
||||
let root_name = data.name();
|
||||
me.sess.err(&format!("the crate `{}` cannot depend \
|
||||
on a crate that needs {}, but \
|
||||
it depends on `{}`", root_name, what,
|
||||
krate_name));
|
||||
}
|
||||
|
||||
for (_, &dep) in data.cnum_map.borrow().iter() {
|
||||
validate(me, dep, root, what, needs_dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -948,7 +924,8 @@ impl<'a> LocalCrateReader<'a> {
|
||||
span: i.span,
|
||||
direct: true,
|
||||
path_len: len,
|
||||
});
|
||||
},
|
||||
&mut FnvHashSet());
|
||||
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@
|
||||
// except according to those terms.
|
||||
|
||||
use cstore;
|
||||
use common;
|
||||
use decoder;
|
||||
use encoder;
|
||||
use loader;
|
||||
@ -588,7 +589,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
|
||||
|
||||
fn metadata_encoding_version(&self) -> &[u8]
|
||||
{
|
||||
encoder::metadata_encoding_version
|
||||
common::metadata_encoding_version
|
||||
}
|
||||
|
||||
/// Returns a map from a sufficiently visible external item (i.e. an external item that is
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
pub use self::MetadataBlob::*;
|
||||
|
||||
use common;
|
||||
use creader;
|
||||
use decoder;
|
||||
use index;
|
||||
@ -26,6 +27,7 @@ use rustc::hir::map::DefKey;
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::middle::cstore::{ExternCrate};
|
||||
use rustc::session::config::PanicStrategy;
|
||||
use rustc_data_structures::indexed_vec::IndexVec;
|
||||
use rustc::util::nodemap::{FnvHashMap, NodeMap, NodeSet, DefIdMap};
|
||||
|
||||
use std::cell::{RefCell, Ref, Cell};
|
||||
@ -46,7 +48,7 @@ pub use middle::cstore::{CrateSource, LinkMeta};
|
||||
// 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.
|
||||
pub type cnum_map = FnvHashMap<ast::CrateNum, ast::CrateNum>;
|
||||
pub type CrateNumMap = IndexVec<ast::CrateNum, ast::CrateNum>;
|
||||
|
||||
pub enum MetadataBlob {
|
||||
MetadataVec(Bytes),
|
||||
@ -64,7 +66,7 @@ pub struct ImportedFileMap {
|
||||
pub translated_filemap: Rc<syntax_pos::FileMap>
|
||||
}
|
||||
|
||||
pub struct crate_metadata {
|
||||
pub struct CrateMetadata {
|
||||
pub name: String,
|
||||
|
||||
/// Information about the extern crate that caused this crate to
|
||||
@ -73,7 +75,7 @@ pub struct crate_metadata {
|
||||
pub extern_crate: Cell<Option<ExternCrate>>,
|
||||
|
||||
pub data: MetadataBlob,
|
||||
pub cnum_map: RefCell<cnum_map>,
|
||||
pub cnum_map: RefCell<CrateNumMap>,
|
||||
pub cnum: ast::CrateNum,
|
||||
pub codemap_import_info: RefCell<Vec<ImportedFileMap>>,
|
||||
pub staged_api: bool,
|
||||
@ -97,7 +99,7 @@ pub struct crate_metadata {
|
||||
|
||||
pub struct CStore {
|
||||
pub dep_graph: DepGraph,
|
||||
metas: RefCell<FnvHashMap<ast::CrateNum, Rc<crate_metadata>>>,
|
||||
metas: RefCell<FnvHashMap<ast::CrateNum, Rc<CrateMetadata>>>,
|
||||
/// Map from NodeId's of local extern crate statements to crate numbers
|
||||
extern_mod_crate_map: RefCell<NodeMap<ast::CrateNum>>,
|
||||
used_crate_sources: RefCell<Vec<CrateSource>>,
|
||||
@ -128,7 +130,7 @@ impl CStore {
|
||||
self.metas.borrow().len() as ast::CrateNum + 1
|
||||
}
|
||||
|
||||
pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<crate_metadata> {
|
||||
pub fn get_crate_data(&self, cnum: ast::CrateNum) -> Rc<CrateMetadata> {
|
||||
self.metas.borrow().get(&cnum).unwrap().clone()
|
||||
}
|
||||
|
||||
@ -137,12 +139,12 @@ impl CStore {
|
||||
decoder::get_crate_hash(cdata.data())
|
||||
}
|
||||
|
||||
pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<crate_metadata>) {
|
||||
pub fn set_crate_data(&self, cnum: ast::CrateNum, data: Rc<CrateMetadata>) {
|
||||
self.metas.borrow_mut().insert(cnum, data);
|
||||
}
|
||||
|
||||
pub fn iter_crate_data<I>(&self, mut i: I) where
|
||||
I: FnMut(ast::CrateNum, &Rc<crate_metadata>),
|
||||
I: FnMut(ast::CrateNum, &Rc<CrateMetadata>),
|
||||
{
|
||||
for (&k, v) in self.metas.borrow().iter() {
|
||||
i(k, v);
|
||||
@ -151,7 +153,7 @@ impl CStore {
|
||||
|
||||
/// Like `iter_crate_data`, but passes source paths (if available) as well.
|
||||
pub fn iter_crate_data_origins<I>(&self, mut i: I) where
|
||||
I: FnMut(ast::CrateNum, &crate_metadata, Option<CrateSource>),
|
||||
I: FnMut(ast::CrateNum, &CrateMetadata, Option<CrateSource>),
|
||||
{
|
||||
for (&k, v) in self.metas.borrow().iter() {
|
||||
let origin = self.opt_used_crate_source(k);
|
||||
@ -182,6 +184,30 @@ impl CStore {
|
||||
self.statically_included_foreign_items.borrow_mut().clear();
|
||||
}
|
||||
|
||||
pub fn crate_dependencies_in_rpo(&self, krate: ast::CrateNum) -> Vec<ast::CrateNum>
|
||||
{
|
||||
let mut ordering = Vec::new();
|
||||
self.push_dependencies_in_postorder(&mut ordering, krate);
|
||||
ordering.reverse();
|
||||
ordering
|
||||
}
|
||||
|
||||
pub fn push_dependencies_in_postorder(&self,
|
||||
ordering: &mut Vec<ast::CrateNum>,
|
||||
krate: ast::CrateNum)
|
||||
{
|
||||
if ordering.contains(&krate) { return }
|
||||
|
||||
let data = self.get_crate_data(krate);
|
||||
for &dep in data.cnum_map.borrow().iter() {
|
||||
if dep != krate {
|
||||
self.push_dependencies_in_postorder(ordering, dep);
|
||||
}
|
||||
}
|
||||
|
||||
ordering.push(krate);
|
||||
}
|
||||
|
||||
// This method is used when generating the command line to pass through to
|
||||
// system linker. The linker expects undefined symbols on the left of the
|
||||
// command line to be defined in libraries on the right, not the other way
|
||||
@ -194,17 +220,8 @@ impl CStore {
|
||||
pub fn do_get_used_crates(&self, prefer: LinkagePreference)
|
||||
-> Vec<(ast::CrateNum, Option<PathBuf>)> {
|
||||
let mut ordering = Vec::new();
|
||||
fn visit(cstore: &CStore, cnum: ast::CrateNum,
|
||||
ordering: &mut Vec<ast::CrateNum>) {
|
||||
if ordering.contains(&cnum) { return }
|
||||
let meta = cstore.get_crate_data(cnum);
|
||||
for (_, &dep) in meta.cnum_map.borrow().iter() {
|
||||
visit(cstore, dep, ordering);
|
||||
}
|
||||
ordering.push(cnum);
|
||||
}
|
||||
for (&num, _) in self.metas.borrow().iter() {
|
||||
visit(self, num, &mut ordering);
|
||||
self.push_dependencies_in_postorder(&mut ordering, num);
|
||||
}
|
||||
info!("topological ordering: {:?}", ordering);
|
||||
ordering.reverse();
|
||||
@ -264,7 +281,7 @@ impl CStore {
|
||||
}
|
||||
}
|
||||
|
||||
impl crate_metadata {
|
||||
impl CrateMetadata {
|
||||
pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
|
||||
pub fn name(&self) -> &str { decoder::get_crate_name(self.data()) }
|
||||
pub fn hash(&self) -> Svh { decoder::get_crate_hash(self.data()) }
|
||||
@ -312,20 +329,25 @@ impl crate_metadata {
|
||||
}
|
||||
|
||||
impl MetadataBlob {
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
|
||||
let slice = match *self {
|
||||
pub fn as_slice_raw<'a>(&'a self) -> &'a [u8] {
|
||||
match *self {
|
||||
MetadataVec(ref vec) => &vec[..],
|
||||
MetadataArchive(ref ar) => ar.as_slice(),
|
||||
};
|
||||
if slice.len() < 4 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [u8] {
|
||||
let slice = self.as_slice_raw();
|
||||
let len_offset = 4 + common::metadata_encoding_version.len();
|
||||
if slice.len() < len_offset+4 {
|
||||
&[] // corrupt metadata
|
||||
} else {
|
||||
let len = (((slice[0] as u32) << 24) |
|
||||
((slice[1] as u32) << 16) |
|
||||
((slice[2] as u32) << 8) |
|
||||
((slice[3] as u32) << 0)) as usize;
|
||||
if len + 4 <= slice.len() {
|
||||
&slice[4.. len + 4]
|
||||
let len = (((slice[len_offset+0] as u32) << 24) |
|
||||
((slice[len_offset+1] as u32) << 16) |
|
||||
((slice[len_offset+2] as u32) << 8) |
|
||||
((slice[len_offset+3] as u32) << 0)) as usize;
|
||||
if len <= slice.len() - 4 - len_offset {
|
||||
&slice[len_offset + 4..len_offset + len + 4]
|
||||
} else {
|
||||
&[] // corrupt or old metadata
|
||||
}
|
||||
|
@ -15,7 +15,7 @@
|
||||
use self::Family::*;
|
||||
|
||||
use astencode::decode_inlined_item;
|
||||
use cstore::{self, crate_metadata};
|
||||
use cstore::{self, CrateMetadata};
|
||||
use common::*;
|
||||
use def_key;
|
||||
use encoder::def_to_u64;
|
||||
@ -30,7 +30,7 @@ use rustc::util::nodemap::FnvHashMap;
|
||||
use rustc::hir;
|
||||
use rustc::session::config::PanicStrategy;
|
||||
|
||||
use middle::cstore::{LOCAL_CRATE, FoundAst, InlinedItem, LinkagePreference};
|
||||
use middle::cstore::{FoundAst, InlinedItem, LinkagePreference};
|
||||
use middle::cstore::{DefLike, DlDef, DlField, DlImpl, tls};
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::hir::def_id::{DefId, DefIndex};
|
||||
@ -61,9 +61,9 @@ use syntax::print::pprust;
|
||||
use syntax::ptr::P;
|
||||
use syntax_pos::{self, Span, BytePos, NO_EXPANSION};
|
||||
|
||||
pub type Cmd<'a> = &'a crate_metadata;
|
||||
pub type Cmd<'a> = &'a CrateMetadata;
|
||||
|
||||
impl crate_metadata {
|
||||
impl CrateMetadata {
|
||||
fn get_item(&self, item_id: DefIndex) -> Option<rbml::Doc> {
|
||||
self.index.lookup_item(self.data(), item_id).map(|pos| {
|
||||
reader::doc_at(self.data(), pos as usize).unwrap().doc
|
||||
@ -663,7 +663,7 @@ fn each_child_of_item_or_crate<F, G>(intr: Rc<IdentInterner>,
|
||||
mut get_crate_data: G,
|
||||
mut callback: F) where
|
||||
F: FnMut(DefLike, ast::Name, ty::Visibility),
|
||||
G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
|
||||
G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
|
||||
{
|
||||
// Iterate over all children.
|
||||
for child_info_doc in reader::tagged_docs(item_doc, tag_mod_child) {
|
||||
@ -758,7 +758,7 @@ pub fn each_child_of_item<F, G>(intr: Rc<IdentInterner>,
|
||||
get_crate_data: G,
|
||||
callback: F) where
|
||||
F: FnMut(DefLike, ast::Name, ty::Visibility),
|
||||
G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
|
||||
G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
|
||||
{
|
||||
// Find the item.
|
||||
let item_doc = match cdata.get_item(id) {
|
||||
@ -779,7 +779,7 @@ pub fn each_top_level_item_of_crate<F, G>(intr: Rc<IdentInterner>,
|
||||
get_crate_data: G,
|
||||
callback: F) where
|
||||
F: FnMut(DefLike, ast::Name, ty::Visibility),
|
||||
G: FnMut(ast::CrateNum) -> Rc<crate_metadata>,
|
||||
G: FnMut(ast::CrateNum) -> Rc<CrateMetadata>,
|
||||
{
|
||||
let root_doc = rbml::Doc::new(cdata.data());
|
||||
let misc_info_doc = reader::get_doc(root_doc, tag_misc_info);
|
||||
@ -1348,25 +1348,16 @@ pub fn translate_def_id(cdata: Cmd, did: DefId) -> DefId {
|
||||
return DefId { krate: cdata.cnum, index: did.index };
|
||||
}
|
||||
|
||||
match cdata.cnum_map.borrow().get(&did.krate) {
|
||||
Some(&n) => {
|
||||
DefId {
|
||||
krate: n,
|
||||
index: did.index,
|
||||
}
|
||||
}
|
||||
None => bug!("didn't find a crate in the cnum_map")
|
||||
DefId {
|
||||
krate: cdata.cnum_map.borrow()[did.krate],
|
||||
index: did.index
|
||||
}
|
||||
}
|
||||
|
||||
// Translate a DefId from the current compilation environment to a DefId
|
||||
// for an external crate.
|
||||
fn reverse_translate_def_id(cdata: Cmd, did: DefId) -> Option<DefId> {
|
||||
if did.krate == cdata.cnum {
|
||||
return Some(DefId { krate: LOCAL_CRATE, index: did.index });
|
||||
}
|
||||
|
||||
for (&local, &global) in cdata.cnum_map.borrow().iter() {
|
||||
for (local, &global) in cdata.cnum_map.borrow().iter_enumerated() {
|
||||
if global == did.krate {
|
||||
return Some(DefId { krate: local, index: did.index });
|
||||
}
|
||||
@ -1545,10 +1536,7 @@ pub fn get_dylib_dependency_formats(cdata: Cmd)
|
||||
let cnum = spec.split(':').nth(0).unwrap();
|
||||
let link = spec.split(':').nth(1).unwrap();
|
||||
let cnum: ast::CrateNum = cnum.parse().unwrap();
|
||||
let cnum = match cdata.cnum_map.borrow().get(&cnum) {
|
||||
Some(&n) => n,
|
||||
None => bug!("didn't find a crate in the cnum_map")
|
||||
};
|
||||
let cnum = cdata.cnum_map.borrow()[cnum];
|
||||
result.push((cnum, if link == "d" {
|
||||
LinkagePreference::RequireDynamic
|
||||
} else {
|
||||
|
@ -1351,6 +1351,7 @@ fn my_visit_expr(expr: &hir::Expr,
|
||||
|
||||
rbml_w.start_tag(tag_items_data_item);
|
||||
encode_def_id_and_key(ecx, rbml_w, def_id);
|
||||
encode_name(rbml_w, syntax::parse::token::intern("<closure>"));
|
||||
|
||||
rbml_w.start_tag(tag_items_closure_ty);
|
||||
write_closure_type(ecx, rbml_w, &ecx.tcx.tables.borrow().closure_tys[&def_id]);
|
||||
@ -1505,7 +1506,7 @@ fn encode_polarity(rbml_w: &mut Encoder, polarity: hir::ImplPolarity) {
|
||||
|
||||
fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
|
||||
fn get_ordered_deps(cstore: &cstore::CStore)
|
||||
-> Vec<(CrateNum, Rc<cstore::crate_metadata>)> {
|
||||
-> Vec<(CrateNum, Rc<cstore::CrateMetadata>)> {
|
||||
// Pull the cnums and name,vers,hash out of cstore
|
||||
let mut deps = Vec::new();
|
||||
cstore.iter_crate_data(|cnum, val| {
|
||||
@ -1736,7 +1737,7 @@ fn encode_reachable(ecx: &EncodeContext, rbml_w: &mut Encoder) {
|
||||
}
|
||||
|
||||
fn encode_crate_dep(rbml_w: &mut Encoder,
|
||||
dep: &cstore::crate_metadata) {
|
||||
dep: &cstore::CrateMetadata) {
|
||||
rbml_w.start_tag(tag_crate_dep);
|
||||
rbml_w.wr_tagged_str(tag_crate_dep_crate_name, &dep.name());
|
||||
let hash = decoder::get_crate_hash(dep.data());
|
||||
@ -1798,10 +1799,6 @@ fn encode_panic_strategy(rbml_w: &mut Encoder, ecx: &EncodeContext) {
|
||||
}
|
||||
}
|
||||
|
||||
// NB: Increment this as you change the metadata encoding version.
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2 ];
|
||||
|
||||
pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
|
||||
let mut wr = Cursor::new(Vec::new());
|
||||
|
||||
@ -1835,12 +1832,25 @@ pub fn encode_metadata(ecx: EncodeContext, krate: &hir::Crate) -> Vec<u8> {
|
||||
// the length of the metadata to the start of the metadata. Later on this
|
||||
// will allow us to slice the metadata to the precise length that we just
|
||||
// generated regardless of trailing bytes that end up in it.
|
||||
let len = v.len() as u32;
|
||||
v.insert(0, (len >> 0) as u8);
|
||||
v.insert(0, (len >> 8) as u8);
|
||||
v.insert(0, (len >> 16) as u8);
|
||||
v.insert(0, (len >> 24) as u8);
|
||||
return v;
|
||||
//
|
||||
// We also need to store the metadata encoding version here, because
|
||||
// rlibs don't have it. To get older versions of rustc to ignore
|
||||
// this metadata, there are 4 zero bytes at the start, which are
|
||||
// treated as a length of 0 by old compilers.
|
||||
|
||||
let len = v.len();
|
||||
let mut result = vec![];
|
||||
result.push(0);
|
||||
result.push(0);
|
||||
result.push(0);
|
||||
result.push(0);
|
||||
result.extend(metadata_encoding_version.iter().cloned());
|
||||
result.push((len >> 24) as u8);
|
||||
result.push((len >> 16) as u8);
|
||||
result.push((len >> 8) as u8);
|
||||
result.push((len >> 0) as u8);
|
||||
result.extend(v);
|
||||
result
|
||||
}
|
||||
|
||||
fn encode_metadata_inner(rbml_w: &mut Encoder,
|
||||
|
@ -36,6 +36,7 @@ extern crate rustc_errors as errors;
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_back;
|
||||
extern crate rustc_llvm;
|
||||
extern crate rustc_const_math;
|
||||
|
@ -213,8 +213,8 @@
|
||||
//! metadata::loader or metadata::creader for all the juicy details!
|
||||
|
||||
use cstore::{MetadataBlob, MetadataVec, MetadataArchive};
|
||||
use common::{metadata_encoding_version, rustc_version};
|
||||
use decoder;
|
||||
use encoder;
|
||||
|
||||
use rustc::hir::svh::Svh;
|
||||
use rustc::session::Session;
|
||||
@ -260,6 +260,7 @@ pub struct Context<'a> {
|
||||
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 should_match_name: bool,
|
||||
}
|
||||
|
||||
@ -336,6 +337,10 @@ impl<'a> Context<'a> {
|
||||
struct_span_err!(self.sess, self.span, E0462,
|
||||
"found staticlib `{}` instead of rlib or dylib{}",
|
||||
self.ident, add)
|
||||
} else if !self.rejected_via_version.is_empty() {
|
||||
struct_span_err!(self.sess, self.span, E0514,
|
||||
"found crate `{}` compiled by an incompatible version of rustc{}",
|
||||
self.ident, add)
|
||||
} else {
|
||||
struct_span_err!(self.sess, self.span, E0463,
|
||||
"can't find crate for `{}`{}",
|
||||
@ -350,7 +355,7 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
if !self.rejected_via_hash.is_empty() {
|
||||
err.note("perhaps this crate needs to be recompiled?");
|
||||
err.note("perhaps that crate needs to be recompiled?");
|
||||
let mismatches = self.rejected_via_hash.iter();
|
||||
for (i, &CrateMismatch{ ref path, .. }) in mismatches.enumerate() {
|
||||
err.note(&format!("crate `{}` path #{}: {}",
|
||||
@ -367,13 +372,22 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
}
|
||||
if !self.rejected_via_kind.is_empty() {
|
||||
err.help("please recompile this crate using --crate-type lib");
|
||||
err.help("please recompile that crate using --crate-type lib");
|
||||
let mismatches = self.rejected_via_kind.iter();
|
||||
for (i, &CrateMismatch { ref path, .. }) in mismatches.enumerate() {
|
||||
err.note(&format!("crate `{}` path #{}: {}",
|
||||
self.ident, i+1, path.display()));
|
||||
}
|
||||
}
|
||||
if !self.rejected_via_version.is_empty() {
|
||||
err.help(&format!("please recompile that crate using this compiler ({})",
|
||||
rustc_version()));
|
||||
let mismatches = self.rejected_via_version.iter();
|
||||
for (i, &CrateMismatch { ref path, ref got }) in mismatches.enumerate() {
|
||||
err.note(&format!("crate `{}` path #{}: {} compiled by {:?}",
|
||||
self.ident, i+1, path.display(), got));
|
||||
}
|
||||
}
|
||||
|
||||
err.emit();
|
||||
self.sess.abort_if_errors();
|
||||
@ -591,6 +605,17 @@ impl<'a> Context<'a> {
|
||||
}
|
||||
|
||||
fn crate_matches(&mut self, crate_data: &[u8], libpath: &Path) -> Option<Svh> {
|
||||
let crate_rustc_version = decoder::crate_rustc_version(crate_data);
|
||||
if crate_rustc_version != Some(rustc_version()) {
|
||||
let message = crate_rustc_version.unwrap_or(format!("an unknown compiler"));
|
||||
info!("Rejecting via version: expected {} got {}", rustc_version(), message);
|
||||
self.rejected_via_version.push(CrateMismatch {
|
||||
path: libpath.to_path_buf(),
|
||||
got: message
|
||||
});
|
||||
return None;
|
||||
}
|
||||
|
||||
if self.should_match_name {
|
||||
match decoder::maybe_get_crate_name(crate_data) {
|
||||
Some(ref name) if self.crate_name == *name => {}
|
||||
@ -742,6 +767,21 @@ impl ArchiveMetadata {
|
||||
pub fn as_slice<'a>(&'a self) -> &'a [u8] { unsafe { &*self.data } }
|
||||
}
|
||||
|
||||
fn verify_decompressed_encoding_version(blob: &MetadataBlob, filename: &Path)
|
||||
-> Result<(), String>
|
||||
{
|
||||
let data = blob.as_slice_raw();
|
||||
if data.len() < 4+metadata_encoding_version.len() ||
|
||||
!<[u8]>::eq(&data[..4], &[0, 0, 0, 0]) ||
|
||||
&data[4..4+metadata_encoding_version.len()] != metadata_encoding_version
|
||||
{
|
||||
Err((format!("incompatible metadata version found: '{}'",
|
||||
filename.display())))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
// Just a small wrapper to time how long reading metadata takes.
|
||||
fn get_metadata_section(target: &Target, flavor: CrateFlavor, filename: &Path)
|
||||
-> Result<MetadataBlob, String> {
|
||||
@ -772,7 +812,10 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
|
||||
return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
|
||||
None => Err(format!("failed to read rlib metadata: '{}'",
|
||||
filename.display())),
|
||||
Some(blob) => Ok(blob)
|
||||
Some(blob) => {
|
||||
try!(verify_decompressed_encoding_version(&blob, filename));
|
||||
Ok(blob)
|
||||
}
|
||||
};
|
||||
}
|
||||
unsafe {
|
||||
@ -801,12 +844,12 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
|
||||
let cbuf = llvm::LLVMGetSectionContents(si.llsi);
|
||||
let csz = llvm::LLVMGetSectionSize(si.llsi) as usize;
|
||||
let cvbuf: *const u8 = cbuf as *const u8;
|
||||
let vlen = encoder::metadata_encoding_version.len();
|
||||
let vlen = metadata_encoding_version.len();
|
||||
debug!("checking {} bytes of metadata-version stamp",
|
||||
vlen);
|
||||
let minsz = cmp::min(vlen, csz);
|
||||
let buf0 = slice::from_raw_parts(cvbuf, minsz);
|
||||
let version_ok = buf0 == encoder::metadata_encoding_version;
|
||||
let version_ok = buf0 == metadata_encoding_version;
|
||||
if !version_ok {
|
||||
return Err((format!("incompatible metadata version found: '{}'",
|
||||
filename.display())));
|
||||
@ -817,7 +860,11 @@ fn get_metadata_section_imp(target: &Target, flavor: CrateFlavor, filename: &Pat
|
||||
csz - vlen);
|
||||
let bytes = slice::from_raw_parts(cvbuf1, csz - vlen);
|
||||
match flate::inflate_bytes(bytes) {
|
||||
Ok(inflated) => return Ok(MetadataVec(inflated)),
|
||||
Ok(inflated) => {
|
||||
let blob = MetadataVec(inflated);
|
||||
try!(verify_decompressed_encoding_version(&blob, filename));
|
||||
return Ok(blob);
|
||||
}
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
@ -169,8 +169,7 @@ pub struct Instance<'tcx> {
|
||||
|
||||
impl<'tcx> fmt::Display for Instance<'tcx> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[],
|
||||
|tcx| Some(tcx.lookup_item_type(self.def).generics))
|
||||
ppaux::parameterized(f, &self.substs, self.def, ppaux::Ns::Value, &[], |_| None)
|
||||
}
|
||||
}
|
||||
|
||||
|
1
src/rustc/Cargo.lock
generated
1
src/rustc/Cargo.lock
generated
@ -213,6 +213,7 @@ dependencies = [
|
||||
"rustc_back 0.0.0",
|
||||
"rustc_bitflags 0.0.0",
|
||||
"rustc_const_math 0.0.0",
|
||||
"rustc_data_structures 0.0.0",
|
||||
"rustc_errors 0.0.0",
|
||||
"rustc_llvm 0.0.0",
|
||||
"serialize 0.0.0",
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
extern crate a;
|
||||
extern crate b; //~ ERROR: found possibly newer version of crate `a` which `b` depends on
|
||||
//~| NOTE: perhaps this crate needs to be recompiled
|
||||
//~| NOTE: perhaps that crate needs to be recompiled
|
||||
//~| NOTE: crate `a` path #1:
|
||||
//~| NOTE: crate `b` path #1:
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
extern crate uta;
|
||||
extern crate utb; //~ ERROR: found possibly newer version of crate `uta` which `utb` depends
|
||||
//~| NOTE: perhaps this crate needs to be recompiled?
|
||||
//~| NOTE: perhaps that crate needs to be recompiled?
|
||||
//~| NOTE: crate `uta` path #1:
|
||||
//~| NOTE: crate `utb` path #1:
|
||||
|
||||
|
@ -28,7 +28,7 @@ all:
|
||||
# Ensure crateC fails to compile since A1 is "missing" and A2/A3 hashes do not match
|
||||
$(RUSTC) -L $(A2) -L $(A3) crateC.rs >$(LOG) 2>&1 || true
|
||||
grep "error: found possibly newer version of crate \`crateA\` which \`crateB\` depends on" $(LOG)
|
||||
grep "note: perhaps this crate needs to be recompiled?" $(LOG)
|
||||
grep "note: perhaps that crate needs to be recompiled?" $(LOG)
|
||||
grep "note: crate \`crateA\` path #1:" $(LOG)
|
||||
grep "note: crate \`crateA\` path #2:" $(LOG)
|
||||
grep "note: crate \`crateB\` path #1:" $(LOG)
|
||||
|
Loading…
Reference in New Issue
Block a user