-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Work towards thread safety in rustc #46779
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
d81cd38
70fd306
94b7124
f7082dc
aa6065b
30a39ac
30733b3
84ce4f1
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -42,6 +42,8 @@ use std::cell::{RefCell, Cell}; | |
use std::mem; | ||
use std::rc::Rc; | ||
use std::{error, fmt}; | ||
use std::sync::atomic::AtomicUsize; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In which case is this not thread safe? |
||
use std::sync::atomic::Ordering::SeqCst; | ||
|
||
mod diagnostic; | ||
mod diagnostic_builder; | ||
|
@@ -236,7 +238,7 @@ pub use diagnostic_builder::DiagnosticBuilder; | |
pub struct Handler { | ||
pub flags: HandlerFlags, | ||
|
||
err_count: Cell<usize>, | ||
err_count: AtomicUsize, | ||
emitter: RefCell<Box<Emitter>>, | ||
continue_after_error: Cell<bool>, | ||
delayed_span_bug: RefCell<Option<Diagnostic>>, | ||
|
@@ -295,7 +297,7 @@ impl Handler { | |
pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> Handler { | ||
Handler { | ||
flags, | ||
err_count: Cell::new(0), | ||
err_count: AtomicUsize::new(0), | ||
emitter: RefCell::new(e), | ||
continue_after_error: Cell::new(true), | ||
delayed_span_bug: RefCell::new(None), | ||
|
@@ -311,7 +313,7 @@ impl Handler { | |
// NOTE: DO NOT call this function from rustc, as it relies on `err_count` being non-zero | ||
// if an error happened to avoid ICEs. This function should only be called from tools. | ||
pub fn reset_err_count(&self) { | ||
self.err_count.set(0); | ||
self.err_count.store(0, SeqCst); | ||
} | ||
|
||
pub fn struct_dummy<'a>(&'a self) -> DiagnosticBuilder<'a> { | ||
|
@@ -507,19 +509,19 @@ impl Handler { | |
|
||
fn bump_err_count(&self) { | ||
self.panic_if_treat_err_as_bug(); | ||
self.err_count.set(self.err_count.get() + 1); | ||
self.err_count.fetch_add(1, SeqCst); | ||
} | ||
|
||
pub fn err_count(&self) -> usize { | ||
self.err_count.get() | ||
self.err_count.load(SeqCst) | ||
} | ||
|
||
pub fn has_errors(&self) -> bool { | ||
self.err_count.get() > 0 | ||
self.err_count() > 0 | ||
} | ||
pub fn abort_if_errors(&self) { | ||
let s; | ||
match self.err_count.get() { | ||
match self.err_count() { | ||
0 => { | ||
if let Some(bug) = self.delayed_span_bug.borrow_mut().take() { | ||
DiagnosticBuilder::new_diagnostic(self, bug).emit(); | ||
|
@@ -528,7 +530,7 @@ impl Handler { | |
} | ||
1 => s = "aborting due to previous error".to_string(), | ||
_ => { | ||
s = format!("aborting due to {} previous errors", self.err_count.get()); | ||
s = format!("aborting due to {} previous errors", self.err_count()); | ||
} | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -15,6 +15,7 @@ use std::hash::{Hash, BuildHasher}; | |
use {Decodable, Encodable, Decoder, Encoder}; | ||
use std::collections::{LinkedList, VecDeque, BTreeMap, BTreeSet, HashMap, HashSet}; | ||
use std::rc::Rc; | ||
use std::sync::Arc; | ||
|
||
impl< | ||
T: Encodable | ||
|
@@ -218,3 +219,26 @@ impl<T: Decodable> Decodable for Rc<[T]> { | |
}) | ||
} | ||
} | ||
|
||
impl<T: Encodable> Encodable for Arc<[T]> { | ||
fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> { | ||
s.emit_seq(self.len(), |s| { | ||
for (index, e) in self.iter().enumerate() { | ||
s.emit_seq_elt(index, |s| e.encode(s))?; | ||
} | ||
Ok(()) | ||
}) | ||
} | ||
} | ||
|
||
impl<T: Decodable> Decodable for Arc<[T]> { | ||
fn decode<D: Decoder>(d: &mut D) -> Result<Arc<[T]>, D::Error> { | ||
d.read_seq(|d, len| { | ||
let mut vec = Vec::with_capacity(len); | ||
for index in 0..len { | ||
vec.push(d.read_seq_elt(index, |d| Decodable::decode(d))?); | ||
} | ||
Ok(vec.into()) | ||
}) | ||
} | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing trailing newline |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,7 +31,7 @@ use symbol::Symbol; | |
use tokenstream::{TokenStream, TokenTree, Delimited}; | ||
use util::ThinVec; | ||
|
||
use std::cell::{RefCell, Cell}; | ||
use std::cell::RefCell; | ||
use std::iter; | ||
|
||
thread_local! { | ||
|
@@ -419,16 +419,14 @@ pub fn mk_spanned_word_item(sp: Span, name: Name) -> MetaItem { | |
MetaItem { span: sp, name: name, node: MetaItemKind::Word } | ||
} | ||
|
||
pub fn mk_attr_id() -> AttrId { | ||
use std::sync::atomic::AtomicUsize; | ||
use std::sync::atomic::Ordering; | ||
|
||
static NEXT_ATTR_ID: AtomicUsize = AtomicUsize::new(0); | ||
|
||
thread_local! { static NEXT_ATTR_ID: Cell<usize> = Cell::new(0) } | ||
|
||
pub fn mk_attr_id() -> AttrId { | ||
let id = NEXT_ATTR_ID.with(|slot| { | ||
let r = slot.get(); | ||
slot.set(r + 1); | ||
r | ||
}); | ||
let id = NEXT_ATTR_ID.fetch_add(1, Ordering::SeqCst); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @rust-lang/compiler Not sure how I feel about this kind of stuff - it will behave non-deterministically in any process running multiple rustc threads in parallel (atm rustc "owns" a thread). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point. I'll make this either a scoped thread local or put it in |
||
assert!(id != ::std::usize::MAX); | ||
AttrId(id) | ||
} | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we need a better locking discipline for the codemap? It feels like "too many locks, not enough discipline". Maybe just add a fixme to it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Given that I just convert all
RefCell
s into locks, there's probably plenty of places where there are too many locks.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok