Skip to content

Commit 7a262d3

Browse files
authored
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
2 parents 8a50e29 + 42b7c32 commit 7a262d3

23 files changed

+214
-159
lines changed

src/librustc/dep_graph/thread.rs

-2
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,6 @@ impl DepGraphThreadData {
118118
/// the buffer is full, this may swap.)
119119
#[inline]
120120
pub fn enqueue(&self, message: DepMessage) {
121-
debug!("enqueue: {:?} tasks_pushed={}", message, self.tasks_pushed.get());
122-
123121
// Regardless of whether dep graph construction is enabled, we
124122
// still want to check that we always have a valid task on the
125123
// stack when a read/write/etc event occurs.

src/librustc_data_structures/indexed_vec.rs

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use std::marker::PhantomData;
1515
use std::ops::{Index, IndexMut, Range};
1616
use std::fmt;
1717
use std::vec;
18+
use std::u32;
1819

1920
use rustc_serialize as serialize;
2021

@@ -31,6 +32,11 @@ impl Idx for usize {
3132
fn index(self) -> usize { self }
3233
}
3334

35+
impl Idx for u32 {
36+
fn new(idx: usize) -> Self { assert!(idx <= u32::MAX as usize); idx as u32 }
37+
fn index(self) -> usize { self as usize }
38+
}
39+
3440
#[derive(Clone)]
3541
pub struct IndexVec<I: Idx, T> {
3642
pub raw: Vec<T>,

src/librustc_metadata/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ rustc = { path = "../librustc" }
1616
rustc_back = { path = "../librustc_back" }
1717
rustc_bitflags = { path = "../librustc_bitflags" }
1818
rustc_const_math = { path = "../librustc_const_math" }
19+
rustc_data_structures = { path = "../librustc_data_structures" }
1920
rustc_errors = { path = "../librustc_errors" }
2021
rustc_llvm = { path = "../librustc_llvm" }
2122
serialize = { path = "../libserialize" }

src/librustc_metadata/astencode.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ use rustc_serialize::{Encodable, EncoderHelpers};
6060

6161
struct DecodeContext<'a, 'b, 'tcx: 'a> {
6262
tcx: TyCtxt<'a, 'tcx, 'tcx>,
63-
cdata: &'b cstore::crate_metadata,
63+
cdata: &'b cstore::CrateMetadata,
6464
from_id_range: IdRange,
6565
to_id_range: IdRange,
6666
// 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> {
121121

122122
/// Decodes an item from its AST in the cdata's metadata and adds it to the
123123
/// ast-map.
124-
pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::crate_metadata,
124+
pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::CrateMetadata,
125125
tcx: TyCtxt<'a, 'tcx, 'tcx>,
126126
parent_def_path: ast_map::DefPath,
127127
parent_did: DefId,
@@ -246,7 +246,7 @@ impl<S:serialize::Encoder> def_id_encoder_helpers for S
246246
trait def_id_decoder_helpers {
247247
fn read_def_id(&mut self, dcx: &DecodeContext) -> DefId;
248248
fn read_def_id_nodcx(&mut self,
249-
cdata: &cstore::crate_metadata) -> DefId;
249+
cdata: &cstore::CrateMetadata) -> DefId;
250250
}
251251

252252
impl<D:serialize::Decoder> def_id_decoder_helpers for D
@@ -258,7 +258,7 @@ impl<D:serialize::Decoder> def_id_decoder_helpers for D
258258
}
259259

260260
fn read_def_id_nodcx(&mut self,
261-
cdata: &cstore::crate_metadata)
261+
cdata: &cstore::CrateMetadata)
262262
-> DefId {
263263
let did: DefId = Decodable::decode(self).unwrap();
264264
decoder::translate_def_id(cdata, did)
@@ -858,17 +858,17 @@ trait rbml_decoder_decoder_helpers<'tcx> {
858858
// Versions of the type reading functions that don't need the full
859859
// DecodeContext.
860860
fn read_ty_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
861-
cdata: &cstore::crate_metadata) -> Ty<'tcx>;
861+
cdata: &cstore::CrateMetadata) -> Ty<'tcx>;
862862
fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
863-
cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
863+
cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>>;
864864
fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
865-
cdata: &cstore::crate_metadata)
865+
cdata: &cstore::CrateMetadata)
866866
-> subst::Substs<'tcx>;
867867
}
868868

