summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_metadata/src/creader.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_metadata/src/creader.rs')
-rw-r--r--compiler/rustc_metadata/src/creader.rs131
1 files changed, 49 insertions, 82 deletions
diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs
index b05626311..23aceca06 100644
--- a/compiler/rustc_metadata/src/creader.rs
+++ b/compiler/rustc_metadata/src/creader.rs
@@ -6,11 +6,11 @@ use crate::rmeta::{CrateDep, CrateMetadata, CrateNumMap, CrateRoot, MetadataBlob
use rustc_ast::expand::allocator::AllocatorKind;
use rustc_ast::{self as ast, *};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::svh::Svh;
-use rustc_data_structures::sync::MappedReadGuard;
+use rustc_data_structures::sync::{MappedReadGuard, MappedWriteGuard, ReadGuard, WriteGuard};
use rustc_expand::base::SyntaxExtension;
-use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, LOCAL_CRATE};
+use rustc_hir::def_id::{CrateNum, LocalDefId, StableCrateId, StableCrateIdMap, LOCAL_CRATE};
use rustc_hir::definitions::Definitions;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::TyCtxt;
@@ -46,9 +46,8 @@ pub struct CStore {
/// This crate has a `#[alloc_error_handler]` item.
has_alloc_error_handler: bool,
- /// This map is used to verify we get no hash conflicts between
- /// `StableCrateId` values.
- pub(crate) stable_crate_ids: FxHashMap<StableCrateId, CrateNum>,
+ /// The interned [StableCrateId]s.
+ pub(crate) stable_crate_ids: StableCrateIdMap,
/// Unused externs of the crate
unused_externs: Vec<Symbol>,
@@ -133,14 +132,32 @@ impl<'a> std::fmt::Debug for CrateDump<'a> {
impl CStore {
pub fn from_tcx(tcx: TyCtxt<'_>) -> MappedReadGuard<'_, CStore> {
- MappedReadGuard::map(tcx.cstore_untracked(), |c| {
- c.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
+ ReadGuard::map(tcx.untracked().cstore.read(), |cstore| {
+ cstore.as_any().downcast_ref::<CStore>().expect("`tcx.cstore` is not a `CStore`")
})
}
- fn alloc_new_crate_num(&mut self) -> CrateNum {
- self.metas.push(None);
- CrateNum::new(self.metas.len() - 1)
+ pub fn from_tcx_mut(tcx: TyCtxt<'_>) -> MappedWriteGuard<'_, CStore> {
+ WriteGuard::map(tcx.untracked().cstore.write(), |cstore| {
+ cstore.untracked_as_any().downcast_mut().expect("`tcx.cstore` is not a `CStore`")
+ })
+ }
+
+ fn intern_stable_crate_id(&mut self, root: &CrateRoot) -> Result<CrateNum, CrateError> {
+ assert_eq!(self.metas.len(), self.stable_crate_ids.len());
+ let num = CrateNum::new(self.stable_crate_ids.len());
+ if let Some(&existing) = self.stable_crate_ids.get(&root.stable_crate_id()) {
+ let crate_name0 = root.name();
+ if let Some(crate_name1) = self.metas[existing].as_ref().map(|data| data.name()) {
+ Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1))
+ } else {
+ Err(CrateError::SymbolConflictsCurrent(crate_name0))
+ }
+ } else {
+ self.metas.push(None);
+ self.stable_crate_ids.insert(root.stable_crate_id(), num);
+ Ok(num)
+ }
}
pub fn has_crate_data(&self, cnum: CrateNum) -> bool {
@@ -168,7 +185,7 @@ impl CStore {
fn push_dependencies_in_postorder(&self, deps: &mut Vec<CrateNum>, cnum: CrateNum) {
if !deps.contains(&cnum) {
let data = self.get_crate_data(cnum);
- for &dep in data.dependencies().iter() {
+ for dep in data.dependencies() {
if dep != cnum {
self.push_dependencies_in_postorder(deps, dep);
}
@@ -241,7 +258,7 @@ impl CStore {
}
pub fn new(sess: &Session) -> CStore {
- let mut stable_crate_ids = FxHashMap::default();
+ let mut stable_crate_ids = StableCrateIdMap::default();
stable_crate_ids.insert(sess.local_stable_crate_id(), LOCAL_CRATE);
CStore {
// We add an empty entry for LOCAL_CRATE (which maps to zero) in
@@ -268,9 +285,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
) -> Self {
CrateLoader { tcx, cstore, used_extern_options }
}
- pub fn cstore(&self) -> &CStore {
- &self.cstore
- }
fn existing_match(&self, name: Symbol, hash: Option<Svh>, kind: PathKind) -> Option<CrateNum> {
for (cnum, data) in self.cstore.iter_crate_data() {
@@ -339,42 +353,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
None
}
- 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() {
- return Err(CrateError::SymbolConflictsCurrent(root.name()));
- }
-
- // Check for conflicts with any crate loaded so far
- for (_, other) in self.cstore.iter_crate_data() {
- // Same stable crate id but different SVH
- if other.stable_crate_id() == root.stable_crate_id() && other.hash() != root.hash() {
- bug!(
- "Previously returned E0523 here. \
- See https://github.com/rust-lang/rust/pull/100599 for additional discussion.\
- root.name() = {}.",
- root.name()
- );
- }
- }
-
- Ok(())
- }
-
- fn verify_no_stable_crate_id_hash_conflicts(
- &mut self,
- root: &CrateRoot,
- cnum: CrateNum,
- ) -> Result<(), CrateError> {
- if let Some(existing) = self.cstore.stable_crate_ids.insert(root.stable_crate_id(), cnum) {
- let crate_name0 = root.name();
- let crate_name1 = self.cstore.get_crate_data(existing).name();
- return Err(CrateError::StableCrateIdCollision(crate_name0, crate_name1));
- }
-
- Ok(())
- }
-
fn register_crate(
&mut self,
host_lib: Option<Library>,
@@ -393,7 +371,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
self.sess.opts.externs.get(name.as_str()).map_or(false, |e| e.is_private_dep);
// Claim this crate number and cache it
- let cnum = self.cstore.alloc_new_crate_num();
+ let cnum = self.cstore.intern_stable_crate_id(&crate_root)?;
info!(
"register crate `{}` (cnum = {}. private_dep = {})",
@@ -429,14 +407,6 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
None
};
- // Perform some verification *after* resolve_crate_deps() above is
- // known to have been successful. It seems that - in error cases - the
- // cstore can be in a temporarily invalid state between cnum allocation
- // and dependency resolution and the verification code would produce
- // ICEs in that case (see #83045).
- self.verify_no_symbol_conflicts(&crate_root)?;
- self.verify_no_stable_crate_id_hash_conflicts(&crate_root, cnum)?;
-
let crate_metadata = CrateMetadata::new(
self.sess,
&self.cstore,
@@ -635,7 +605,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
if cmeta.update_extern_crate(extern_crate) {
// Propagate the extern crate info to dependencies if it was updated.
let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate };
- for &dep_cnum in cmeta.dependencies().iter() {
+ for dep_cnum in cmeta.dependencies() {
self.update_extern_crate(dep_cnum, extern_crate);
}
}
@@ -717,8 +687,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// compilation mode also comes into play.
let desired_strategy = self.sess.panic_strategy();
let mut runtime_found = false;
- let mut needs_panic_runtime =
- self.sess.contains_name(&krate.attrs, sym::needs_panic_runtime);
+ let mut needs_panic_runtime = attr::contains_name(&krate.attrs, sym::needs_panic_runtime);
for (cnum, data) in self.cstore.iter_crate_data() {
needs_panic_runtime = needs_panic_runtime || data.needs_panic_runtime();
@@ -786,7 +755,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
info!("loading profiler");
let name = Symbol::intern(&self.sess.opts.unstable_opts.profiler_runtime);
- if name == sym::profiler_builtins && self.sess.contains_name(&krate.attrs, sym::no_core) {
+ if name == sym::profiler_builtins && attr::contains_name(&krate.attrs, sym::no_core) {
self.sess.emit_err(errors::ProfilerBuiltinsNeedsCore);
}
@@ -800,14 +769,14 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
fn inject_allocator_crate(&mut self, krate: &ast::Crate) {
- self.cstore.has_global_allocator = match &*global_allocator_spans(&self.sess, krate) {
+ self.cstore.has_global_allocator = match &*global_allocator_spans(krate) {
[span1, span2, ..] => {
self.sess.emit_err(errors::NoMultipleGlobalAlloc { span2: *span2, span1: *span1 });
true
}
spans => !spans.is_empty(),
};
- self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(&self.sess, krate) {
+ self.cstore.has_alloc_error_handler = match &*alloc_error_handler_spans(krate) {
[span1, span2, ..] => {
self.sess
.emit_err(errors::NoMultipleAllocErrorHandler { span2: *span2, span1: *span1 });
@@ -819,7 +788,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// Check to see if we actually need an allocator. This desire comes
// about through the `#![needs_allocator]` attribute and is typically
// written down in liballoc.
- if !self.sess.contains_name(&krate.attrs, sym::needs_allocator)
+ if !attr::contains_name(&krate.attrs, sym::needs_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.needs_allocator())
{
return;
@@ -878,7 +847,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// allocator. At this point our allocator request is typically fulfilled
// by the standard library, denoted by the `#![default_lib_allocator]`
// attribute.
- if !self.sess.contains_name(&krate.attrs, sym::default_lib_allocator)
+ if !attr::contains_name(&krate.attrs, sym::default_lib_allocator)
&& !self.cstore.iter_crate_data().any(|(_, data)| data.has_default_lib_allocator())
{
self.sess.emit_err(errors::GlobalAllocRequired);
@@ -1000,7 +969,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
None => item.ident.name,
};
- let dep_kind = if self.sess.contains_name(&item.attrs, sym::no_link) {
+ let dep_kind = if attr::contains_name(&item.attrs, sym::no_link) {
CrateDepKind::MacrosOnly
} else {
CrateDepKind::Explicit
@@ -1046,16 +1015,15 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
}
-fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
- struct Finder<'a> {
- sess: &'a Session,
+fn global_allocator_spans(krate: &ast::Crate) -> Vec<Span> {
+ struct Finder {
name: Symbol,
spans: Vec<Span>,
}
- impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> {
+ impl<'ast> visit::Visitor<'ast> for Finder {
fn visit_item(&mut self, item: &'ast ast::Item) {
if item.ident.name == self.name
- && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol)
+ && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
{
self.spans.push(item.span);
}
@@ -1064,21 +1032,20 @@ fn global_allocator_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
}
let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::alloc));
- let mut f = Finder { sess, name, spans: Vec::new() };
+ let mut f = Finder { name, spans: Vec::new() };
visit::walk_crate(&mut f, krate);
f.spans
}
-fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
- struct Finder<'a> {
- sess: &'a Session,
+fn alloc_error_handler_spans(krate: &ast::Crate) -> Vec<Span> {
+ struct Finder {
name: Symbol,
spans: Vec<Span>,
}
- impl<'ast, 'a> visit::Visitor<'ast> for Finder<'a> {
+ impl<'ast> visit::Visitor<'ast> for Finder {
fn visit_item(&mut self, item: &'ast ast::Item) {
if item.ident.name == self.name
- && self.sess.contains_name(&item.attrs, sym::rustc_std_internal_symbol)
+ && attr::contains_name(&item.attrs, sym::rustc_std_internal_symbol)
{
self.spans.push(item.span);
}
@@ -1087,7 +1054,7 @@ fn alloc_error_handler_spans(sess: &Session, krate: &ast::Crate) -> Vec<Span> {
}
let name = Symbol::intern(&AllocatorKind::Global.fn_name(sym::oom));
- let mut f = Finder { sess, name, spans: Vec::new() };
+ let mut f = Finder { name, spans: Vec::new() };
visit::walk_crate(&mut f, krate);
f.spans
}