}
}
- pub fn get<'a>(&'a self, tag: usize) -> Doc<'a> {
+ pub fn get(&self, tag: usize) -> Doc<'doc> {
reader::get_doc(*self, tag)
}
self.start == self.end
}
- pub fn as_str_slice<'a>(&'a self) -> &'a str {
+ pub fn as_str_slice(&self) -> &'doc str {
str::from_utf8(&self.data[self.start..self.end]).unwrap()
}
fn crate_attrs(&self, cnum: ast::CrateNum) -> Vec<ast::Attribute>;
fn crate_name(&self, cnum: ast::CrateNum) -> InternedString;
fn crate_hash(&self, cnum: ast::CrateNum) -> Svh;
+ fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString;
fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
-> FnvHashMap<DefId, Vec<ast::Attribute>>;
fn plugin_registrar_fn(&self, cnum: ast::CrateNum) -> Option<DefId>;
{ unimplemented!() }
fn crate_name(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
fn crate_hash(&self, cnum: ast::CrateNum) -> Svh { unimplemented!() }
+ fn crate_disambiguator(&self, cnum: ast::CrateNum) -> InternedString { unimplemented!() }
fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
-> FnvHashMap<DefId, Vec<ast::Attribute>>
{ unimplemented!() }
pub plugin_attributes: RefCell<Vec<(String, AttributeType)>>,
pub crate_types: RefCell<Vec<config::CrateType>>,
pub dependency_formats: RefCell<dependency_format::Dependencies>,
- pub crate_metadata: RefCell<Vec<String>>,
+ // The crate_disambiguator is constructed out of all the `-C metadata`
+ // arguments passed to the compiler. Its value together with the crate-name
+ // forms a unique global identifier for the crate. It is used to allow
+ // multiple crates with the same name to coexist. See the
+ // trans::back::symbol_names module for more information.
+ pub crate_disambiguator: RefCell<String>,
pub features: RefCell<feature_gate::Features>,
/// The maximum recursion limit for potentially infinitely recursive
plugin_attributes: RefCell::new(Vec::new()),
crate_types: RefCell::new(Vec::new()),
dependency_formats: RefCell::new(FnvHashMap()),
- crate_metadata: RefCell::new(Vec::new()),
+ crate_disambiguator: RefCell::new(String::new()),
features: RefCell::new(feature_gate::Features::new()),
recursion_limit: Cell::new(64),
next_node_id: Cell::new(1),
&self.hash
}
- pub fn calculate(metadata: &Vec<String>, krate: &hir::Crate) -> Svh {
+ pub fn calculate(crate_disambiguator: &str, krate: &hir::Crate) -> Svh {
// FIXME (#14132): This is better than it used to be, but it still not
// ideal. We now attempt to hash only the relevant portions of the
// Crate AST as well as the top-level crate attributes. (However,
// avoid collisions.
let mut state = SipHasher::new();
- for data in metadata {
- data.hash(&mut state);
- }
+ "crate_disambiguator".hash(&mut state);
+ crate_disambiguator.len().hash(&mut state);
+ crate_disambiguator.hash(&mut state);
{
let mut visit = svh_visitor::make(&mut state, krate);
use rustc::middle::ty::TyCtxt;
use rustc::util::common::time;
use rustc::util::nodemap::NodeSet;
+use rustc_back::sha2::{Sha256, Digest};
use rustc_borrowck as borrowck;
use rustc_resolve as resolve;
use rustc_metadata::macro_import;
})?;
*sess.crate_types.borrow_mut() = collect_crate_types(sess, &krate.attrs);
- *sess.crate_metadata.borrow_mut() = collect_crate_metadata(sess, &krate.attrs);
+ *sess.crate_disambiguator.borrow_mut() = compute_crate_disambiguator(sess);
time(time_passes, "recursion limit", || {
middle::recursion_limit::update_recursion_limit(sess, &krate);
.collect()
}
-pub fn collect_crate_metadata(session: &Session, _attrs: &[ast::Attribute]) -> Vec<String> {
- session.opts.cg.metadata.clone()
+pub fn compute_crate_disambiguator(session: &Session) -> String {
+ let mut hasher = Sha256::new();
+
+ let mut metadata = session.opts.cg.metadata.clone();
+ // We don't want the crate_disambiguator to dependent on the order
+ // -C metadata arguments, so sort them:
+ metadata.sort();
+ // Every distinct -C metadata value is only incorporated once:
+ metadata.dedup();
+
+ hasher.input_str("metadata");
+ for s in &metadata {
+ // Also incorporate the length of a metadata string, so that we generate
+ // different values for `-Cmetadata=ab -Cmetadata=c` and
+ // `-Cmetadata=a -Cmetadata=bc`
+ hasher.input_str(&format!("{}", s.len())[..]);
+ hasher.input_str(&s[..]);
+ }
+
+ let mut hash = hasher.result_str();
+
+ // If this is an executable, add a special suffix, so that we don't get
+ // symbol conflicts when linking against a library of the same name.
+ if session.crate_types.borrow().contains(&config::CrateTypeExecutable) {
+ hash.push_str("-exe");
+ }
+
+ hash
}
pub fn build_output_filenames(input: &Input,
continue;
}
let crate_types = driver::collect_crate_types(sess, attrs);
- let metadata = driver::collect_crate_metadata(sess, attrs);
- *sess.crate_metadata.borrow_mut() = metadata;
for &style in &crate_types {
let fname = link::filename_for_input(sess, style, &id, &t_outputs);
println!("{}",
pub const tag_crate_hash: usize = 0x103; // top-level only
pub const tag_crate_crate_name: usize = 0x104; // top-level only
+pub const tag_crate_disambiguator: usize = 0x113; // top-level only
pub const tag_crate_dep_crate_name: usize = 0x36;
pub const tag_crate_dep_hash: usize = 0x37;
decoder::get_crate_hash(cdata.data())
}
+ fn crate_disambiguator(&self, cnum: ast::CrateNum) -> token::InternedString
+ {
+ let cdata = self.get_crate_data(cnum);
+ token::intern_and_get_ident(decoder::get_crate_disambiguator(cdata.data()))
+ }
+
fn crate_struct_field_attrs(&self, cnum: ast::CrateNum)
-> FnvHashMap<DefId, Vec<ast::Attribute>>
{
})
}
+pub fn get_crate_disambiguator<'a>(data: &'a [u8]) -> &'a str {
+ let crate_doc = rbml::Doc::new(data);
+ let salt_doc = reader::get_doc(crate_doc, tag_crate_disambiguator);
+ let slice: &'a str = salt_doc.as_str_slice();
+ slice
+}
+
pub fn get_crate_triple(data: &[u8]) -> Option<String> {
let cratedoc = rbml::Doc::new(data);
let triple_doc = reader::maybe_get_doc(cratedoc, tag_crate_triple);
rbml_w.wr_tagged_str(tag_crate_crate_name, crate_name);
}
+fn encode_crate_disambiguator(rbml_w: &mut Encoder, crate_disambiguator: &str) {
+ rbml_w.wr_tagged_str(tag_crate_disambiguator, crate_disambiguator);
+}
+
fn encode_crate_triple(rbml_w: &mut Encoder, triple: &str) {
rbml_w.wr_tagged_str(tag_crate_triple, triple);
}
encode_crate_name(rbml_w, &ecx.link_meta.crate_name);
encode_crate_triple(rbml_w, &ecx.tcx.sess.opts.target_triple);
encode_hash(rbml_w, &ecx.link_meta.crate_hash);
+ encode_crate_disambiguator(rbml_w, &ecx.tcx.sess.crate_disambiguator.borrow());
encode_dylib_dependency_formats(rbml_w, &ecx);
let mut i = rbml_w.writer.seek(SeekFrom::Current(0)).unwrap();
-> LinkMeta {
let r = LinkMeta {
crate_name: name.to_owned(),
- crate_hash: Svh::calculate(&sess.opts.cg.metadata, krate),
+ crate_hash: Svh::calculate(&sess.crate_disambiguator.borrow()[..], krate),
};
info!("{:?}", r);
return r;
output[.. 8].to_hex().to_string()
}
-pub fn def_to_string(_tcx: &ty::ctxt, did: DefId) -> String {
+pub fn def_to_string(_tcx: &TyCtxt, did: DefId) -> String {
format!("{}:{}", did.krate, did.index.as_usize())
}
symbol_hasher.input_str(&link_meta.crate_name);
symbol_hasher.input_str("-");
symbol_hasher.input_str(link_meta.crate_hash.as_str());
- for meta in tcx.sess.crate_metadata.borrow().iter() {
- symbol_hasher.input_str(&meta[..]);
- }
+ symbol_hasher.input_str(&tcx.sess.crate_disambiguator.borrow()[..]);
symbol_hasher.input_str("-");
symbol_hasher.input(&tcx.sess.cstore.encode_type(tcx, t, def_to_string));
// Prefix with 'h' so that it never blends into adjacent digits