869869
impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
870870
fn read_ty_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
871-
cdata: &cstore::crate_metadata)
871+
cdata: &cstore::CrateMetadata)
872872
-> Ty<'tcx> {
873873
self.read_opaque(|_, doc| {
874874
Ok(
@@ -879,15 +879,15 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
879879
}
880880

881881
fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
882-
cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>> {
882+
cdata: &cstore::CrateMetadata) -> Vec<Ty<'tcx>> {
883883
self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
884884
.unwrap()
885885
.into_iter()
886886
.collect()
887887
}
888888

889889
fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
890-
cdata: &cstore::crate_metadata)
890+
cdata: &cstore::CrateMetadata)
891891
-> subst::Substs<'tcx>
892892
{
893893
self.read_opaque(|_, doc| {

src/librustc_metadata/common.rs

+4
Original file line numberDiff line numberDiff line change
@@ -252,3 +252,7 @@ pub fn rustc_version() -> String {
252252
}
253253

254254
pub const tag_panic_strategy: usize = 0x114;
255+
256+
// NB: increment this if you change the format of metadata such that
257+
// rustc_version can't be found.
258+
pub const metadata_encoding_version : &'static [u8] = &[b'r', b'u', b's', b't', 0, 0, 0, 2];

src/librustc_metadata/creader.rs

+40-63
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212

1313
//! Validates all used crates and extern libraries and loads their metadata
1414
15-
use common::rustc_version;
1615
use cstore::{self, CStore, CrateSource, MetadataBlob};
1716
use decoder;
1817
use loader::{self, CratePaths};
@@ -24,7 +23,7 @@ use rustc::session::{config, Session};
2423
use rustc::session::config::PanicStrategy;
2524
use rustc::session::search_paths::PathKind;
2625
use rustc::middle::cstore::{CrateStore, validate_crate_name, ExternCrate};
27-
use rustc::util::nodemap::FnvHashMap;
26+
use rustc::util::nodemap::{FnvHashMap, FnvHashSet};
2827
use rustc::hir::map as hir_map;
2928

3029
use std::cell::{RefCell, Cell};
@@ -132,7 +131,7 @@ struct ExtensionCrate {
132131
}
133132

134133
enum PMDSource {
135-
Registered(Rc<cstore::crate_metadata>),
134+
Registered(Rc<cstore::CrateMetadata>),
136135
Owned(MetadataBlob),
137136
}
138137

@@ -236,25 +235,6 @@ impl<'a> CrateReader<'a> {
236235
return ret;
237236
}
238237

239-
fn verify_rustc_version(&self,
240-
name: &str,
241-
span: Span,
242-
metadata: &MetadataBlob) {
243-
let crate_rustc_version = decoder::crate_rustc_version(metadata.as_slice());
244-
if crate_rustc_version != Some(rustc_version()) {
245-
let mut err = struct_span_fatal!(self.sess, span, E0514,
246-
"the crate `{}` has been compiled with {}, which is \
247-
incompatible with this version of rustc",
248-
name,
249-
crate_rustc_version
250-
.as_ref().map(|s| &**s)
251-
.unwrap_or("an old version of rustc"));
252-
err.help("consider removing the compiled binaries and recompiling \
253-
with your current version of rustc");
254-
err.emit();
255-
}
256-
}
257-
258238
fn verify_no_symbol_conflicts(&self,
259239
span: Span,
260240
metadata: &MetadataBlob) {
@@ -294,9 +274,8 @@ impl<'a> CrateReader<'a> {
294274
span: Span,
295275
lib: loader::Library,
296276
explicitly_linked: bool)
297-
-> (ast::CrateNum, Rc<cstore::crate_metadata>,
277+
-> (ast::CrateNum, Rc<cstore::CrateMetadata>,
298278
cstore::CrateSource) {
299-
self.verify_rustc_version(name, span, &lib.metadata);
300279
self.verify_no_symbol_conflicts(span, &lib.metadata);
301280

302281
// Claim this crate number and cache it
@@ -318,10 +297,10 @@ impl<'a> CrateReader<'a> {
318297

319298
let loader::Library { dylib, rlib, metadata } = lib;
320299

321-
let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), span);
300+
let cnum_map = self.resolve_crate_deps(root, metadata.as_slice(), cnum, span);
322301
let staged_api = self.is_staged_api(metadata.as_slice());
323302

324-
let cmeta = Rc::new(cstore::crate_metadata {
303+
let cmeta = Rc::new(cstore::CrateMetadata {
325304
name: name.to_string(),
326305
extern_crate: Cell::new(None),
327306
index: decoder::load_index(metadata.as_slice()),
@@ -364,7 +343,7 @@ impl<'a> CrateReader<'a> {
364343
span: Span,
365344
kind: PathKind,
366345
explicitly_linked: bool)
367-
-> (ast::CrateNum, Rc<cstore::crate_metadata>, cstore::CrateSource) {
346+
-> (ast::CrateNum, Rc<cstore::CrateMetadata>, cstore::CrateSource) {
368347
let result = match self.existing_match(name, hash, kind) {
369348
Some(cnum) => LoadResult::Previous(cnum),
370349
None => {
@@ -381,6 +360,7 @@ impl<'a> CrateReader<'a> {
381360
rejected_via_hash: vec!(),
382361
rejected_via_triple: vec!(),
383362
rejected_via_kind: vec!(),
363+
rejected_via_version: vec!(),
384364
should_match_name: true,
385365
};
386366
match self.load(&mut load_ctxt) {
@@ -438,8 +418,11 @@ impl<'a> CrateReader<'a> {
438418

439419
fn update_extern_crate(&mut self,
440420
cnum: ast::CrateNum,
441-
mut extern_crate: ExternCrate)
421+
mut extern_crate: ExternCrate,
422+
visited: &mut FnvHashSet<(ast::CrateNum, bool)>)
442423
{
424+
if !visited.insert((cnum, extern_crate.direct)) { return }
425+
443426
let cmeta = self.cstore.get_crate_data(cnum);
444427
let old_extern_crate = cmeta.extern_crate.get();
445428

@@ -458,24 +441,24 @@ impl<'a> CrateReader<'a> {
458441
}
459442

460443
cmeta.extern_crate.set(Some(extern_crate));
461-
462444
// Propagate the extern crate info to dependencies.
463445
extern_crate.direct = false;
464-
for &dep_cnum in cmeta.cnum_map.borrow().values() {
465-
self.update_extern_crate(dep_cnum, extern_crate);
446+
for &dep_cnum in cmeta.cnum_map.borrow().iter() {
447+
self.update_extern_crate(dep_cnum, extern_crate, visited);
466448
}
467449
}
468450

469451
// Go through the crate metadata and load any crates that it references
470452
fn resolve_crate_deps(&mut self,
471453
root: &Option<CratePaths>,
472454
cdata: &[u8],
473-
span : Span)
474-
-> cstore::cnum_map {
455+
krate: ast::CrateNum,
456+
span: Span)
457+
-> cstore::CrateNumMap {
475458
debug!("resolving deps of external crate");
476459
// The map from crate numbers in the crate we're resolving to local crate
477460
// numbers
478-
decoder::get_crate_deps(cdata).iter().map(|dep| {
461+
let map: FnvHashMap<_, _> = decoder::get_crate_deps(cdata).iter().map(|dep| {
479462
debug!("resolving dep crate {} hash: `{}`", dep.name, dep.hash);
480463
let (local_cnum, _, _) = self.resolve_crate(root,
481464
&dep.name,
@@ -485,7 +468,13 @@ impl<'a> CrateReader<'a> {
485468
PathKind::Dependency,
486469
dep.explicitly_linked);
487470
(dep.cnum, local_cnum)
488-
}).collect()
471+
}).collect();
472+
473+
let max_cnum = map.values().cloned().max().unwrap_or(0);
474+
475+
// we map 0 and all other holes in the map to our parent crate. The "additional"
476+
// self-dependencies should be harmless.
477+
(0..max_cnum+1).map(|cnum| map.get(&cnum).cloned().unwrap_or(krate)).collect()
489478
}
490479

491480
fn read_extension_crate(&mut self, span: Span, info: &CrateInfo) -> ExtensionCrate {
@@ -508,6 +497,7 @@ impl<'a> CrateReader<'a> {
508497
rejected_via_hash: vec!(),
509498
rejected_via_triple: vec!(),
510499
rejected_via_kind: vec!(),
500+
rejected_via_version: vec!(),
511501
should_match_name: true,
512502
};
513503
let library = self.load(&mut load_ctxt).or_else(|| {
@@ -826,7 +816,7 @@ impl<'a> CrateReader<'a> {
826816
fn inject_dependency_if(&self,
827817
krate: ast::CrateNum,
828818
what: &str,
829-
needs_dep: &Fn(&cstore::crate_metadata) -> bool) {
819+
needs_dep: &Fn(&cstore::CrateMetadata) -> bool) {
830820
// don't perform this validation if the session has errors, as one of
831821
// those errors may indicate a circular dependency which could cause
832822
// this to stack overflow.
@@ -837,7 +827,17 @@ impl<'a> CrateReader<'a> {
837827
// Before we inject any dependencies, make sure we don't inject a
838828
// circular dependency by validating that this crate doesn't
839829
// transitively depend on any crates satisfying `needs_dep`.
840-
validate(self, krate, krate, what, needs_dep);
830+
for dep in self.cstore.crate_dependencies_in_rpo(krate) {
831+
let data = self.cstore.get_crate_data(dep);
832+
if needs_dep(&data) {
833+
self.sess.err(&format!("the crate `{}` cannot depend \
834+
on a crate that needs {}, but \
835+
it depends on `{}`",
836+
self.cstore.get_crate_data(krate).name(),
837+
what,
838+
data.name()));
839+
}
840+
}
841841

842842
// All crates satisfying `needs_dep` do not explicitly depend on the
843843
// crate provided for this compile, but in order for this compilation to
@@ -849,32 +849,8 @@ impl<'a> CrateReader<'a> {
849849
}
850850

851851
info!("injecting a dep from {} to {}", cnum, krate);
852-
let mut cnum_map = data.cnum_map.borrow_mut();
853-
let remote_cnum = cnum_map.len() + 1;
854-
let prev = cnum_map.insert(remote_cnum as ast::CrateNum, krate);
855-
assert!(prev.is_none());
852+
data.cnum_map.borrow_mut().push(krate);
856853
});
857-
858-
fn validate(me: &CrateReader,
859-
krate: ast::CrateNum,
860-
root: ast::CrateNum,
861-
what: &str,
862-
needs_dep: &Fn(&cstore::crate_metadata) -> bool) {
863-
let data = me.cstore.get_crate_data(krate);
864-
if needs_dep(&data) {
865-
let krate_name = data.name();
866-
let data = me.cstore.get_crate_data(root);
867-
let root_name = data.name();
868-
me.sess.err(&format!("the crate `{}` cannot depend \
869-
on a crate that needs {}, but \
870-
it depends on `{}`", root_name, what,
871-
krate_name));
872-
}
873-
874-
for (_, &dep) in data.cnum_map.borrow().iter() {
875-
validate(me, dep, root, what, needs_dep);
876-
}
877-
}
878854
}
879855
}
880856

@@ -948,7 +924,8 @@ impl<'a> LocalCrateReader<'a> {
948924
span: i.span,
949925
direct: true,
950926
path_len: len,
951-
});
927+
},
928+
&mut FnvHashSet());
952929
self.cstore.add_extern_mod_stmt_cnum(info.id, cnum);
953930
}
954931
}

src/librustc_metadata/csearch.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
// except according to those terms.
1010

1111
use cstore;
12+
use common;
1213
use decoder;
1314
use encoder;
1415
use loader;
@@ -588,7 +589,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
588589

589590
fn metadata_encoding_version(&self) -> &[u8]
590591
{
591-
encoder::metadata_encoding_version
592+
common::metadata_encoding_version
592593
}
593594

594595
/// Returns a map from a sufficiently visible external item (i.e. an external item that is

0 commit comments

Comments
 (0)