1
Fork 0

Auto merge of #49390 - Zoxc:sync-syntax, r=michaelwoerister

More thread-safety changes

r? @michaelwoerister
This commit is contained in:
bors 2018-04-10 09:00:27 +00:00
commit 67712d7945
14 changed files with 101 additions and 89 deletions

View file

@ -33,10 +33,11 @@ use hir::svh::Svh;
use util::nodemap::{DefIdMap, FxHashMap}; use util::nodemap::{DefIdMap, FxHashMap};
use arena::TypedArena; use arena::TypedArena;
use std::cell::RefCell;
use std::io; use std::io;
use ty::TyCtxt; use ty::TyCtxt;
use rustc_data_structures::sync::Lock;
pub mod blocks; pub mod blocks;
mod collector; mod collector;
mod def_collector; mod def_collector;
@ -264,7 +265,7 @@ pub struct Map<'hir> {
definitions: &'hir Definitions, definitions: &'hir Definitions,
/// Bodies inlined from other crates are cached here. /// 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`. /// The reverse mapping of `node_to_hir_id`.
hir_to_node_id: FxHashMap<HirId, NodeId>, 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 { 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); let body = self.forest.inlined_bodies.alloc(body);
self.inlined_bodies.borrow_mut().insert(def_id, body); inlined_bodies.insert(def_id, body);
body body
} }
@ -1189,7 +1195,7 @@ pub fn map_crate<'hir>(sess: &::session::Session,
map, map,
hir_to_node_id, hir_to_node_id,
definitions, definitions,
inlined_bodies: RefCell::new(DefIdMap()), inlined_bodies: Lock::new(DefIdMap()),
}; };
hir_id_validator::check_crate(&map); hir_id_validator::check_crate(&map);

View file

@ -31,7 +31,7 @@
pub use self::Level::*; pub use self::Level::*;
pub use self::LintSource::*; pub use self::LintSource::*;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::{self, Lrc};
use errors::{DiagnosticBuilder, DiagnosticId}; use errors::{DiagnosticBuilder, DiagnosticId};
use hir::def_id::{CrateNum, LOCAL_CRATE}; use hir::def_id::{CrateNum, LOCAL_CRATE};
@ -287,8 +287,9 @@ pub trait EarlyLintPass: LintPass {
} }
/// A lint pass boxed up as a trait object. /// A lint pass boxed up as a trait object.
pub type EarlyLintPassObject = Box<dyn EarlyLintPass + 'static>; pub type EarlyLintPassObject = Box<dyn EarlyLintPass + sync::Send + sync::Sync + 'static>;
pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + 'static>; pub type LateLintPassObject = Box<dyn for<'a, 'tcx> LateLintPass<'a, 'tcx> + sync::Send
+ sync::Sync + 'static>;
/// Identifies a lint known to the compiler. /// Identifies a lint known to the compiler.
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]

View file

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::cell::{Ref, RefCell};
use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::indexed_vec::IndexVec;
use rustc_data_structures::sync::{RwLock, ReadGuard};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
StableHasherResult}; StableHasherResult};
use ich::StableHashingContext; use ich::StableHashingContext;
@ -19,7 +19,7 @@ use rustc_serialize as serialize;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Cache { 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 { impl Cache {
pub fn new() -> Self { pub fn new() -> Self {
Cache { Cache {
predecessors: RefCell::new(None) predecessors: RwLock::new(None)
} }
} }
@ -55,12 +55,12 @@ impl Cache {
*self.predecessors.borrow_mut() = None; *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() { if self.predecessors.borrow().is_none() {
*self.predecessors.borrow_mut() = Some(calculate_predecessors(mir)); *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())
} }
} }

View file

@ -34,7 +34,7 @@ use util::ppaux;
use std::slice; use std::slice;
use hir::{self, InlineAsm}; use hir::{self, InlineAsm};
use std::borrow::{Cow}; use std::borrow::{Cow};
use std::cell::Ref; use rustc_data_structures::sync::ReadGuard;
use std::fmt::{self, Debug, Formatter, Write}; use std::fmt::{self, Debug, Formatter, Write};
use std::{iter, mem, u32}; use std::{iter, mem, u32};
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
@ -187,13 +187,13 @@ impl<'tcx> Mir<'tcx> {
} }
#[inline] #[inline]
pub fn predecessors(&self) -> Ref<IndexVec<BasicBlock, Vec<BasicBlock>>> { pub fn predecessors(&self) -> ReadGuard<IndexVec<BasicBlock, Vec<BasicBlock>>> {
self.cache.predecessors(self) self.cache.predecessors(self)
} }
#[inline] #[inline]
pub fn predecessors_for(&self, bb: BasicBlock) -> Ref<Vec<BasicBlock>> { pub fn predecessors_for(&self, bb: BasicBlock) -> ReadGuard<Vec<BasicBlock>> {
Ref::map(self.predecessors(), |p| &p[bb]) ReadGuard::map(self.predecessors(), |p| &p[bb])
} }
#[inline] #[inline]

