diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index b1ab4eaa06924..f17ab264bffbb 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -62,7 +62,7 @@ cfg_if! { pub use std::cell::RefMut as WriteGuard; pub use std::cell::RefMut as LockGuard; - pub use std::cell::RefCell as RwLock; + use std::cell::RefCell as InnerRwLock; use std::cell::RefCell as InnerLock; use std::cell::Cell; @@ -159,13 +159,12 @@ cfg_if! { pub use parking_lot::MutexGuard as LockGuard; - use parking_lot; - pub use std::sync::Arc as Lrc; pub use self::Lock as MTLock; use parking_lot::Mutex as InnerLock; + use parking_lot::RwLock as InnerRwLock; pub type MetadataRef = OwningRef, [u8]>; @@ -222,42 +221,6 @@ cfg_if! { self.0.lock().take() } } - - #[derive(Debug)] - pub struct RwLock(parking_lot::RwLock); - - impl RwLock { - #[inline(always)] - pub fn new(inner: T) -> Self { - RwLock(parking_lot::RwLock::new(inner)) - } - - #[inline(always)] - pub fn borrow(&self) -> ReadGuard { - if ERROR_CHECKING { - self.0.try_read().expect("lock was already held") - } else { - self.0.read() - } - } - - #[inline(always)] - pub fn borrow_mut(&self) -> WriteGuard { - if ERROR_CHECKING { - self.0.try_write().expect("lock was already held") - } else { - self.0.write() - } - } - } - - // FIXME: Probably a bad idea - impl Clone for RwLock { - #[inline] - fn clone(&self) -> Self { - RwLock::new(self.borrow().clone()) - } - } } } @@ -383,6 +346,11 @@ impl Lock { self.0.borrow_mut() } + #[inline(always)] + pub fn with_lock R, R>(&self, f: F) -> R { + f(&mut *self.lock()) + } + #[inline(always)] pub fn borrow(&self) -> LockGuard { self.lock() @@ -401,3 +369,83 @@ impl Clone for Lock { Lock::new(self.borrow().clone()) } } + +#[derive(Debug)] +pub struct RwLock(InnerRwLock); + +impl RwLock { + #[inline(always)] + pub fn new(inner: T) -> Self { + RwLock(InnerRwLock::new(inner)) + } + + #[inline(always)] + pub fn into_inner(self) -> T { + self.0.into_inner() + } + + #[inline(always)] + pub fn get_mut(&mut self) -> &mut T { + self.0.get_mut() + } + + #[cfg(not(parallel_queries))] + #[inline(always)] + pub fn read(&self) -> ReadGuard { + self.0.borrow() + } + + #[cfg(parallel_queries)] + #[inline(always)] + pub fn read(&self) -> ReadGuard { + if ERROR_CHECKING { + self.0.try_read().expect("lock was already held") + } else { + self.0.read() + } + } + + #[inline(always)] + pub fn with_read_lock R, R>(&self, f: F) -> R { + f(&*self.read()) + } + + #[cfg(not(parallel_queries))] + #[inline(always)] + pub fn write(&self) -> WriteGuard { + self.0.borrow_mut() + } + + #[cfg(parallel_queries)] + #[inline(always)] + pub fn write(&self) -> WriteGuard { + if ERROR_CHECKING { + self.0.try_write().expect("lock was already held") + } else { + self.0.write() + } + } + + #[inline(always)] + pub fn with_write_lock R, R>(&self, f: F) -> R { + f(&mut *self.write()) + } + + #[inline(always)] + pub fn borrow(&self) -> ReadGuard { + self.read() + } + + #[inline(always)] + pub fn borrow_mut(&self) -> WriteGuard { + self.write() + } +} + +// FIXME: Probably a bad idea +impl Clone for RwLock { + #[inline] + fn clone(&self) -> Self { + RwLock::new(self.borrow().clone()) + } +} diff --git a/src/libsyntax/diagnostics/plugin.rs b/src/libsyntax/diagnostics/plugin.rs index dd27dea4f0d97..e8c2d325bd653 100644 --- a/src/libsyntax/diagnostics/plugin.rs +++ b/src/libsyntax/diagnostics/plugin.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cell::RefCell; use std::collections::BTreeMap; use std::env; @@ -31,12 +30,6 @@ pub use errors::*; // Maximum width of any line in an extended error description (inclusive). const MAX_DESCRIPTION_WIDTH: usize = 80; -thread_local! { - static REGISTERED_DIAGNOSTICS: RefCell = { - RefCell::new(BTreeMap::new()) - } -} - /// Error information type. pub struct ErrorInfo { pub description: Option, @@ -46,14 +39,6 @@ pub struct ErrorInfo { /// Mapping from error codes to metadata. pub type ErrorMap = BTreeMap; -fn with_registered_diagnostics(f: F) -> T where - F: FnOnce(&mut ErrorMap) -> T, -{ - REGISTERED_DIAGNOSTICS.with(move |slot| { - f(&mut *slot.borrow_mut()) - }) -} - pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, span: Span, token_tree: &[TokenTree]) @@ -63,7 +48,7 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt, _ => unreachable!() }; - with_registered_diagnostics(|diagnostics| { + ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { match diagnostics.get_mut(&code.name) { // Previously used errors. Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => { @@ -132,7 +117,7 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt, } }); // Add the error to the map. - with_registered_diagnostics(|diagnostics| { + ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { let info = ErrorInfo { description, use_site: None @@ -174,7 +159,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, // Output error metadata to `tmp/extended-errors//.json` if let Ok(target_triple) = env::var("CFG_COMPILER_HOST_TRIPLE") { - with_registered_diagnostics(|diagnostics| { + ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { if let Err(e) = output_metadata(ecx, &target_triple, &crate_name.name.as_str(), @@ -194,7 +179,7 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt, // Construct the output expression. let (count, expr) = - with_registered_diagnostics(|diagnostics| { + ecx.parse_sess.registered_diagnostics.with_lock(|diagnostics| { let descriptions: Vec> = diagnostics.iter().filter_map(|(&code, info)| { info.description.map(|description| { diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 94195ccc72c49..cdf38453d7ea4 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1764,6 +1764,8 @@ mod tests { use std::collections::HashSet; use std::io; use std::path::PathBuf; + use diagnostics::plugin::ErrorMap; + use rustc_data_structures::sync::Lock; fn mk_sess(cm: Lrc) -> ParseSess { let emitter = errors::emitter::EmitterWriter::new(Box::new(io::sink()), Some(cm.clone()), @@ -1776,6 +1778,7 @@ mod tests { included_mod_stack: RefCell::new(Vec::new()), code_map: cm, missing_fragment_specifiers: RefCell::new(HashSet::new()), + registered_diagnostics: Lock::new(ErrorMap::new()), non_modrs_mods: RefCell::new(vec![]), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 1d9af682fec8a..3fb0c209f70f4 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -10,7 +10,7 @@ //! The main parser interface -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Lock}; use ast::{self, CrateConfig}; use codemap::{CodeMap, FilePathMapping}; use syntax_pos::{self, Span, FileMap, NO_EXPANSION, FileName}; @@ -21,6 +21,7 @@ use ptr::P; use str::char_at; use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; +use diagnostics::plugin::ErrorMap; use std::cell::RefCell; use std::collections::HashSet; @@ -47,6 +48,8 @@ pub struct ParseSess { pub unstable_features: UnstableFeatures, pub config: CrateConfig, pub missing_fragment_specifiers: RefCell>, + /// The registered diagnostics codes + pub registered_diagnostics: Lock, // Spans where a `mod foo;` statement was included in a non-mod.rs file. // These are used to issue errors if the non_modrs_mods feature is not enabled. pub non_modrs_mods: RefCell>, @@ -71,6 +74,7 @@ impl ParseSess { unstable_features: UnstableFeatures::from_environment(), config: HashSet::new(), missing_fragment_specifiers: RefCell::new(HashSet::new()), + registered_diagnostics: Lock::new(ErrorMap::new()), included_mod_stack: RefCell::new(vec![]), code_map, non_modrs_mods: RefCell::new(vec![]),