diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index e8bcbfbb77a17..1e348e3a31ce2 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -33,10 +33,11 @@ use hir::svh::Svh; use util::nodemap::{DefIdMap, FxHashMap}; use arena::TypedArena; -use std::cell::RefCell; use std::io; use ty::TyCtxt; +use rustc_data_structures::sync::Lock; + pub mod blocks; mod collector; mod def_collector; @@ -264,7 +265,7 @@ pub struct Map<'hir> { definitions: &'hir Definitions, /// Bodies inlined from other crates are cached here. - inlined_bodies: RefCell>, + inlined_bodies: Lock>, /// The reverse mapping of `node_to_hir_id`. hir_to_node_id: FxHashMap, @@ -927,8 +928,13 @@ impl<'hir> Map<'hir> { } pub fn intern_inlined_body(&self, def_id: DefId, body: Body) -> &'hir Body { + let mut inlined_bodies = self.inlined_bodies.borrow_mut(); + if let Some(&b) = inlined_bodies.get(&def_id) { + debug_assert_eq!(&body, b); + return b; + } let body = self.forest.inlined_bodies.alloc(body); - self.inlined_bodies.borrow_mut().insert(def_id, body); + inlined_bodies.insert(def_id, body); body } @@ -1189,7 +1195,7 @@ pub fn map_crate<'hir>(sess: &::session::Session, map, hir_to_node_id, definitions, - inlined_bodies: RefCell::new(DefIdMap()), + inlined_bodies: Lock::new(DefIdMap()), }; hir_id_validator::check_crate(&map); diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs index 1497be2d5ba0d..2103a7d22b5ba 100644 --- a/src/librustc/lint/mod.rs +++ b/src/librustc/lint/mod.rs @@ -31,7 +31,7 @@ pub use self::Level::*; pub use self::LintSource::*; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use errors::{DiagnosticBuilder, DiagnosticId}; use hir::def_id::{CrateNum, LOCAL_CRATE}; @@ -287,8 +287,9 @@ pub trait EarlyLintPass: LintPass { } /// A lint pass boxed up as a trait object. -pub type EarlyLintPassObject = Box; -pub type LateLintPassObject = Box LateLintPass<'a, 'tcx> + 'static>; +pub type EarlyLintPassObject = Box; +pub type LateLintPassObject = Box LateLintPass<'a, 'tcx> + sync::Send + + sync::Sync + 'static>; /// Identifies a lint known to the compiler. #[derive(Clone, Copy, Debug)] diff --git a/src/librustc/mir/cache.rs b/src/librustc/mir/cache.rs index 9b75c19a875eb..1ed5a22257c53 100644 --- a/src/librustc/mir/cache.rs +++ b/src/librustc/mir/cache.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cell::{Ref, RefCell}; use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::sync::{RwLock, ReadGuard}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; use ich::StableHashingContext; @@ -19,7 +19,7 @@ use rustc_serialize as serialize; #[derive(Clone, Debug)] pub struct Cache { - predecessors: RefCell>>> + predecessors: RwLock>>> } @@ -46,7 +46,7 @@ impl<'a> HashStable> for Cache { impl Cache { pub fn new() -> Self { Cache { - predecessors: RefCell::new(None) + predecessors: RwLock::new(None) } } @@ -55,12 +55,12 @@ impl Cache { *self.predecessors.borrow_mut() = None; } - pub fn predecessors(&self, mir: &Mir) -> Ref>> { + pub fn predecessors(&self, mir: &Mir) -> ReadGuard>> { if self.predecessors.borrow().is_none() { *self.predecessors.borrow_mut() = Some(calculate_predecessors(mir)); } - Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap()) + ReadGuard::map(self.predecessors.borrow(), |p| p.as_ref().unwrap()) } } diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 9ed4e6a8e00ae..33f52ab09c856 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -34,7 +34,7 @@ use util::ppaux; use std::slice; use hir::{self, InlineAsm}; use std::borrow::{Cow}; -use std::cell::Ref; +use rustc_data_structures::sync::ReadGuard; use std::fmt::{self, Debug, Formatter, Write}; use std::{iter, mem, u32}; use std::ops::{Index, IndexMut}; @@ -187,13 +187,13 @@ impl<'tcx> Mir<'tcx> { } #[inline] - pub fn predecessors(&self) -> Ref>> { + pub fn predecessors(&self) -> ReadGuard>> { self.cache.predecessors(self) } #[inline] - pub fn predecessors_for(&self, bb: BasicBlock) -> Ref> { - Ref::map(self.predecessors(), |p| &p[bb]) + pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard> { + ReadGuard::map(self.predecessors(), |p| &p[bb]) } #[inline] diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index fdda2286da03b..fa47315f41dfb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -57,7 +57,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap, StableVec}; use arena::{TypedArena, DroplessArena}; use rustc_data_structures::indexed_vec::IndexVec; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Lock}; use std::any::Any; use std::borrow::Borrow; use std::cell::{Cell, RefCell}; @@ -130,28 +130,28 @@ pub struct CtxtInterners<'tcx> { /// Specifically use a speedy hash algorithm for these hash sets, /// they're accessed quite often. - type_: RefCell>>>, - type_list: RefCell>>>>, - substs: RefCell>>>, - canonical_var_infos: RefCell>>>, - region: RefCell>>, - existential_predicates: RefCell>>>>, - predicates: RefCell>>>>, - const_: RefCell>>>, + type_: Lock>>>, + type_list: Lock>>>>, + substs: Lock>>>, + canonical_var_infos: Lock>>>, + region: Lock>>, + existential_predicates: Lock>>>>, + predicates: Lock>>>>, + const_: Lock>>>, } impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> { CtxtInterners { - arena, - type_: RefCell::new(FxHashSet()), - type_list: RefCell::new(FxHashSet()), - substs: RefCell::new(FxHashSet()), - region: RefCell::new(FxHashSet()), - existential_predicates: RefCell::new(FxHashSet()), - canonical_var_infos: RefCell::new(FxHashSet()), - predicates: RefCell::new(FxHashSet()), - const_: RefCell::new(FxHashSet()), + arena: arena, + type_: Lock::new(FxHashSet()), + type_list: Lock::new(FxHashSet()), + substs: Lock::new(FxHashSet()), + canonical_var_infos: Lock::new(FxHashSet()), + region: Lock::new(FxHashSet()), + existential_predicates: Lock::new(FxHashSet()), + predicates: Lock::new(FxHashSet()), + const_: Lock::new(FxHashSet()), } } @@ -891,11 +891,11 @@ pub struct GlobalCtxt<'tcx> { /// by `proc-macro` crates. pub derive_macros: RefCell>, - stability_interner: RefCell>, + stability_interner: Lock>, pub interpret_interner: InterpretInterner<'tcx>, - layout_interner: RefCell>, + layout_interner: Lock>, /// A vector of every trait accessible in the whole crate /// (i.e. including those from subcrates). This is used only for @@ -909,7 +909,7 @@ pub struct GlobalCtxt<'tcx> { /// This is intended to only get used during the trans phase of the compiler /// when satisfying the query for a particular codegen unit. Internally in /// the query it'll send data along this channel to get processed later. - pub tx_to_llvm_workers: mpsc::Sender>, + pub tx_to_llvm_workers: Lock>>, output_filenames: Arc, } @@ -917,7 +917,7 @@ pub struct GlobalCtxt<'tcx> { /// Everything needed to efficiently work with interned allocations #[derive(Debug, Default)] pub struct InterpretInterner<'tcx> { - inner: RefCell>, + inner: Lock>, } #[derive(Debug, Default)] @@ -1277,13 +1277,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { evaluation_cache: traits::EvaluationCache::new(), crate_name: Symbol::intern(crate_name), data_layout, - layout_interner: RefCell::new(FxHashSet()), + layout_interner: Lock::new(FxHashSet()), layout_depth: Cell::new(0), derive_macros: RefCell::new(NodeMap()), - stability_interner: RefCell::new(FxHashSet()), + stability_interner: Lock::new(FxHashSet()), interpret_interner: Default::default(), all_traits: RefCell::new(None), - tx_to_llvm_workers: tx, + tx_to_llvm_workers: Lock::new(tx), output_filenames: Arc::new(output_filenames.clone()), }, f) } diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs index 0b0818888812f..842c0d6573432 100644 --- a/src/librustc/ty/steal.rs +++ b/src/librustc/ty/steal.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cell::{Ref, RefCell}; +use rustc_data_structures::sync::{RwLock, ReadGuard}; use std::mem; /// The `Steal` struct is intended to used as the value for a query. @@ -32,25 +32,25 @@ use std::mem; /// /// FIXME(#41710) -- what is the best way to model linear queries? pub struct Steal { - value: RefCell> + value: RwLock> } impl Steal { pub fn new(value: T) -> Self { Steal { - value: RefCell::new(Some(value)) + value: RwLock::new(Some(value)) } } - pub fn borrow(&self) -> Ref { - Ref::map(self.value.borrow(), |opt| match *opt { + pub fn borrow(&self) -> ReadGuard { + ReadGuard::map(self.value.borrow(), |opt| match *opt { None => bug!("attempted to read from stolen value"), Some(ref v) => v }) } pub fn steal(&self) -> T { - let value_ref = &mut *self.value.borrow_mut(); + let value_ref = &mut *self.value.try_write().expect("stealing value which is locked"); let value = mem::replace(value_ref, None); value.expect("attempt to read from stolen value") } diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 93d6247eeae47..2049a146a0f02 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -128,7 +128,7 @@ fn borrowck<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, owner_def_id: DefId) // Note that `mir_validated` is a "stealable" result; the // thief, `optimized_mir()`, forces borrowck, so we know that // is not yet stolen. - tcx.mir_validated(owner_def_id).borrow(); + ty::maps::queries::mir_validated::ensure(tcx, owner_def_id); // option dance because you can't capture an uninitialized variable // by mut-ref. diff --git a/src/librustc_data_structures/sync.rs b/src/librustc_data_structures/sync.rs index 184ef1369761c..0f534f0adec4b 100644 --- a/src/librustc_data_structures/sync.rs +++ b/src/librustc_data_structures/sync.rs @@ -388,6 +388,18 @@ impl RwLock { f(&*self.read()) } + #[cfg(not(parallel_queries))] + #[inline(always)] + pub fn try_write(&self) -> Result, ()> { + self.0.try_borrow_mut().map_err(|_| ()) + } + + #[cfg(parallel_queries)] + #[inline(always)] + pub fn try_write(&self) -> Result, ()> { + self.0.try_write().ok_or(()) + } + #[cfg(not(parallel_queries))] #[inline(always)] pub fn write(&self) -> WriteGuard { diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index 2cbb88fed05c2..6e7ebd4846e39 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -1035,7 +1035,7 @@ pub fn start_async_translation(tcx: TyCtxt, crate_info, time_graph, - coordinator_send: tcx.tx_to_llvm_workers.clone(), + coordinator_send: tcx.tx_to_llvm_workers.lock().clone(), trans_worker_receive, shared_emitter_main, future: coordinator_thread, @@ -1428,7 +1428,7 @@ fn start_executing_work(tcx: TyCtxt, metadata_config: Arc, allocator_config: Arc) -> thread::JoinHandle> { - let coordinator_send = tcx.tx_to_llvm_workers.clone(); + let coordinator_send = tcx.tx_to_llvm_workers.lock().clone(); let sess = tcx.sess; // Compute the set of symbols we need to retain when doing LTO (if we need to) @@ -2340,7 +2340,7 @@ pub(crate) fn submit_translated_module_to_llvm(tcx: TyCtxt, mtrans: ModuleTranslation, cost: u64) { let llvm_work_item = WorkItem::Optimize(mtrans); - drop(tcx.tx_to_llvm_workers.send(Box::new(Message::TranslationDone { + drop(tcx.tx_to_llvm_workers.lock().send(Box::new(Message::TranslationDone { llvm_work_item, cost, }))); diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs index c3ae0fd2ca863..90459fec670e3 100644 --- a/src/libsyntax/ext/base.rs +++ b/src/libsyntax/ext/base.rs @@ -28,7 +28,7 @@ use std::collections::HashMap; use std::iter; use std::path::PathBuf; use std::rc::Rc; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use std::default::Default; use tokenstream::{self, TokenStream}; @@ -529,26 +529,26 @@ pub enum SyntaxExtension { /// `#[derive(...)]` is a `MultiItemDecorator`. /// /// Prefer ProcMacro or MultiModifier since they are more flexible. - MultiDecorator(Box), + MultiDecorator(Box), /// A syntax extension that is attached to an item and modifies it /// in-place. Also allows decoration, i.e., creating new items. - MultiModifier(Box), + MultiModifier(Box), /// A function-like procedural macro. TokenStream -> TokenStream. - ProcMacro(Box), + ProcMacro(Box), /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream. /// The first TokenSteam is the attribute, the second is the annotated item. /// Allows modification of the input items and adding new items, similar to /// MultiModifier, but uses TokenStreams, rather than AST nodes. - AttrProcMacro(Box), + AttrProcMacro(Box), /// A normal, function-like syntax extension. /// /// `bytes!` is a `NormalTT`. NormalTT { - expander: Box, + expander: Box, def_info: Option<(ast::NodeId, Span)>, /// Whether the contents of the macro can /// directly use `#[unstable]` things (true == yes). @@ -563,13 +563,15 @@ pub enum SyntaxExtension { /// A function-like syntax extension that has an extra ident before /// the block. /// - IdentTT(Box, Option, bool), + IdentTT(Box, Option, bool), /// An attribute-like procedural macro. TokenStream -> TokenStream. /// The input is the annotated item. /// Allows generating code to implement a Trait for a given struct /// or enum item. - ProcMacroDerive(Box, Vec /* inert attribute names */), + ProcMacroDerive(Box, Vec /* inert attribute names */), /// An attribute-like procedural macro that derives a builtin trait. BuiltinDerive(BuiltinDeriveFn), @@ -577,7 +579,7 @@ pub enum SyntaxExtension { /// A declarative macro, e.g. `macro m() {}`. /// /// The second element is the definition site span. - DeclMacro(Box, Option<(ast::NodeId, Span)>), + DeclMacro(Box, Option<(ast::NodeId, Span)>), } impl SyntaxExtension { diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs index 74f1ee373ec63..ce7fa226b96ae 100644 --- a/src/libsyntax/lib.rs +++ b/src/libsyntax/lib.rs @@ -28,6 +28,8 @@ #![feature(const_atomic_usize_new)] #![feature(rustc_attrs)] +#![recursion_limit="256"] + // See librustc_cratesio_shim/Cargo.toml for a comment explaining this. #[allow(unused_extern_crates)] extern crate rustc_cratesio_shim; diff --git a/src/libsyntax/parse/lexer/mod.rs b/src/libsyntax/parse/lexer/mod.rs index 068929c8948df..5db279c768182 100644 --- a/src/libsyntax/parse/lexer/mod.rs +++ b/src/libsyntax/parse/lexer/mod.rs @@ -1781,7 +1781,6 @@ mod tests { use errors; use feature_gate::UnstableFeatures; use parse::token; - use std::cell::RefCell; use std::collections::HashSet; use std::io; use std::path::PathBuf; @@ -1797,12 +1796,12 @@ mod tests { span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)), unstable_features: UnstableFeatures::from_environment(), config: CrateConfig::new(), - included_mod_stack: RefCell::new(Vec::new()), + included_mod_stack: Lock::new(Vec::new()), code_map: cm, - missing_fragment_specifiers: RefCell::new(HashSet::new()), - raw_identifier_spans: RefCell::new(Vec::new()), + missing_fragment_specifiers: Lock::new(HashSet::new()), + raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), - non_modrs_mods: RefCell::new(vec![]), + non_modrs_mods: Lock::new(vec![]), } } diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 7b39db16ac2c8..d5103eb18334f 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -23,7 +23,6 @@ use symbol::Symbol; use tokenstream::{TokenStream, TokenTree}; use diagnostics::plugin::ErrorMap; -use std::cell::RefCell; use std::collections::HashSet; use std::iter; use std::path::{Path, PathBuf}; @@ -47,17 +46,17 @@ pub struct ParseSess { pub span_diagnostic: Handler, pub unstable_features: UnstableFeatures, pub config: CrateConfig, - pub missing_fragment_specifiers: RefCell>, + pub missing_fragment_specifiers: Lock>, /// Places where raw identifiers were used. This is used for feature gating /// raw identifiers - pub raw_identifier_spans: RefCell>, + pub raw_identifier_spans: Lock>, /// 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>, + pub non_modrs_mods: Lock>, /// Used to determine and report recursive mod inclusions - included_mod_stack: RefCell>, + included_mod_stack: Lock>, code_map: Lrc, } @@ -76,12 +75,12 @@ impl ParseSess { span_diagnostic: handler, unstable_features: UnstableFeatures::from_environment(), config: HashSet::new(), - missing_fragment_specifiers: RefCell::new(HashSet::new()), - raw_identifier_spans: RefCell::new(Vec::new()), + missing_fragment_specifiers: Lock::new(HashSet::new()), + raw_identifier_spans: Lock::new(Vec::new()), registered_diagnostics: Lock::new(ErrorMap::new()), - included_mod_stack: RefCell::new(vec![]), + included_mod_stack: Lock::new(vec![]), code_map, - non_modrs_mods: RefCell::new(vec![]), + non_modrs_mods: Lock::new(vec![]), } } diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 7798a7a77ee6c..2c30ac9ba3523 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -25,9 +25,8 @@ use syntax_pos::{self, Span, FileName}; use tokenstream::{TokenStream, TokenTree}; use tokenstream; -use std::cell::Cell; use std::{cmp, fmt}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{Lrc, Lock}; #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] pub enum BinOpToken { @@ -614,15 +613,8 @@ pub fn is_op(tok: &Token) -> bool { } } -pub struct LazyTokenStream(Cell>); - -impl Clone for LazyTokenStream { - fn clone(&self) -> Self { - let opt_stream = self.0.take(); - self.0.set(opt_stream.clone()); - LazyTokenStream(Cell::new(opt_stream)) - } -} +#[derive(Clone)] +pub struct LazyTokenStream(Lock>); impl cmp::Eq for LazyTokenStream {} impl PartialEq for LazyTokenStream { @@ -639,15 +631,14 @@ impl fmt::Debug for LazyTokenStream { impl LazyTokenStream { pub fn new() -> Self { - LazyTokenStream(Cell::new(None)) + LazyTokenStream(Lock::new(None)) } pub fn force TokenStream>(&self, f: F) -> TokenStream { - let mut opt_stream = self.0.take(); + let mut opt_stream = self.0.lock(); if opt_stream.is_none() { - opt_stream = Some(f()); + *opt_stream = Some(f()); } - self.0.set(opt_stream.clone()); opt_stream.clone().unwrap() } }