about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-04-10 09:00:27 +0000
committerbors <bors@rust-lang.org>2018-04-10 09:00:27 +0000
commit67712d79451b042b6fca2167c1a57d91d86f663b (patch)
tree4027dafb2a803d522019bc41052763d61b056f5c
parenta1c21ed7e21642b85947ba5d030bbaeffbe377de (diff)
parent1e3f6388361e1489d27679d6b9e8ba16681e3d26 (diff)
downloadrust-67712d79451b042b6fca2167c1a57d91d86f663b.tar.gz
rust-67712d79451b042b6fca2167c1a57d91d86f663b.zip
Auto merge of #49390 - Zoxc:sync-syntax, r=michaelwoerister
More thread-safety changes

r? @michaelwoerister
-rw-r--r--src/librustc/hir/map/mod.rs14
-rw-r--r--src/librustc/lint/mod.rs7
-rw-r--r--src/librustc/mir/cache.rs10
-rw-r--r--src/librustc/mir/mod.rs8
-rw-r--r--src/librustc/ty/context.rs50
-rw-r--r--src/librustc/ty/steal.rs12
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs2
-rw-r--r--src/librustc_data_structures/sync.rs12
-rw-r--r--src/librustc_trans/back/write.rs6
-rw-r--r--src/libsyntax/ext/base.rs20
-rw-r--r--src/libsyntax/lib.rs2
-rw-r--r--src/libsyntax/parse/lexer/mod.rs9
-rw-r--r--src/libsyntax/parse/mod.rs17
-rw-r--r--src/libsyntax/parse/token.rs21
14 files changed, 101 insertions, 89 deletions
diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs
index e8bcbfbb77a..1e348e3a31c 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<DefIdMap<&'hir Body>>,
+    inlined_bodies: Lock<DefIdMap<&'hir Body>>,
 
     /// The reverse mapping of `node_to_hir_id`.
     hir_to_node_id: FxHashMap<HirId, NodeId>,
@@ -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 89a9f303478..0d4fd99995f 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<dyn EarlyLintPass + 'static>;
-pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>;
+pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
+pub type LateLintPassObject = Box<dyn for<'a, 'tcx> 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 9b75c19a875..1ed5a22257c 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<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
+    predecessors: RwLock<Option<IndexVec<BasicBlock, Vec<BasicBlock>>>>
 }
 
 
@@ -46,7 +46,7 @@ impl<'a> HashStable<StableHashingContext<'a>> 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<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self, mir: &Mir) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         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 9ed4e6a8e00..33f52ab09c8 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<IndexVec<BasicBlock, Vec<BasicBlock>>> {
+    pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
         self.cache.predecessors(self)
     }
 
     #[inline]
-    pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> {
-        Ref::map(self.predecessors(), |p| &p[bb])
+    pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
+        ReadGuard::map(self.predecessors(), |p| &p[bb])
     }
 
     #[inline]
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 69b33efdb35..e6ad95ec3c7 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -58,7 +58,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};
@@ -131,28 +131,28 @@ pub struct CtxtInterners<'tcx> {
 
     /// Specifically use a speedy hash algorithm for these hash sets,
     /// they're accessed quite often.
-    type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
-    type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
-    substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
-    canonical_var_infos: RefCell<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
-    region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>,
-    existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
-    predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
-    const_: RefCell<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
+    type_: Lock<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
+    type_list: Lock<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
+    substs: Lock<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
+    canonical_var_infos: Lock<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
+    region: Lock<FxHashSet<Interned<'tcx, RegionKind>>>,
+    existential_predicates: Lock<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
+    predicates: Lock<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
+    const_: Lock<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
 }
 
 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()),
         }
     }
 
@@ -892,11 +892,11 @@ pub struct GlobalCtxt<'tcx> {
     /// by `proc-macro` crates.
     pub derive_macros: RefCell<NodeMap<Symbol>>,
 
-    stability_interner: RefCell<FxHashSet<&'tcx attr::Stability>>,
+    stability_interner: Lock<FxHashSet<&'tcx attr::Stability>>,
 
     pub interpret_interner: InterpretInterner<'tcx>,
 
-    layout_interner: RefCell<FxHashSet<&'tcx LayoutDetails>>,
+    layout_interner: Lock<FxHashSet<&'tcx LayoutDetails>>,
 
     /// A vector of every trait accessible in the whole crate
     /// (i.e. including those from subcrates). This is used only for
@@ -910,7 +910,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<Box<dyn Any + Send>>,
+    pub tx_to_llvm_workers: Lock<mpsc::Sender<Box<dyn Any + Send>>>,
 
     output_filenames: Arc<OutputFilenames>,
 }
@@ -918,7 +918,7 @@ pub struct GlobalCtxt<'tcx> {
 /// Everything needed to efficiently work with interned allocations
 #[derive(Debug, Default)]
 pub struct InterpretInterner<'tcx> {
-    inner: RefCell<InterpretInternerInner<'tcx>>,
+    inner: Lock<InterpretInternerInner<'tcx>>,
 }
 
 #[derive(Debug, Default)]
@@ -1278,13 +1278,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()),
         };
 