View file

@ -58,7 +58,7 @@ use rustc_data_structures::stable_hasher::{HashStable, hash_stable_hashmap,
StableVec}; StableVec};
use arena::{TypedArena, DroplessArena}; use arena::{TypedArena, DroplessArena};
use rustc_data_structures::indexed_vec::IndexVec; 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::any::Any;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::cell::{Cell, RefCell}; use std::cell::{Cell, RefCell};
@ -131,28 +131,28 @@ pub struct CtxtInterners<'tcx> {
/// Specifically use a speedy hash algorithm for these hash sets, /// Specifically use a speedy hash algorithm for these hash sets,
/// they're accessed quite often. /// they're accessed quite often.
type_: RefCell<FxHashSet<Interned<'tcx, TyS<'tcx>>>>, type_: Lock<FxHashSet<Interned<'tcx, TyS<'tcx>>>>,
type_list: RefCell<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>, type_list: Lock<FxHashSet<Interned<'tcx, Slice<Ty<'tcx>>>>>,
substs: RefCell<FxHashSet<Interned<'tcx, Substs<'tcx>>>>, substs: Lock<FxHashSet<Interned<'tcx, Substs<'tcx>>>>,
canonical_var_infos: RefCell<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>, canonical_var_infos: Lock<FxHashSet<Interned<'tcx, Slice<CanonicalVarInfo>>>>,
region: RefCell<FxHashSet<Interned<'tcx, RegionKind>>>, region: Lock<FxHashSet<Interned<'tcx, RegionKind>>>,
existential_predicates: RefCell<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>, existential_predicates: Lock<FxHashSet<Interned<'tcx, Slice<ExistentialPredicate<'tcx>>>>>,
predicates: RefCell<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>, predicates: Lock<FxHashSet<Interned<'tcx, Slice<Predicate<'tcx>>>>>,
const_: RefCell<FxHashSet<Interned<'tcx, Const<'tcx>>>>, const_: Lock<FxHashSet<Interned<'tcx, Const<'tcx>>>>,
} }
impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> { impl<'gcx: 'tcx, 'tcx> CtxtInterners<'tcx> {
fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> { fn new(arena: &'tcx DroplessArena) -> CtxtInterners<'tcx> {
CtxtInterners { CtxtInterners {
arena, arena: arena,
type_: RefCell::new(FxHashSet()), type_: Lock::new(FxHashSet()),
type_list: RefCell::new(FxHashSet()), type_list: Lock::new(FxHashSet()),
substs: RefCell::new(FxHashSet()), substs: Lock::new(FxHashSet()),
region: RefCell::new(FxHashSet()), canonical_var_infos: Lock::new(FxHashSet()),
existential_predicates: RefCell::new(FxHashSet()), region: Lock::new(FxHashSet()),
canonical_var_infos: RefCell::new(FxHashSet()), existential_predicates: Lock::new(FxHashSet()),
predicates: RefCell::new(FxHashSet()), predicates: Lock::new(FxHashSet()),
const_: RefCell::new(FxHashSet()), const_: Lock::new(FxHashSet()),
} }
} }
@ -892,11 +892,11 @@ pub struct GlobalCtxt<'tcx> {
/// by `proc-macro` crates. /// by `proc-macro` crates.
pub derive_macros: RefCell<NodeMap<Symbol>>, 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>, 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 /// A vector of every trait accessible in the whole crate
/// (i.e. including those from subcrates). This is used only for /// (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 /// 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 /// when satisfying the query for a particular codegen unit. Internally in
/// the query it'll send data along this channel to get processed later. /// 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>, output_filenames: Arc<OutputFilenames>,
} }
@ -918,7 +918,7 @@ pub struct GlobalCtxt<'tcx> {
/// Everything needed to efficiently work with interned allocations /// Everything needed to efficiently work with interned allocations
#[derive(Debug, Default)] #[derive(Debug, Default)]
pub struct InterpretInterner<'tcx> { pub struct InterpretInterner<'tcx> {
inner: RefCell<InterpretInternerInner<'tcx>>, inner: Lock<InterpretInternerInner<'tcx>>,
} }
#[derive(Debug, Default)] #[derive(Debug, Default)]
@ -1278,13 +1278,13 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
evaluation_cache: traits::EvaluationCache::new(), evaluation_cache: traits::EvaluationCache::new(),
crate_name: Symbol::intern(crate_name), crate_name: Symbol::intern(crate_name),
data_layout, data_layout,
layout_interner: RefCell::new(FxHashSet()), layout_interner: Lock::new(FxHashSet()),
layout_depth: Cell::new(0), layout_depth: Cell::new(0),
derive_macros: RefCell::new(NodeMap()), derive_macros: RefCell::new(NodeMap()),
stability_interner: RefCell::new(FxHashSet()), stability_interner: Lock::new(FxHashSet()),
interpret_interner: Default::default(), interpret_interner: Default::default(),
all_traits: RefCell::new(None), all_traits: RefCell::new(None),
tx_to_llvm_workers: tx, tx_to_llvm_workers: Lock::new(tx),
output_filenames: Arc::new(output_filenames.clone()), output_filenames: Arc::new(output_filenames.clone()),
}; };

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
use std::cell::{Ref, RefCell}; use rustc_data_structures::sync::{RwLock, ReadGuard};
use std::mem; use std::mem;
/// The `Steal` struct is intended to used as the value for a query. /// 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? /// FIXME(#41710) -- what is the best way to model linear queries?
pub struct Steal<T> { pub struct Steal<T> {
value: RefCell<Option<T>> value: RwLock<Option<T>>
} }
impl<T> Steal<T> { impl<T> Steal<T> {
pub fn new(value: T) -> Self { pub fn new(value: T) -> Self {
Steal { Steal {
value: RefCell::new(Some(value)) value: RwLock::new(Some(value))
} }
} }
pub fn borrow(&self) -> Ref<T> { pub fn borrow(&self) -> ReadGuard<T> {
Ref::map(self.value.borrow(), |opt| match *opt { ReadGuard::map(self.value.borrow(), |opt| match *opt {
None => bug!("attempted to read from stolen value"), None => bug!("attempted to read from stolen value"),
Some(ref v) => v Some(ref v) => v
}) })
} }
pub fn steal(&self) -> T { 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); let value = mem::replace(value_ref, None);
value.expect("attempt to read from stolen value") value.expect("attempt to read from stolen value")
} }

