diff --git a/Cargo.lock b/Cargo.lock index c7bd689b2d864..07dcca0fd47b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1418,9 +1418,9 @@ dependencies = [ [[package]] name = "elsa" -version = "1.8.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f74077c3c3aedb99a2683919698285596662518ea13e5eedcf8bdd43b0d0453b" +checksum = "848fe615fbb0a74d9ae68dcaa510106d32e37d9416207bbea4bd008bd89c47ed" dependencies = [ "stable_deref_trait", ] diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml index 0b2b03da2080a..24b6b5cfb1f73 100644 --- a/compiler/rustc_data_structures/Cargo.toml +++ b/compiler/rustc_data_structures/Cargo.toml @@ -32,7 +32,7 @@ stacker = "0.1.15" tempfile = "3.2" thin-vec = "0.2.12" tracing = "0.1" -elsa = "1.8" +elsa = "=1.7.1" [dependencies.parking_lot] version = "0.11" diff --git a/compiler/rustc_data_structures/src/sync.rs b/compiler/rustc_data_structures/src/sync.rs index 4e2126fff7be9..e8ee4fb76cc51 100644 --- a/compiler/rustc_data_structures/src/sync.rs +++ b/compiler/rustc_data_structures/src/sync.rs @@ -51,7 +51,7 @@ use std::panic::{catch_unwind, resume_unwind, AssertUnwindSafe}; pub use std::sync::atomic::Ordering; pub use std::sync::atomic::Ordering::SeqCst; -pub use vec::AppendOnlyVec; +pub use vec::{AppendOnlyIndexVec, AppendOnlyVec}; mod vec; @@ -107,6 +107,14 @@ cfg_if! { } } + impl Atomic { + pub fn fetch_or(&self, val: bool, _: Ordering) -> bool { + let result = self.0.get() | val; + self.0.set(val); + result + } + } + impl Atomic { #[inline] pub fn compare_exchange(&self, @@ -481,14 +489,6 @@ impl Default for Lock { } } -// FIXME: Probably a bad idea -impl Clone for Lock { - #[inline] - fn clone(&self) -> Self { - Lock::new(self.borrow().clone()) - } -} - #[derive(Debug, Default)] pub struct RwLock(InnerRwLock); diff --git a/compiler/rustc_data_structures/src/sync/vec.rs b/compiler/rustc_data_structures/src/sync/vec.rs index cbea4f0599922..aefaa8519d536 100644 --- a/compiler/rustc_data_structures/src/sync/vec.rs +++ b/compiler/rustc_data_structures/src/sync/vec.rs @@ -2,7 +2,8 @@ use std::marker::PhantomData; use rustc_index::vec::Idx; -pub struct AppendOnlyVec { +#[derive(Default)] +pub struct AppendOnlyIndexVec { #[cfg(not(parallel_compiler))] vec: elsa::vec::FrozenVec, #[cfg(parallel_compiler)] @@ -10,7 +11,7 @@ pub struct AppendOnlyVec { _marker: PhantomData, } -impl AppendOnlyVec { +impl AppendOnlyIndexVec { pub fn new() -> Self { Self { #[cfg(not(parallel_compiler))] @@ -39,3 +40,66 @@ impl AppendOnlyVec { return self.vec.get(i); } } + +#[derive(Default)] +pub struct AppendOnlyVec { + #[cfg(not(parallel_compiler))] + vec: elsa::vec::FrozenVec, + #[cfg(parallel_compiler)] + vec: elsa::sync::LockFreeFrozenVec, +} + +impl AppendOnlyVec { + pub fn new() -> Self { + Self { + #[cfg(not(parallel_compiler))] + vec: elsa::vec::FrozenVec::new(), + #[cfg(parallel_compiler)] + vec: elsa::sync::LockFreeFrozenVec::new(), + } + } + + pub fn push(&self, val: T) -> usize { + #[cfg(not(parallel_compiler))] + let i = self.vec.len(); + #[cfg(not(parallel_compiler))] + self.vec.push(val); + #[cfg(parallel_compiler)] + let i = self.vec.push(val); + i + } + + pub fn get(&self, i: usize) -> Option { + #[cfg(not(parallel_compiler))] + return self.vec.get_copy(i); + #[cfg(parallel_compiler)] + return self.vec.get(i); + } + + pub fn iter_enumerated(&self) -> impl Iterator + '_ { + (0..) + .map(|i| (i, self.get(i))) + .take_while(|(_, o)| o.is_some()) + .filter_map(|(i, o)| Some((i, o?))) + } + + pub fn iter(&self) -> impl Iterator + '_ { + (0..).map(|i| self.get(i)).take_while(|o| o.is_some()).filter_map(|o| o) + } +} + +impl AppendOnlyVec { + pub fn contains(&self, val: T) -> bool { + self.iter_enumerated().any(|(_, v)| v == val) + } +} + +impl FromIterator for AppendOnlyVec { + fn from_iter>(iter: T) -> Self { + let this = Self::new(); + for val in iter { + this.push(val); + } + this + } +} diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index d2293780836d5..818f450a58c16 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -7,7 +7,7 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{AppendOnlyVec, Lrc, OnceCell, RwLock, WorkerLocal}; +use rustc_data_structures::sync::{AppendOnlyIndexVec, Lrc, OnceCell, RwLock, WorkerLocal}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::DepGraphFuture; @@ -215,7 +215,7 @@ impl<'tcx> Queries<'tcx> { let cstore = RwLock::new(Box::new(CStore::new(sess)) as _); let definitions = RwLock::new(Definitions::new(sess.local_stable_crate_id())); - let source_span = AppendOnlyVec::new(); + let source_span = AppendOnlyIndexVec::new(); let _id = source_span.push(krate.spans.inner_span); debug_assert_eq!(_id, CRATE_DEF_ID); let untracked = Untracked { cstore, source_span, definitions }; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index c1b247e3d615a..6b387df785e7d 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1947,7 +1947,7 @@ impl KeywordIdents { }; // Don't lint `r#foo`. - if cx.sess().parse_sess.raw_identifier_spans.borrow().contains(&ident.span) { + if cx.sess().parse_sess.raw_identifier_spans.contains(ident.span) { return; } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index 23c1aebb8ae38..23aceca06223a 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -185,7 +185,7 @@ impl CStore { fn push_dependencies_in_postorder(&self, deps: &mut Vec, 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); } @@ -605,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); } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 43e5946f31354..21ac7e201f9a3 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -7,7 +7,7 @@ use rustc_ast as ast; use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; -use rustc_data_structures::sync::{Lock, LockGuard, Lrc, OnceCell}; +use rustc_data_structures::sync::{AppendOnlyVec, Lock, Lrc, OnceCell}; use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; @@ -109,7 +109,7 @@ pub(crate) struct CrateMetadata { /// IDs as they are seen from the current compilation session. cnum_map: CrateNumMap, /// Same ID set as `cnum_map` plus maybe some injected crates like panic runtime. - dependencies: Lock>, + dependencies: AppendOnlyVec, /// How to link (or not link) this crate to the currently compiled crate. dep_kind: Lock, /// Filesystem location of this crate. @@ -1594,7 +1594,7 @@ impl CrateMetadata { .collect(); let alloc_decoding_state = AllocDecodingState::new(root.interpret_alloc_index.decode(&blob).collect()); - let dependencies = Lock::new(cnum_map.iter().cloned().collect()); + let dependencies = cnum_map.iter().copied().collect(); // Pre-decode the DefPathHash->DefIndex table. This is a cheap operation // that does not copy any data. It just does some data verification. @@ -1634,12 +1634,12 @@ impl CrateMetadata { cdata } - pub(crate) fn dependencies(&self) -> LockGuard<'_, Vec> { - self.dependencies.borrow() + pub(crate) fn dependencies(&self) -> impl Iterator + '_ { + self.dependencies.iter() } pub(crate) fn add_dependency(&self, cnum: CrateNum) { - self.dependencies.borrow_mut().push(cnum); + self.dependencies.push(cnum); } pub(crate) fn update_extern_crate(&self, new_extern_crate: ExternCrate) -> bool { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2652a4280d373..0e8155afcb4db 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1712,8 +1712,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let stability = tcx.lookup_stability(CRATE_DEF_ID); let macros = self.lazy_array(tcx.resolutions(()).proc_macros.iter().map(|p| p.local_def_index)); - let spans = self.tcx.sess.parse_sess.proc_macro_quoted_spans(); - for (i, span) in spans.into_iter().enumerate() { + for (i, span) in self.tcx.sess.parse_sess.proc_macro_quoted_spans() { let span = self.lazy(span); self.tables.proc_macro_quoted_spans.set_some(i, span); } diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 1766d7a669804..1f8b650e34cfc 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -263,7 +263,8 @@ impl AllocDecodingState { } pub fn new(data_offsets: Vec) -> Self { - let decoding_state = vec![Lock::new(State::Empty); data_offsets.len()]; + let decoding_state = + std::iter::repeat_with(|| Lock::new(State::Empty)).take(data_offsets.len()).collect(); Self { decoding_state, data_offsets } } diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 9dbddee5a56f0..4a7da11a09784 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -175,7 +175,7 @@ impl<'a> StringReader<'a> { if !sym.can_be_raw() { self.sess.emit_err(errors::CannotBeRawIdent { span, ident: sym }); } - self.sess.raw_identifier_spans.borrow_mut().push(span); + self.sess.raw_identifier_spans.push(span); token::Ident(sym, true) } rustc_lexer::TokenKind::UnknownPrefix => { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 53c25a80c4bf3..aa57b804779b0 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -29,6 +29,7 @@ use rustc_ast::{Async, AttrArgs, AttrArgsEq, Expr, ExprKind, MacDelimiter, Mutab use rustc_ast::{HasAttrs, HasTokens, Unsafe, Visibility, VisibilityKind}; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sync::Ordering; use rustc_errors::PResult; use rustc_errors::{ Applicability, DiagnosticBuilder, ErrorGuaranteed, FatalError, IntoDiagnostic, MultiSpan, @@ -1540,8 +1541,10 @@ pub(crate) fn make_unclosed_delims_error( } pub fn emit_unclosed_delims(unclosed_delims: &mut Vec, sess: &ParseSess) { - *sess.reached_eof.borrow_mut() |= - unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()); + let _ = sess.reached_eof.fetch_or( + unclosed_delims.iter().any(|unmatched_delim| unmatched_delim.found_delim.is_none()), + Ordering::Relaxed, + ); for unmatched in unclosed_delims.drain(..) { if let Some(mut e) = make_unclosed_delims_error(unmatched, sess) { e.emit(); diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 8c3dff23b272d..e3e4b73efa324 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -187,7 +187,7 @@ fn sigpipe(tcx: TyCtxt<'_>, def_id: DefId) -> u8 { fn no_main_err(tcx: TyCtxt<'_>, visitor: &EntryContext<'_>) { let sp = tcx.def_span(CRATE_DEF_ID); - if *tcx.sess.parse_sess.reached_eof.borrow() { + if tcx.sess.parse_sess.reached_eof.load(rustc_data_structures::sync::Ordering::Relaxed) { // There's an unclosed brace that made the parser reach `Eof`, we shouldn't complain about // the missing `fn main()` then as it might have been hidden inside an unclosed block. tcx.sess.delay_span_bug(sp, "`main` not found, but expected unclosed brace error"); diff --git a/compiler/rustc_query_system/src/cache.rs b/compiler/rustc_query_system/src/cache.rs index 7cc885be2ba6a..6e862db0b2547 100644 --- a/compiler/rustc_query_system/src/cache.rs +++ b/compiler/rustc_query_system/src/cache.rs @@ -7,11 +7,16 @@ use rustc_data_structures::sync::Lock; use std::hash::Hash; -#[derive(Clone)] pub struct Cache { hashmap: Lock>>, } +impl Clone for Cache { + fn clone(&self) -> Self { + Self { hashmap: Lock::new(self.hashmap.borrow().clone()) } + } +} + impl Default for Cache { fn default() -> Self { Self { hashmap: Default::default() } diff --git a/compiler/rustc_session/src/cstore.rs b/compiler/rustc_session/src/cstore.rs index a262c06d91f03..dd1721801f37f 100644 --- a/compiler/rustc_session/src/cstore.rs +++ b/compiler/rustc_session/src/cstore.rs @@ -6,7 +6,7 @@ use crate::search_paths::PathKind; use crate::utils::NativeLibKind; use crate::Session; use rustc_ast as ast; -use rustc_data_structures::sync::{self, AppendOnlyVec, MetadataRef, RwLock}; +use rustc_data_structures::sync::{self, AppendOnlyIndexVec, MetadataRef, RwLock}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash, Definitions}; use rustc_span::hygiene::{ExpnHash, ExpnId}; @@ -257,6 +257,6 @@ pub type CrateStoreDyn = dyn CrateStore + sync::Sync + sync::Send; pub struct Untracked { pub cstore: RwLock>, /// Reference span for definitions. - pub source_span: AppendOnlyVec, + pub source_span: AppendOnlyIndexVec, pub definitions: RwLock, } diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 4e8c3f73e29cd..002ae1e3165ac 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -8,7 +8,7 @@ use crate::lint::{ }; use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; -use rustc_data_structures::sync::{Lock, Lrc}; +use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc}; use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler}; use rustc_errors::{ fallback_fluent_bundle, Diagnostic, DiagnosticBuilder, DiagnosticId, DiagnosticMessage, @@ -194,7 +194,7 @@ pub struct ParseSess { pub edition: Edition, /// Places where raw identifiers were used. This is used to avoid complaining about idents /// clashing with keywords in new editions. - pub raw_identifier_spans: Lock>, + pub raw_identifier_spans: AppendOnlyVec, /// Places where identifiers that contain invalid Unicode codepoints but that look like they /// should be. Useful to avoid bad tokenization when encountering emoji. We group them to /// provide a single error per unique incorrect identifier. @@ -208,7 +208,7 @@ pub struct ParseSess { pub gated_spans: GatedSpans, pub symbol_gallery: SymbolGallery, /// The parser has reached `Eof` due to an unclosed brace. Used to silence unnecessary errors. - pub reached_eof: Lock, + pub reached_eof: AtomicBool, /// Environment variables accessed during the build and their values when they exist. pub env_depinfo: Lock)>>, /// File paths accessed during the build. @@ -219,7 +219,7 @@ pub struct ParseSess { pub assume_incomplete_release: bool, /// Spans passed to `proc_macro::quote_span`. Each span has a numerical /// identifier represented by its position in the vector. - pub proc_macro_quoted_spans: Lock>, + pub proc_macro_quoted_spans: AppendOnlyVec, /// Used to generate new `AttrId`s. Every `AttrId` is unique. pub attr_id_generator: AttrIdGenerator, } @@ -247,14 +247,14 @@ impl ParseSess { config: FxIndexSet::default(), check_config: CrateCheckConfig::default(), edition: ExpnId::root().expn_data().edition, - raw_identifier_spans: Lock::new(Vec::new()), + raw_identifier_spans: Default::default(), bad_unicode_identifiers: Lock::new(Default::default()), source_map, buffered_lints: Lock::new(vec![]), ambiguous_block_expr_parse: Lock::new(FxHashMap::default()), gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), - reached_eof: Lock::new(false), + reached_eof: AtomicBool::new(false), env_depinfo: Default::default(), file_depinfo: Default::default(), type_ascription_path_suggestions: Default::default(), @@ -324,13 +324,13 @@ impl ParseSess { } pub fn save_proc_macro_span(&self, span: Span) -> usize { - let mut spans = self.proc_macro_quoted_spans.lock(); - spans.push(span); - return spans.len() - 1; + self.proc_macro_quoted_spans.push(span) } - pub fn proc_macro_quoted_spans(&self) -> Vec { - self.proc_macro_quoted_spans.lock().clone() + pub fn proc_macro_quoted_spans(&self) -> impl Iterator + '_ { + // This is equivalent to `.iter().copied().enumerate()`, but that isn't possible for + // AppendOnlyVec, so we resort to this scheme. + self.proc_macro_quoted_spans.iter_enumerated() } #[track_caller] diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index e14760aa01885..11cd5811be8b9 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -1318,7 +1318,6 @@ pub struct SourceFileDiffs { } /// A single source in the [`SourceMap`]. -#[derive(Clone)] pub struct SourceFile { /// The name of the file that the source came from. Source that doesn't /// originate from files has names between angle brackets by convention @@ -1349,6 +1348,25 @@ pub struct SourceFile { pub cnum: CrateNum, } +impl Clone for SourceFile { + fn clone(&self) -> Self { + Self { + name: self.name.clone(), + src: self.src.clone(), + src_hash: self.src_hash.clone(), + external_src: Lock::new(self.external_src.borrow().clone()), + start_pos: self.start_pos.clone(), + end_pos: self.end_pos.clone(), + lines: Lock::new(self.lines.borrow().clone()), + multibyte_chars: self.multibyte_chars.clone(), + non_narrow_chars: self.non_narrow_chars.clone(), + normalized_pos: self.normalized_pos.clone(), + name_hash: self.name_hash.clone(), + cnum: self.cnum.clone(), + } + } +} + impl Encodable for SourceFile { fn encode(&self, s: &mut S) { self.name.encode(s);