diff --git a/src/librustc/ty/steal.rs b/src/librustc/ty/steal.rs
index 0b081888881..842c0d65734 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<T> {
-    value: RefCell<Option<T>>
+    value: RwLock<Option<T>>
 }
 
 impl<T> Steal<T> {
     pub fn new(value: T) -> Self {
         Steal {
-            value: RefCell::new(Some(value))
+            value: RwLock::new(Some(value))
         }
     }
 
-    pub fn borrow(&self) -> Ref<T> {
-        Ref::map(self.value.borrow(), |opt| match *opt {
+    pub fn borrow(&self) -> ReadGuard<T> {
+        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 93d6247eeae..2049a146a0f 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 184ef136976..0f534f0adec 100644
--- a/src/librustc_data_structures/sync.rs
+++ b/src/librustc_data_structures/sync.rs
@@ -390,6 +390,18 @@ impl<T> RwLock<T> {
 
     #[cfg(not(parallel_queries))]
     #[inline(always)]
+    pub fn try_write(&self) -> Result<WriteGuard<T>, ()> {
+        self.0.try_borrow_mut().map_err(|_| ())
+    }
+
+    #[cfg(parallel_queries)]
+    #[inline(always)]
+    pub fn try_write(&self) -> Result<WriteGuard<T>, ()> {
+        self.0.try_write().ok_or(())
+    }
+
+    #[cfg(not(parallel_queries))]
+    #[inline(always)]
     pub fn write(&self) -> WriteGuard<T> {
         self.0.borrow_mut()
     }
diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs
index fc699f7569f..6c756576411 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<ModuleConfig>,
                         allocator_config: Arc<ModuleConfig>)
                         -> thread::JoinHandle<Result<CompiledModules, ()>> {
-    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 a09bea25a24..c25a7686bea 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};
 
@@ -565,26 +565,26 @@ pub enum SyntaxExtension {
     /// `#[derive(...)]` is a `MultiItemDecorator`.
     ///
     /// Prefer ProcMacro or MultiModifier since they are more flexible.
-    MultiDecorator(Box<MultiItemDecorator>),
+    MultiDecorator(Box<MultiItemDecorator + sync::Sync + sync::Send>),
 
     /// A syntax extension that is attached to an item and modifies it
     /// in-place. Also allows decoration, i.e., creating new items.
-    MultiModifier(Box<MultiItemModifier>),
+    MultiModifier(Box<MultiItemModifier + sync::Sync + sync::Send>),
 
     /// A function-like procedural macro. TokenStream -> TokenStream.
-    ProcMacro(Box<ProcMacro>),
+    ProcMacro(Box<ProcMacro + sync::Sync + sync::Send>),
 
     /// 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>),
+    AttrProcMacro(Box<AttrProcMacro + sync::Sync + sync::Send>),
 
     /// A normal, function-like syntax extension.
     ///
     /// `bytes!` is a `NormalTT`.
     NormalTT {
-        expander: Box<TTMacroExpander>,
+        expander: Box<TTMacroExpander + sync::Sync + sync::Send>,
         def_info: Option<(ast::NodeId, Span)>,
         /// Whether the contents of the macro can
         /// directly use `#[unstable]` things (true == yes).
@@ -599,13 +599,15 @@ pub enum SyntaxExtension {
     /// A function-like syntax extension that has an extra ident before
     /// the block.
     ///
-    IdentTT(Box<IdentMacroExpander>, Option<Span>, bool),
+    IdentTT(Box<IdentMacroExpander + sync::Sync + sync::Send>, Option<Span>, 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<MultiItemModifier>, Vec<Symbol> /* inert attribute names */),
+    ProcMacroDerive(Box<MultiItemModifier +
+                        sync::Sync +
+                        sync::Send>, Vec<Symbol> /* inert attribute names */),
 
     /// An attribute-like procedural macro that derives a builtin trait.
     BuiltinDerive(BuiltinDeriveFn),
@@ -613,7 +615,7 @@ pub enum SyntaxExtension {
     /// A declarative macro, e.g. `macro m() {}`.
     ///
     /// The second element is the definition site span.
-    DeclMacro(Box<TTMacroExpander>, Option<(ast::NodeId, Span)>),
+    DeclMacro(Box<TTMacroExpander + sync::Sync + sync::Send>, Option<(ast::NodeId, Span)>),
 }
 
 impl SyntaxExtension {
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index c456dc45d21..b1a22724a9a 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -26,6 +26,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 152c4c31eb3..39b2f77f230 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 428b3b136df..ff63c9a5c6d 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};
@@ -46,17 +45,17 @@ pub struct ParseSess {
     pub span_diagnostic: Handler,
     pub unstable_features: UnstableFeatures,
     pub config: CrateConfig,
-    pub missing_fragment_specifiers: RefCell<HashSet<Span>>,
+    pub missing_fragment_specifiers: Lock<HashSet<Span>>,
     /// Places where raw identifiers were used. This is used for feature gating
     /// raw identifiers
-    pub raw_identifier_spans: RefCell<Vec<Span>>,
+    pub raw_identifier_spans: Lock<Vec<Span>>,
     /// The registered diagnostics codes
     pub registered_diagnostics: Lock<ErrorMap>,
     // 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<Vec<(ast::Ident, Span)>>,
+    pub non_modrs_mods: Lock<Vec<(ast::Ident, Span)>>,
     /// Used to determine and report recursive mod inclusions
-    included_mod_stack: RefCell<Vec<PathBuf>>,
+    included_mod_stack: Lock<Vec<PathBuf>>,
     code_map: Lrc<CodeMap>,
 }
 
@@ -75,12 +74,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 df0ea05005c..8da79f92768 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 {
@@ -627,15 +626,8 @@ pub fn is_op(tok: &Token) -> bool {
     }
 }
 
-pub struct LazyTokenStream(Cell<Option<TokenStream>>);
-
-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<Option<TokenStream>>);
 
 impl cmp::Eq for LazyTokenStream {}
 impl PartialEq for LazyTokenStream {
@@ -652,15 +644,14 @@ impl fmt::Debug for LazyTokenStream {
 
 impl LazyTokenStream {
     pub fn new() -> Self {
-        LazyTokenStream(Cell::new(None))
+        LazyTokenStream(Lock::new(None))
     }
 
     pub fn force<F: FnOnce() -> 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()
     }
 }