View file

@ -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 // Note that `mir_validated` is a "stealable" result; the
// thief, `optimized_mir()`, forces borrowck, so we know that // thief, `optimized_mir()`, forces borrowck, so we know that
// is not yet stolen. // 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 // option dance because you can't capture an uninitialized variable
// by mut-ref. // by mut-ref.

View file

@ -388,6 +388,18 @@ impl<T> RwLock<T> {
f(&*self.read()) f(&*self.read())
} }
#[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))] #[cfg(not(parallel_queries))]
#[inline(always)] #[inline(always)]
pub fn write(&self) -> WriteGuard<T> { pub fn write(&self) -> WriteGuard<T> {

View file

@ -1035,7 +1035,7 @@ pub fn start_async_translation(tcx: TyCtxt,
crate_info, crate_info,
time_graph, time_graph,
coordinator_send: tcx.tx_to_llvm_workers.clone(), coordinator_send: tcx.tx_to_llvm_workers.lock().clone(),
trans_worker_receive, trans_worker_receive,
shared_emitter_main, shared_emitter_main,
future: coordinator_thread, future: coordinator_thread,
@ -1428,7 +1428,7 @@ fn start_executing_work(tcx: TyCtxt,
metadata_config: Arc<ModuleConfig>, metadata_config: Arc<ModuleConfig>,
allocator_config: Arc<ModuleConfig>) allocator_config: Arc<ModuleConfig>)
-> thread::JoinHandle<Result<CompiledModules, ()>> { -> 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; let sess = tcx.sess;
// Compute the set of symbols we need to retain when doing LTO (if we need to) // 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, mtrans: ModuleTranslation,
cost: u64) { cost: u64) {
let llvm_work_item = WorkItem::Optimize(mtrans); 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, llvm_work_item,
cost, cost,
}))); })));

