diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index fda1ba809526c..49f418d51a82d 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -14,6 +14,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::unhash::UnhashMap; use rustc_index::vec::IndexVec; +use rustc_span::crate_disambiguator::CrateDisambiguator; use rustc_span::hygiene::ExpnId; use rustc_span::symbol::{kw, sym, Symbol}; @@ -338,7 +339,7 @@ impl Definitions { } /// Adds a root definition (no parent) and a few other reserved definitions. - pub fn new(stable_crate_id: StableCrateId) -> Definitions { + pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> Definitions { let key = DefKey { parent: None, disambiguated_data: DisambiguatedDefPathData { @@ -347,6 +348,7 @@ impl Definitions { }, }; + let stable_crate_id = StableCrateId::new(crate_name, crate_disambiguator); let parent_hash = DefPathHash::new(stable_crate_id, 0); let def_path_hash = key.compute_stable_hash(parent_hash); diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 2ed0539841aa3..83e80b55daec1 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -108,7 +108,7 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorReported; use rustc_fs_util::{link_or_copy, LinkOrCopy}; -use rustc_session::{Session, StableCrateId}; +use rustc_session::{CrateDisambiguator, Session}; use std::fs as std_fs; use std::io; @@ -189,7 +189,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu pub fn prepare_session_directory( sess: &Session, crate_name: &str, - stable_crate_id: StableCrateId, + crate_disambiguator: CrateDisambiguator, ) -> Result<(), ErrorReported> { if sess.opts.incremental.is_none() { return Ok(()); @@ -200,7 +200,7 @@ pub fn prepare_session_directory( debug!("prepare_session_directory"); // {incr-comp-dir}/{crate-name-and-disambiguator} - let crate_dir = crate_path(sess, crate_name, stable_crate_id); + let crate_dir = crate_path(sess, crate_name, crate_disambiguator); debug!("crate-dir: {}", crate_dir.display()); create_dir(sess, &crate_dir, "crate")?; @@ -648,12 +648,19 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path(sess: &Session, crate_name: &str, stable_crate_id: StableCrateId) -> PathBuf { +fn crate_path( + sess: &Session, + crate_name: &str, + crate_disambiguator: CrateDisambiguator, +) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); - let stable_crate_id = base_n::encode(stable_crate_id.to_u64() as u128, INT_ENCODE_BASE); + // The full crate disambiguator is really long. 64 bits of it should be + // sufficient. + let crate_disambiguator = crate_disambiguator.to_fingerprint().to_smaller_hash(); + let crate_disambiguator = base_n::encode(crate_disambiguator as u128, INT_ENCODE_BASE); - let crate_name = format!("{}-{}", crate_name, stable_crate_id); + let crate_name = format!("{}-{}", crate_name, crate_disambiguator); incr_dir.join(crate_name) } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index b1f89fd42cced..aa7af609fb54f 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -12,7 +12,7 @@ use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::{box_region_allow_access, declare_box_region_type, parallel}; use rustc_errors::{ErrorReported, PResult}; use rustc_expand::base::ExtCtxt; -use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; +use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::Crate; use rustc_lint::LintStore; use rustc_metadata::creader::CStore; @@ -170,13 +170,9 @@ pub fn register_plugins<'a>( let crate_types = util::collect_crate_types(sess, &krate.attrs); sess.init_crate_types(crate_types); - let stable_crate_id = StableCrateId::new( - crate_name, - sess.crate_types().contains(&CrateType::Executable), - sess.opts.cg.metadata.clone(), - ); - sess.stable_crate_id.set(stable_crate_id).expect("not yet initialized"); - rustc_incremental::prepare_session_directory(sess, &crate_name, stable_crate_id)?; + let disambiguator = util::compute_crate_disambiguator(sess); + sess.crate_disambiguator.set(disambiguator).expect("not yet initialized"); + rustc_incremental::prepare_session_directory(sess, &crate_name, disambiguator)?; if sess.opts.incremental.is_some() { sess.time("incr_comp_garbage_collect_session_directories", || { diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index d1d0eee365d48..6485fbebd665f 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -2,9 +2,11 @@ use rustc_ast::mut_visit::{visit_clobber, MutVisitor, *}; use rustc_ast::ptr::P; use rustc_ast::{self as ast, AttrVec, BlockCheckMode}; use rustc_codegen_ssa::traits::CodegenBackend; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] use rustc_data_structures::jobserver; +use rustc_data_structures::stable_hasher::StableHasher; use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; use rustc_metadata::dynamic_lib::DynamicLibrary; @@ -16,6 +18,7 @@ use rustc_session::config::{self, CrateType}; use rustc_session::config::{ErrorOutputType, Input, OutputFilenames}; use rustc_session::lint::{self, BuiltinLintDiagnostics, LintBuffer}; use rustc_session::parse::CrateConfig; +use rustc_session::CrateDisambiguator; use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::lev_distance::find_best_match_for_name; @@ -484,6 +487,39 @@ pub fn get_codegen_sysroot( } } +pub(crate) fn compute_crate_disambiguator(session: &Session) -> CrateDisambiguator { + use std::hash::Hasher; + + // The crate_disambiguator is a 128 bit hash. The disambiguator is fed + // into various other hashes quite a bit (symbol hashes, incr. comp. hashes, + // debuginfo type IDs, etc), so we don't want it to be too wide. 128 bits + // should still be safe enough to avoid collisions in practice. + let mut hasher = StableHasher::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.write(b"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.write_usize(s.len()); + hasher.write(s.as_bytes()); + } + + // Also incorporate crate type, so that we don't get symbol conflicts when + // linking against a library of the same name, if this is an executable. + let is_exe = session.crate_types().contains(&CrateType::Executable); + hasher.write(if is_exe { b"exe" } else { b"lib" }); + + CrateDisambiguator::from(hasher.finish::()) +} + pub(crate) fn check_attr_crate_type( sess: &Session, attrs: &[ast::Attribute], diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 42c32219aba41..e9ae22f8cedbc 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -21,7 +21,7 @@ use rustc_session::config::{self, CrateType, ExternLocation}; use rustc_session::lint::{self, BuiltinLintDiagnostics, ExternDepSpec}; use rustc_session::output::validate_crate_name; use rustc_session::search_paths::PathKind; -use rustc_session::Session; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -222,8 +222,10 @@ impl<'a> CrateLoader<'a> { metadata_loader: &'a MetadataLoaderDyn, local_crate_name: &str, ) -> Self { + let local_crate_stable_id = + StableCrateId::new(local_crate_name, sess.local_crate_disambiguator()); let mut stable_crate_ids = FxHashMap::default(); - stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE); + stable_crate_ids.insert(local_crate_stable_id, LOCAL_CRATE); CrateLoader { sess, @@ -325,14 +327,17 @@ impl<'a> CrateLoader<'a> { fn verify_no_symbol_conflicts(&self, root: &CrateRoot<'_>) -> Result<(), CrateError> { // Check for (potential) conflicts with the local crate - if self.sess.local_stable_crate_id() == root.stable_crate_id() { + if self.local_crate_name == root.name() + && self.sess.local_crate_disambiguator() == root.disambiguator() + { return Err(CrateError::SymbolConflictsCurrent(root.name())); } // Check for conflicts with any crate loaded so far let mut res = Ok(()); self.cstore.iter_crate_data(|_, other| { - if other.stable_crate_id() == root.stable_crate_id() && // same stable crate id + if other.name() == root.name() && // same crate-name + other.disambiguator() == root.disambiguator() && // same crate-disambiguator other.hash() != root.hash() { // but different SVH @@ -406,7 +411,7 @@ impl<'a> CrateLoader<'a> { None => (&source, &crate_root), }; let dlsym_dylib = dlsym_source.dylib.as_ref().expect("no dylib for a proc-macro crate"); - Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.stable_crate_id())?) + Some(self.dlsym_proc_macros(&dlsym_dylib.0, dlsym_root.disambiguator())?) } else { None }; @@ -659,7 +664,7 @@ impl<'a> CrateLoader<'a> { fn dlsym_proc_macros( &self, path: &Path, - stable_crate_id: StableCrateId, + disambiguator: CrateDisambiguator, ) -> Result<&'static [ProcMacro], CrateError> { // Make sure the path contains a / or the linker will search for it. let path = env::current_dir().unwrap().join(path); @@ -668,7 +673,7 @@ impl<'a> CrateLoader<'a> { Err(s) => return Err(CrateError::DlOpen(s)), }; - let sym = self.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let sym = self.sess.generate_proc_macro_decls_symbol(disambiguator); let decls = unsafe { let sym = match lib.symbol(&sym) { Ok(f) => f, diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index b830c6b2481cc..6e7360950908e 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -226,7 +226,7 @@ use rustc_session::config::{self, CrateType}; use rustc_session::filesearch::{FileDoesntMatch, FileMatches, FileSearch}; use rustc_session::search_paths::PathKind; use rustc_session::utils::CanonicalizedPath; -use rustc_session::{Session, StableCrateId}; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; use rustc_target::spec::{Target, TargetTriple}; @@ -787,7 +787,7 @@ pub fn find_plugin_registrar( metadata_loader: &dyn MetadataLoader, span: Span, name: Symbol, -) -> (PathBuf, StableCrateId) { +) -> (PathBuf, CrateDisambiguator) { match find_plugin_registrar_impl(sess, metadata_loader, name) { Ok(res) => res, // `core` is always available if we got as far as loading plugins. @@ -799,7 +799,7 @@ fn find_plugin_registrar_impl<'a>( sess: &'a Session, metadata_loader: &dyn MetadataLoader, name: Symbol, -) -> Result<(PathBuf, StableCrateId), CrateError> { +) -> Result<(PathBuf, CrateDisambiguator), CrateError> { info!("find plugin registrar `{}`", name); let mut locator = CrateLocator::new( sess, @@ -816,7 +816,7 @@ fn find_plugin_registrar_impl<'a>( match locator.maybe_load_library_crate()? { Some(library) => match library.source.dylib { - Some(dylib) => Ok((dylib.0, library.metadata.get_root().stable_crate_id())), + Some(dylib) => Ok((dylib.0, library.metadata.get_root().disambiguator())), None => Err(CrateError::NonDylibPlugin(name)), }, None => Err(locator.into_error()), diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 59fec58f0a1b3..52cb1e1996e38 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -620,6 +620,10 @@ impl CrateRoot<'_> { self.name } + crate fn disambiguator(&self) -> CrateDisambiguator { + self.disambiguator + } + crate fn hash(&self) -> Svh { self.hash } @@ -1923,8 +1927,8 @@ impl CrateMetadata { self.root.name } - crate fn stable_crate_id(&self) -> StableCrateId { - self.root.stable_crate_id + crate fn disambiguator(&self) -> CrateDisambiguator { + self.root.disambiguator } crate fn hash(&self) -> Svh { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 9e615e48a3cd0..7cec4ce1d91b2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -19,7 +19,7 @@ use rustc_middle::middle::stability::DeprecationEntry; use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, Visibility}; use rustc_session::utils::NativeLibKind; -use rustc_session::{Session, StableCrateId}; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::source_map::{Span, Spanned}; use rustc_span::symbol::Symbol; @@ -186,6 +186,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, } native_libraries => { Lrc::new(cdata.get_native_libraries(tcx.sess)) } foreign_modules => { cdata.get_foreign_modules(tcx) } + crate_disambiguator => { cdata.root.disambiguator } crate_hash => { cdata.root.hash } crate_host_hash => { cdata.host_hash } crate_name => { cdata.root.name } @@ -488,8 +489,8 @@ impl CrateStore for CStore { self.get_crate_data(cnum).root.name } - fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId { - self.get_crate_data(cnum).root.stable_crate_id + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator { + self.get_crate_data(cnum).root.disambiguator } fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 0883977821aa8..7600739800041 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -671,6 +671,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { extra_filename: tcx.sess.opts.cg.extra_filename.clone(), triple: tcx.sess.opts.target_triple.clone(), hash: tcx.crate_hash(LOCAL_CRATE), + disambiguator: tcx.sess.local_crate_disambiguator(), stable_crate_id: tcx.def_path_hash(LOCAL_CRATE.as_def_id()).stable_crate_id(), panic_strategy: tcx.sess.panic_strategy(), edition: tcx.sess.edition(), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 9a3a6284c3610..04fe5cf5890a0 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -18,6 +18,7 @@ use rustc_middle::mir; use rustc_middle::ty::{self, ReprOptions, Ty}; use rustc_serialize::opaque::Encoder; use rustc_session::config::SymbolManglingVersion; +use rustc_session::CrateDisambiguator; use rustc_span::edition::Edition; use rustc_span::hygiene::MacroKind; use rustc_span::symbol::{Ident, Symbol}; @@ -201,6 +202,7 @@ crate struct CrateRoot<'tcx> { triple: TargetTriple, extra_filename: String, hash: Svh, + disambiguator: CrateDisambiguator, stable_crate_id: StableCrateId, panic_strategy: PanicStrategy, edition: Edition, diff --git a/compiler/rustc_middle/src/dep_graph/dep_node.rs b/compiler/rustc_middle/src/dep_graph/dep_node.rs index aa54d1ae7b9d1..8476929eaeced 100644 --- a/compiler/rustc_middle/src/dep_graph/dep_node.rs +++ b/compiler/rustc_middle/src/dep_graph/dep_node.rs @@ -285,7 +285,7 @@ pub type DepNode = rustc_query_system::dep_graph::DepNode; // required that their size stay the same, but we don't want to change // it inadvertently. This assert just ensures we're aware of any change. #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] -static_assert_size!(DepNode, 17); +static_assert_size!(DepNode, 18); #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] static_assert_size!(DepNode, 24); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 07b39c97c492a..20bbf9097f425 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -15,7 +15,6 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::itemlikevisit::ItemLikeVisitor; use rustc_hir::*; use rustc_index::vec::Idx; -use rustc_span::def_id::StableCrateId; use rustc_span::hygiene::MacroKind; use rustc_span::source_map::Spanned; use rustc_span::symbol::{kw, Ident, Symbol}; @@ -991,24 +990,25 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { upstream_crates.hash_stable(&mut hcx, &mut stable_hasher); source_file_names.hash_stable(&mut hcx, &mut stable_hasher); tcx.sess.opts.dep_tracking_hash(true).hash_stable(&mut hcx, &mut stable_hasher); - tcx.sess.local_stable_crate_id().hash_stable(&mut hcx, &mut stable_hasher); + tcx.sess.local_crate_disambiguator().to_fingerprint().hash_stable(&mut hcx, &mut stable_hasher); tcx.untracked_crate.non_exported_macro_attrs.hash_stable(&mut hcx, &mut stable_hasher); let crate_hash: Fingerprint = stable_hasher.finish(); Svh::new(crate_hash.to_smaller_hash()) } -fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(StableCrateId, Svh)> { +fn upstream_crates(cstore: &dyn CrateStore) -> Vec<(Symbol, Fingerprint, Svh)> { let mut upstream_crates: Vec<_> = cstore .crates_untracked() .iter() .map(|&cnum| { - let stable_crate_id = cstore.stable_crate_id_untracked(cnum); + let name = cstore.crate_name_untracked(cnum); + let disambiguator = cstore.crate_disambiguator_untracked(cnum).to_fingerprint(); let hash = cstore.crate_hash_untracked(cnum); - (stable_crate_id, hash) + (name, disambiguator, hash) }) .collect(); - upstream_crates.sort_unstable_by_key(|&(stable_crate_id, _)| stable_crate_id); + upstream_crates.sort_unstable_by_key(|&(name, dis, _)| (name.as_str(), dis)); upstream_crates } diff --git a/compiler/rustc_middle/src/middle/cstore.rs b/compiler/rustc_middle/src/middle/cstore.rs index df578708931fc..f09449ab864b7 100644 --- a/compiler/rustc_middle/src/middle/cstore.rs +++ b/compiler/rustc_middle/src/middle/cstore.rs @@ -14,7 +14,7 @@ use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_macros::HashStable; use rustc_session::search_paths::PathKind; use rustc_session::utils::NativeLibKind; -use rustc_session::StableCrateId; +use rustc_session::CrateDisambiguator; use rustc_span::symbol::Symbol; use rustc_span::Span; use rustc_target::spec::Target; @@ -206,7 +206,7 @@ pub trait CrateStore { // "queries" used in resolve that aren't tracked for incremental compilation fn crate_name_untracked(&self, cnum: CrateNum) -> Symbol; - fn stable_crate_id_untracked(&self, cnum: CrateNum) -> StableCrateId; + fn crate_disambiguator_untracked(&self, cnum: CrateNum) -> CrateDisambiguator; fn crate_hash_untracked(&self, cnum: CrateNum) -> Svh; // This is basically a 1-based range of ints, which is a little diff --git a/compiler/rustc_middle/src/middle/exported_symbols.rs b/compiler/rustc_middle/src/middle/exported_symbols.rs index 5ea78e087f845..288dd03944645 100644 --- a/compiler/rustc_middle/src/middle/exported_symbols.rs +++ b/compiler/rustc_middle/src/middle/exported_symbols.rs @@ -48,8 +48,8 @@ impl<'tcx> ExportedSymbol<'tcx> { pub fn metadata_symbol_name(tcx: TyCtxt<'_>) -> String { format!( - "rust_metadata_{}_{:08x}", + "rust_metadata_{}_{}", tcx.crate_name(LOCAL_CRATE), - tcx.sess.local_stable_crate_id().to_u64(), + tcx.crate_disambiguator(LOCAL_CRATE).to_fingerprint().to_hex() ) } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index c354cdd985b36..74650f50a1c8a 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -490,18 +490,15 @@ impl CodegenUnitNameBuilder<'tcx> { // local crate's ID. Otherwise there can be collisions between CGUs // instantiating stuff for upstream crates. let local_crate_id = if cnum != LOCAL_CRATE { - let local_stable_crate_id = tcx.sess.local_stable_crate_id(); - format!( - "-in-{}.{:08x}", - tcx.crate_name(LOCAL_CRATE), - local_stable_crate_id.to_u64() - ) + let local_crate_disambiguator = format!("{}", tcx.crate_disambiguator(LOCAL_CRATE)); + format!("-in-{}.{}", tcx.crate_name(LOCAL_CRATE), &local_crate_disambiguator[0..8]) } else { String::new() }; - let stable_crate_id = tcx.sess.local_stable_crate_id(); - format!("{}.{:08x}{}", tcx.crate_name(cnum), stable_crate_id.to_u64(), local_crate_id) + let crate_disambiguator = tcx.crate_disambiguator(cnum).to_string(); + // Using a shortened disambiguator of about 40 bits + format!("{}.{}{}", tcx.crate_name(cnum), &crate_disambiguator[0..8], local_crate_id) }); write!(cgu_name, "{}", crate_prefix).unwrap(); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ad624d8d113f9..0860520ef9dfe 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -1237,6 +1237,10 @@ rustc_queries! { query proc_macro_decls_static(_: ()) -> Option { desc { "looking up the derive registrar for a crate" } } + query crate_disambiguator(_: CrateNum) -> CrateDisambiguator { + eval_always + desc { "looking up the disambiguator a crate" } + } // The macro which defines `rustc_metadata::provide_extern` depends on this query's name. // Changing the name should cause a compiler error, but in case that changes, be aware. query crate_hash(_: CrateNum) -> Svh { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 970e669c16f70..047b95f116ec2 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1275,24 +1275,24 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_path_debug_str(self, def_id: DefId) -> String { // We are explicitly not going through queries here in order to get - // crate name and stable crate id since this code is called from debug!() + // crate name and disambiguator since this code is called from debug!() // statements within the query system and we'd run into endless // recursion otherwise. - let (crate_name, stable_crate_id) = if def_id.is_local() { - (self.crate_name, self.sess.local_stable_crate_id()) + let (crate_name, crate_disambiguator) = if def_id.is_local() { + (self.crate_name, self.sess.local_crate_disambiguator()) } else { ( self.cstore.crate_name_untracked(def_id.krate), - self.def_path_hash(def_id.krate.as_def_id()).stable_crate_id(), + self.cstore.crate_disambiguator_untracked(def_id.krate), ) }; format!( "{}[{}]{}", crate_name, - // Don't print the whole stable crate id. That's just + // Don't print the whole crate disambiguator. That's just // annoying in debug output. - &(format!("{:08x}", stable_crate_id.to_u64()))[..4], + &(crate_disambiguator.to_fingerprint().to_hex())[..4], self.def_path(def_id).to_string_no_crate_verbose() ) } diff --git a/compiler/rustc_middle/src/ty/query/mod.rs b/compiler/rustc_middle/src/ty/query/mod.rs index a5b540dcb70cd..297110ee3ecff 100644 --- a/compiler/rustc_middle/src/ty/query/mod.rs +++ b/compiler/rustc_middle/src/ty/query/mod.rs @@ -47,6 +47,7 @@ use rustc_index::{bit_set::FiniteBitSet, vec::IndexVec}; use rustc_serialize::opaque; use rustc_session::config::{EntryFnType, OptLevel, OutputFilenames, SymbolManglingVersion}; use rustc_session::utils::NativeLibKind; +use rustc_session::CrateDisambiguator; use rustc_target::spec::PanicStrategy; use rustc_ast as ast; diff --git a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs index e473559812fe6..ebb52d8863f37 100644 --- a/compiler/rustc_middle/src/ty/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/ty/query/on_disk_cache.rs @@ -18,7 +18,7 @@ use rustc_serialize::{ opaque::{self, FileEncodeResult, FileEncoder, IntEncodedWithFixedSize}, Decodable, Decoder, Encodable, Encoder, }; -use rustc_session::{Session, StableCrateId}; +use rustc_session::{CrateDisambiguator, Session}; use rustc_span::hygiene::{ ExpnDataDecodeMode, ExpnDataEncodeMode, ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData, @@ -52,7 +52,7 @@ pub struct OnDiskCache<'sess> { // session. current_diagnostics: Lock>>, - prev_cnums: Vec<(u32, StableCrateId)>, + prev_cnums: Vec<(u32, String, CrateDisambiguator)>, cnum_map: OnceCell>>, source_map: &'sess SourceMap, @@ -120,7 +120,7 @@ pub struct OnDiskCache<'sess> { #[derive(Encodable, Decodable)] struct Footer { file_index_to_stable_id: FxHashMap, - prev_cnums: Vec<(u32, StableCrateId)>, + prev_cnums: Vec<(u32, String, CrateDisambiguator)>, query_result_index: EncodedQueryResultIndex, diagnostics_index: EncodedQueryResultIndex, // The location of all allocations. @@ -349,8 +349,9 @@ impl<'sess> OnDiskCache<'sess> { let prev_cnums: Vec<_> = sorted_cnums .iter() .map(|&cnum| { - let stable_crate_id = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); - (cnum.as_u32(), stable_crate_id) + let crate_name = tcx.crate_name(cnum).to_string(); + let crate_disambiguator = tcx.crate_disambiguator(cnum); + (cnum.as_u32(), crate_name, crate_disambiguator) }) .collect(); @@ -574,23 +575,25 @@ impl<'sess> OnDiskCache<'sess> { // maps to None. fn compute_cnum_map( tcx: TyCtxt<'_>, - prev_cnums: &[(u32, StableCrateId)], + prev_cnums: &[(u32, String, CrateDisambiguator)], ) -> IndexVec> { tcx.dep_graph.with_ignore(|| { let current_cnums = tcx .all_crate_nums(()) .iter() .map(|&cnum| { - let stable_crate_id = tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); - (stable_crate_id, cnum) + let crate_name = tcx.crate_name(cnum).to_string(); + let crate_disambiguator = tcx.crate_disambiguator(cnum); + ((crate_name, crate_disambiguator), cnum) }) .collect::>(); let map_size = prev_cnums.iter().map(|&(cnum, ..)| cnum).max().unwrap_or(0) + 1; let mut map = IndexVec::from_elem_n(None, map_size as usize); - for &(prev_cnum, stable_crate_id) in prev_cnums { - map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&stable_crate_id).cloned(); + for &(prev_cnum, ref crate_name, crate_disambiguator) in prev_cnums { + let key = (crate_name.clone(), crate_disambiguator); + map[CrateNum::from_u32(prev_cnum)] = current_cnums.get(&key).cloned(); } map[LOCAL_CRATE] = Some(LOCAL_CRATE); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 41935e7d6dfd5..fd9b897111a98 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1222,7 +1222,7 @@ impl<'a> Resolver<'a> { let mut module_map = FxHashMap::default(); module_map.insert(root_local_def_id, graph_root); - let definitions = Definitions::new(session.local_stable_crate_id()); + let definitions = Definitions::new(crate_name, session.local_crate_disambiguator()); let root = definitions.get_root_def(); let mut visibilities = FxHashMap::default(); diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 842f7f9deee38..54b6a12158581 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -142,7 +142,12 @@ impl<'tcx> DumpVisitor<'tcx> { let data = CratePreludeData { crate_id: GlobalCrateId { name: name.into(), - disambiguator: (self.tcx.sess.local_stable_crate_id().to_u64(), 0), + disambiguator: self + .tcx + .sess + .local_crate_disambiguator() + .to_fingerprint() + .as_value(), }, crate_root: crate_root.unwrap_or_else(|| "".to_owned()), external_crates: self.save_ctxt.get_external_crates(), diff --git a/compiler/rustc_save_analysis/src/lib.rs b/compiler/rustc_save_analysis/src/lib.rs index 524c352fef515..297383bfed1fa 100644 --- a/compiler/rustc_save_analysis/src/lib.rs +++ b/compiler/rustc_save_analysis/src/lib.rs @@ -127,10 +127,7 @@ impl<'tcx> SaveContext<'tcx> { num: n.as_u32(), id: GlobalCrateId { name: self.tcx.crate_name(n).to_string(), - disambiguator: ( - self.tcx.def_path_hash(n.as_def_id()).stable_crate_id().to_u64(), - 0, - ), + disambiguator: self.tcx.crate_disambiguator(n).to_fingerprint().as_value(), }, }); } diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 47833dcda4f1f..86b8389a670e6 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -22,7 +22,7 @@ use rustc_errors::json::JsonEmitter; use rustc_errors::registry::Registry; use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticId, ErrorReported}; use rustc_lint_defs::FutureBreakage; -pub use rustc_span::def_id::StableCrateId; +pub use rustc_span::crate_disambiguator::CrateDisambiguator; use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span}; use rustc_span::{edition::Edition, RealFileName}; use rustc_span::{sym, SourceFileHashAlgorithm, Symbol}; @@ -133,12 +133,12 @@ pub struct Session { /// in order to avoid redundantly verbose output (Issue #24690, #44953). pub one_time_diagnostics: Lock, String)>>, crate_types: OnceCell>, - /// The `stable_crate_id` is constructed out of the crate name and all the - /// `-C metadata` arguments passed to the compiler. Its value forms a unique - /// global identifier for the crate. It is used to allow multiple crates - /// with the same name to coexist. See the + /// 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 /// `rustc_codegen_llvm::back::symbol_names` module for more information. - pub stable_crate_id: OnceCell, + pub crate_disambiguator: OnceCell, features: OnceCell, @@ -335,8 +335,8 @@ impl Session { self.parse_sess.span_diagnostic.emit_future_breakage_report(diags_and_breakage); } - pub fn local_stable_crate_id(&self) -> StableCrateId { - self.stable_crate_id.get().copied().unwrap() + pub fn local_crate_disambiguator(&self) -> CrateDisambiguator { + self.crate_disambiguator.get().copied().unwrap() } pub fn crate_types(&self) -> &[CrateType] { @@ -833,12 +833,12 @@ impl Session { /// Returns the symbol name for the registrar function, /// given the crate `Svh` and the function `DefIndex`. - pub fn generate_plugin_registrar_symbol(&self, stable_crate_id: StableCrateId) -> String { - format!("__rustc_plugin_registrar_{:08x}__", stable_crate_id.to_u64()) + pub fn generate_plugin_registrar_symbol(&self, disambiguator: CrateDisambiguator) -> String { + format!("__rustc_plugin_registrar_{}__", disambiguator.to_fingerprint().to_hex()) } - pub fn generate_proc_macro_decls_symbol(&self, stable_crate_id: StableCrateId) -> String { - format!("__rustc_proc_macro_decls_{:08x}__", stable_crate_id.to_u64()) + pub fn generate_proc_macro_decls_symbol(&self, disambiguator: CrateDisambiguator) -> String { + format!("__rustc_proc_macro_decls_{}__", disambiguator.to_fingerprint().to_hex()) } pub fn target_filesearch(&self, kind: PathKind) -> filesearch::FileSearch<'_> { @@ -1397,7 +1397,7 @@ pub fn build_session( working_dir, one_time_diagnostics: Default::default(), crate_types: OnceCell::new(), - stable_crate_id: OnceCell::new(), + crate_disambiguator: OnceCell::new(), features: OnceCell::new(), lint_store: OnceCell::new(), recursion_limit: OnceCell::new(), diff --git a/compiler/rustc_span/src/crate_disambiguator.rs b/compiler/rustc_span/src/crate_disambiguator.rs new file mode 100644 index 0000000000000..bd7d85167140d --- /dev/null +++ b/compiler/rustc_span/src/crate_disambiguator.rs @@ -0,0 +1,35 @@ +// This is here because `rustc_session` wants to refer to it, +// and so does `rustc_hir`, but `rustc_hir` shouldn't refer to `rustc_session`. + +use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::{base_n, impl_stable_hash_via_hash}; + +use std::fmt; + +/// Hash value constructed out of all the `-C metadata` arguments passed to the +/// compiler. Together with the crate-name forms a unique global identifier for +/// the crate. +#[derive(Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Clone, Copy, Encodable, Decodable)] +pub struct CrateDisambiguator(Fingerprint); + +impl CrateDisambiguator { + pub fn to_fingerprint(self) -> Fingerprint { + self.0 + } +} + +impl fmt::Display for CrateDisambiguator { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + let (a, b) = self.0.as_value(); + let as_u128 = a as u128 | ((b as u128) << 64); + f.write_str(&base_n::encode(as_u128, base_n::CASE_INSENSITIVE)) + } +} + +impl From for CrateDisambiguator { + fn from(fingerprint: Fingerprint) -> CrateDisambiguator { + CrateDisambiguator(fingerprint) + } +} + +impl_stable_hash_via_hash!(CrateDisambiguator); diff --git a/compiler/rustc_span/src/def_id.rs b/compiler/rustc_span/src/def_id.rs index b04a10d22a02f..228d09b30d9b5 100644 --- a/compiler/rustc_span/src/def_id.rs +++ b/compiler/rustc_span/src/def_id.rs @@ -1,3 +1,4 @@ +use crate::crate_disambiguator::CrateDisambiguator; use crate::HashStableContext; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; @@ -126,51 +127,26 @@ impl Borrow for DefPathHash { } } -/// A [StableCrateId] is a 64 bit hash of the crate name combined with all -/// `-Cmetadata` arguments. It is to [CrateNum] what [DefPathHash] is to -/// [DefId]. It is stable across compilation sessions. +/// A [StableCrateId] is a 64 bit hash of `(crate-name, crate-disambiguator)`. It +/// is to [CrateNum] what [DefPathHash] is to [DefId]. It is stable across +/// compilation sessions. /// /// Since the ID is a hash value there is a (very small) chance that two crates /// end up with the same [StableCrateId]. The compiler will check for such /// collisions when loading crates and abort compilation in order to avoid /// further trouble. -#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug)] -#[derive(HashStable_Generic, Encodable, Decodable)] +#[derive(Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord, Debug, Encodable, Decodable)] pub struct StableCrateId(u64); impl StableCrateId { - pub fn to_u64(self) -> u64 { - self.0 - } - /// Computes the stable ID for a crate with the given name and - /// `-Cmetadata` arguments. - pub fn new(crate_name: &str, is_exe: bool, mut metadata: Vec) -> StableCrateId { + /// disambiguator. + pub fn new(crate_name: &str, crate_disambiguator: CrateDisambiguator) -> StableCrateId { use std::hash::Hash; - use std::hash::Hasher; let mut hasher = StableHasher::new(); crate_name.hash(&mut hasher); - - // We don't want the stable crate id 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.write(b"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.write_usize(s.len()); - hasher.write(s.as_bytes()); - } - - // Also incorporate crate type, so that we don't get symbol conflicts when - // linking against a library of the same name, if this is an executable. - hasher.write(if is_exe { b"exe" } else { b"lib" }); - + crate_disambiguator.hash(&mut hasher); StableCrateId(hasher.finish()) } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 51a53918f0792..de132616b0d67 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -45,6 +45,8 @@ pub mod lev_distance; mod span_encoding; pub use span_encoding::{Span, DUMMY_SP}; +pub mod crate_disambiguator; + pub mod symbol; pub use symbol::{sym, Symbol}; diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 0c64fe6ea60a9..025eaffcbd328 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -126,9 +126,8 @@ fn get_symbol_hash<'tcx>( substs.hash_stable(&mut hcx, &mut hasher); if let Some(instantiating_crate) = instantiating_crate { - tcx.def_path_hash(instantiating_crate.as_def_id()) - .stable_crate_id() - .hash_stable(&mut hcx, &mut hasher); + tcx.crate_name(instantiating_crate).as_str().hash_stable(&mut hcx, &mut hasher); + tcx.crate_disambiguator(instantiating_crate).hash_stable(&mut hcx, &mut hasher); } // We want to avoid accidental collision between different types of instances. diff --git a/compiler/rustc_symbol_mangling/src/lib.rs b/compiler/rustc_symbol_mangling/src/lib.rs index ba59ff96f6554..f716ce1efce86 100644 --- a/compiler/rustc_symbol_mangling/src/lib.rs +++ b/compiler/rustc_symbol_mangling/src/lib.rs @@ -165,12 +165,12 @@ fn compute_symbol_name( // FIXME(eddyb) Precompute a custom symbol name based on attributes. let is_foreign = if let Some(def_id) = def_id.as_local() { if tcx.plugin_registrar_fn(()) == Some(def_id) { - let stable_crate_id = tcx.sess.local_stable_crate_id(); - return tcx.sess.generate_plugin_registrar_symbol(stable_crate_id); + let disambiguator = tcx.sess.local_crate_disambiguator(); + return tcx.sess.generate_plugin_registrar_symbol(disambiguator); } if tcx.proc_macro_decls_static(()) == Some(def_id) { - let stable_crate_id = tcx.sess.local_stable_crate_id(); - return tcx.sess.generate_proc_macro_decls_symbol(stable_crate_id); + let disambiguator = tcx.sess.local_crate_disambiguator(); + return tcx.sess.generate_proc_macro_decls_symbol(disambiguator); } let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); matches!(tcx.hir().get(hir_id), Node::ForeignItem(_)) diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e7da56ed0f3c7..828f1ac0a7989 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -592,8 +592,8 @@ impl Printer<'tcx> for SymbolMangler<'tcx> { fn path_crate(mut self, cnum: CrateNum) -> Result { self.push("C"); - let stable_crate_id = self.tcx.def_path_hash(cnum.as_def_id()).stable_crate_id(); - self.push_disambiguator(stable_crate_id.to_u64()); + let fingerprint = self.tcx.crate_disambiguator(cnum).to_fingerprint(); + self.push_disambiguator(fingerprint.to_smaller_hash()); let name = self.tcx.crate_name(cnum).as_str(); self.push_ident(&name); Ok(self) diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs index 07a3132568b8d..ebc7b0d0d99cf 100644 --- a/compiler/rustc_ty_utils/src/ty.rs +++ b/compiler/rustc_ty_utils/src/ty.rs @@ -1,11 +1,12 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE}; use rustc_middle::hir::map as hir_map; use rustc_middle::ty::subst::Subst; use rustc_middle::ty::{ self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness, }; +use rustc_session::CrateDisambiguator; use rustc_span::Span; use rustc_trait_selection::traits; @@ -387,6 +388,11 @@ fn param_env_reveal_all_normalized(tcx: TyCtxt<'_>, def_id: DefId) -> ty::ParamE tcx.param_env(def_id).with_reveal_all_normalized(tcx) } +fn crate_disambiguator(tcx: TyCtxt<'_>, crate_num: CrateNum) -> CrateDisambiguator { + assert_eq!(crate_num, LOCAL_CRATE); + tcx.sess.local_crate_disambiguator() +} + fn instance_def_size_estimate<'tcx>( tcx: TyCtxt<'tcx>, instance_def: ty::InstanceDef<'tcx>, @@ -532,6 +538,7 @@ pub fn provide(providers: &mut ty::query::Providers) { param_env, param_env_reveal_all_normalized, trait_of_item, + crate_disambiguator, instance_def_size_estimate, issue33140_self_ty, impl_defaultness,