View file

@ -28,7 +28,7 @@ use std::collections::HashMap;
use std::iter; use std::iter;
use std::path::PathBuf; use std::path::PathBuf;
use std::rc::Rc; use std::rc::Rc;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::{self, Lrc};
use std::default::Default; use std::default::Default;
use tokenstream::{self, TokenStream}; use tokenstream::{self, TokenStream};
@ -565,26 +565,26 @@ pub enum SyntaxExtension {
/// `#[derive(...)]` is a `MultiItemDecorator`. /// `#[derive(...)]` is a `MultiItemDecorator`.
/// ///
/// Prefer ProcMacro or MultiModifier since they are more flexible. /// 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 /// A syntax extension that is attached to an item and modifies it
/// in-place. Also allows decoration, i.e., creating new items. /// 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. /// 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. /// An attribute-like procedural macro. TokenStream, TokenStream -> TokenStream.
/// The first TokenSteam is the attribute, the second is the annotated item. /// The first TokenSteam is the attribute, the second is the annotated item.
/// Allows modification of the input items and adding new items, similar to /// Allows modification of the input items and adding new items, similar to
/// MultiModifier, but uses TokenStreams, rather than AST nodes. /// MultiModifier, but uses TokenStreams, rather than AST nodes.
AttrProcMacro(Box<AttrProcMacro>), AttrProcMacro(Box<AttrProcMacro + sync::Sync + sync::Send>),
/// A normal, function-like syntax extension. /// A normal, function-like syntax extension.
/// ///
/// `bytes!` is a `NormalTT`. /// `bytes!` is a `NormalTT`.
NormalTT { NormalTT {
expander: Box<TTMacroExpander>, expander: Box<TTMacroExpander + sync::Sync + sync::Send>,
def_info: Option<(ast::NodeId, Span)>, def_info: Option<(ast::NodeId, Span)>,
/// Whether the contents of the macro can /// Whether the contents of the macro can
/// directly use `#[unstable]` things (true == yes). /// directly use `#[unstable]` things (true == yes).
@ -599,13 +599,15 @@ pub enum SyntaxExtension {
/// A function-like syntax extension that has an extra ident before /// A function-like syntax extension that has an extra ident before
/// the block. /// 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. /// An attribute-like procedural macro. TokenStream -> TokenStream.
/// The input is the annotated item. /// The input is the annotated item.
/// Allows generating code to implement a Trait for a given struct /// Allows generating code to implement a Trait for a given struct
/// or enum item. /// 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. /// An attribute-like procedural macro that derives a builtin trait.
BuiltinDerive(BuiltinDeriveFn), BuiltinDerive(BuiltinDeriveFn),
@ -613,7 +615,7 @@ pub enum SyntaxExtension {
/// A declarative macro, e.g. `macro m() {}`. /// A declarative macro, e.g. `macro m() {}`.
/// ///
/// The second element is the definition site span. /// 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 { impl SyntaxExtension {

View file

@ -26,6 +26,8 @@
#![feature(const_atomic_usize_new)] #![feature(const_atomic_usize_new)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]
#![recursion_limit="256"]
// See librustc_cratesio_shim/Cargo.toml for a comment explaining this. // See librustc_cratesio_shim/Cargo.toml for a comment explaining this.
#[allow(unused_extern_crates)] #[allow(unused_extern_crates)]
extern crate rustc_cratesio_shim; extern crate rustc_cratesio_shim;

View file

@ -1781,7 +1781,6 @@ mod tests {
use errors; use errors;
use feature_gate::UnstableFeatures; use feature_gate::UnstableFeatures;
use parse::token; use parse::token;
use std::cell::RefCell;
use std::collections::HashSet; use std::collections::HashSet;
use std::io; use std::io;
use std::path::PathBuf; use std::path::PathBuf;
@ -1797,12 +1796,12 @@ mod tests {
span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)), span_diagnostic: errors::Handler::with_emitter(true, false, Box::new(emitter)),
unstable_features: UnstableFeatures::from_environment(), unstable_features: UnstableFeatures::from_environment(),
config: CrateConfig::new(), config: CrateConfig::new(),
included_mod_stack: RefCell::new(Vec::new()), included_mod_stack: Lock::new(Vec::new()),
code_map: cm, code_map: cm,
missing_fragment_specifiers: RefCell::new(HashSet::new()), missing_fragment_specifiers: Lock::new(HashSet::new()),
raw_identifier_spans: RefCell::new(Vec::new()), raw_identifier_spans: Lock::new(Vec::new()),
registered_diagnostics: Lock::new(ErrorMap::new()), registered_diagnostics: Lock::new(ErrorMap::new()),
non_modrs_mods: RefCell::new(vec![]), non_modrs_mods: Lock::new(vec![]),
} }
} }

View file

@ -23,7 +23,6 @@ use symbol::Symbol;
use tokenstream::{TokenStream, TokenTree}; use tokenstream::{TokenStream, TokenTree};
use diagnostics::plugin::ErrorMap; use diagnostics::plugin::ErrorMap;
use std::cell::RefCell;
use std::collections::HashSet; use std::collections::HashSet;
use std::iter; use std::iter;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
@ -46,17 +45,17 @@ pub struct ParseSess {
pub span_diagnostic: Handler, pub span_diagnostic: Handler,
pub unstable_features: UnstableFeatures, pub unstable_features: UnstableFeatures,
pub config: CrateConfig, 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 /// Places where raw identifiers were used. This is used for feature gating
/// raw identifiers /// raw identifiers
pub raw_identifier_spans: RefCell<Vec<Span>>, pub raw_identifier_spans: Lock<Vec<Span>>,
/// The registered diagnostics codes /// The registered diagnostics codes
pub registered_diagnostics: Lock<ErrorMap>, pub registered_diagnostics: Lock<ErrorMap>,
// Spans where a `mod foo;` statement was included in a non-mod.rs file. // 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. // 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 /// Used to determine and report recursive mod inclusions
included_mod_stack: RefCell<Vec<PathBuf>>, included_mod_stack: Lock<Vec<PathBuf>>,
code_map: Lrc<CodeMap>, code_map: Lrc<CodeMap>,
} }
@ -75,12 +74,12 @@ impl ParseSess {
span_diagnostic: handler, span_diagnostic: handler,
unstable_features: UnstableFeatures::from_environment(), unstable_features: UnstableFeatures::from_environment(),
config: HashSet::new(), config: HashSet::new(),
missing_fragment_specifiers: RefCell::new(HashSet::new()), missing_fragment_specifiers: Lock::new(HashSet::new()),
raw_identifier_spans: RefCell::new(Vec::new()), raw_identifier_spans: Lock::new(Vec::new()),
registered_diagnostics: Lock::new(ErrorMap::new()), registered_diagnostics: Lock::new(ErrorMap::new()),
included_mod_stack: RefCell::new(vec![]), included_mod_stack: Lock::new(vec![]),
code_map, code_map,
non_modrs_mods: RefCell::new(vec![]), non_modrs_mods: Lock::new(vec![]),
} }
} }

View file

@ -25,9 +25,8 @@ use syntax_pos::{self, Span, FileName};
use tokenstream::{TokenStream, TokenTree}; use tokenstream::{TokenStream, TokenTree};
use tokenstream; use tokenstream;
use std::cell::Cell;
use std::{cmp, fmt}; 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)] #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
pub enum BinOpToken { pub enum BinOpToken {
@ -627,15 +626,8 @@ pub fn is_op(tok: &Token) -> bool {
} }
} }
pub struct LazyTokenStream(Cell<Option<TokenStream>>); #[derive(Clone)]
pub struct LazyTokenStream(Lock<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))
}
}
impl cmp::Eq for LazyTokenStream {} impl cmp::Eq for LazyTokenStream {}
impl PartialEq for LazyTokenStream { impl PartialEq for LazyTokenStream {
@ -652,15 +644,14 @@ impl fmt::Debug for LazyTokenStream {
impl LazyTokenStream { impl LazyTokenStream {
pub fn new() -> Self { pub fn new() -> Self {
LazyTokenStream(Cell::new(None)) LazyTokenStream(Lock::new(None))
} }
pub fn force<F: FnOnce() -> TokenStream>(&self, f: F) -> TokenStream { 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() { if opt_stream.is_none() {
opt_stream = Some(f()); *opt_stream = Some(f());
} }
self.0.set(opt_stream.clone());
opt_stream.clone().unwrap() opt_stream.clone().unwrap()
} }
} }