Skip to content

Commit f4bb956

Browse files
committed
Auto merge of #49349 - Zoxc:sync-errors, r=michaelwoerister
Make Handler more thread-safe The use of `code_emitted` to suppress extended explanations is not thread safe. I'm not sure why we keep the documentation for errors outside `diagnostics.rs` anyway. It would be better to add a `teach` method to `DiagnosticsBuilder`, so instead of: ``` if self.tcx.sess.teach(&err.get_code().unwrap()) { err.note("..."); } ``` we'd use `err.teach("...")` cc @estebank r? @michaelwoerister
2 parents 23561c6 + e5fc06d commit f4bb956

File tree

4 files changed

+40
-35
lines changed

4 files changed

+40
-35
lines changed

src/librustc/session/mod.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use util::nodemap::{FxHashSet};
2626
use util::common::{duration_to_secs_str, ErrorReported};
2727
use util::common::ProfileQueriesMsg;
2828

29-
use rustc_data_structures::sync::{Lrc, Lock, LockCell, OneThread, Once, RwLock};
29+
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock};
3030

3131
use syntax::ast::NodeId;
3232
use errors::{self, DiagnosticBuilder, DiagnosticId};
@@ -89,7 +89,7 @@ pub struct Session {
8989
/// Set of (DiagnosticId, Option<Span>, message) tuples tracking
9090
/// (sub)diagnostics that have been set once, but should not be set again,
9191
/// in order to avoid redundantly verbose output (Issue #24690, #44953).
92-
pub one_time_diagnostics: RefCell<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
92+
pub one_time_diagnostics: Lock<FxHashSet<(DiagnosticMessageId, Option<Span>, String)>>,
9393
pub plugin_llvm_passes: OneThread<RefCell<Vec<String>>>,
9494
pub plugin_attributes: OneThread<RefCell<Vec<(String, AttributeType)>>>,
9595
pub crate_types: Once<Vec<config::CrateType>>,
@@ -929,7 +929,7 @@ impl Session {
929929
}
930930

931931
pub fn teach(&self, code: &DiagnosticId) -> bool {
932-
self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code)
932+
self.opts.debugging_opts.teach && self.parse_sess.span_diagnostic.must_teach(code)
933933
}
934934

935935
/// Are we allowed to use features from the Rust 2018 edition?
@@ -983,7 +983,7 @@ pub fn build_session_with_codemap(
983983

984984
let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace;
985985

986-
let emitter: Box<dyn Emitter> =
986+
let emitter: Box<dyn Emitter + sync::Send> =
987987
match (sopts.error_format, emitter_dest) {
988988
(config::ErrorOutputType::HumanReadable(color_config), None) => Box::new(
989989
EmitterWriter::stderr(
@@ -1091,7 +1091,7 @@ pub fn build_session_(
10911091
working_dir,
10921092
lint_store: RwLock::new(lint::LintStore::new()),
10931093
buffered_lints: Lock::new(Some(lint::LintBuffer::new())),
1094-
one_time_diagnostics: RefCell::new(FxHashSet()),
1094+
one_time_diagnostics: Lock::new(FxHashSet()),
10951095
plugin_llvm_passes: OneThread::new(RefCell::new(Vec::new())),
10961096
plugin_attributes: OneThread::new(RefCell::new(Vec::new())),
10971097
crate_types: Once::new(),
@@ -1188,7 +1188,7 @@ pub enum IncrCompSession {
11881188
}
11891189

11901190
pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
1191-
let emitter: Box<dyn Emitter> = match output {
1191+
let emitter: Box<dyn Emitter + sync::Send> = match output {
11921192
config::ErrorOutputType::HumanReadable(color_config) => {
11931193
Box::new(EmitterWriter::stderr(color_config, None, false, false))
11941194
}
@@ -1203,7 +1203,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! {
12031203
}
12041204

12051205
pub fn early_warn(output: config::ErrorOutputType, msg: &str) {
1206-
let emitter: Box<dyn Emitter> = match output {
1206+
let emitter: Box<dyn Emitter + sync::Send> = match output {
12071207
config::ErrorOutputType::HumanReadable(color_config) => {
12081208
Box::new(EmitterWriter::stderr(color_config, None, false, false))
12091209
}

src/librustc_driver/test.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use rustc_metadata::cstore::CStore;
2828
use rustc::hir::map as hir_map;
2929
use rustc::session::{self, config};
3030
use rustc::session::config::{OutputFilenames, OutputTypes};
31-
use rustc_data_structures::sync::Lrc;
31+
use rustc_data_structures::sync::{self, Lrc};
3232
use syntax;
3333
use syntax::ast;
3434
use syntax::abi::Abi;
@@ -88,13 +88,13 @@ impl Emitter for ExpectErrorEmitter {
8888
}
8989
}
9090

91-
fn errors(msgs: &[&str]) -> (Box<Emitter + Send>, usize) {
91+
fn errors(msgs: &[&str]) -> (Box<Emitter + sync::Send>, usize) {
9292
let v = msgs.iter().map(|m| m.to_string()).collect();
93-
(box ExpectErrorEmitter { messages: v } as Box<Emitter + Send>, msgs.len())
93+
(box ExpectErrorEmitter { messages: v } as Box<Emitter + sync::Send>, msgs.len())
9494
}
9595

9696
fn test_env<F>(source_string: &str,
97-
args: (Box<Emitter + Send>, usize),
97+
args: (Box<Emitter + sync::Send>, usize),
9898
body: F)
9999
where F: FnOnce(Env)
100100
{
@@ -104,7 +104,7 @@ fn test_env<F>(source_string: &str,
104104
}
105105

106106
fn test_env_impl<F>(source_string: &str,
107-
(emitter, expected_err_count): (Box<Emitter + Send>, usize),
107+
(emitter, expected_err_count): (Box<Emitter + sync::Send>, usize),
108108
body: F)
109109
where F: FnOnce(Env)
110110
{

src/librustc_errors/lib.rs

+26-21
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,12 @@ use self::Level::*;
3333

3434
use emitter::{Emitter, EmitterWriter};
3535

36-
use rustc_data_structures::sync::{self, Lrc};
36+
use rustc_data_structures::sync::{self, Lrc, Lock, LockCell};
3737
use rustc_data_structures::fx::FxHashSet;
3838
use rustc_data_structures::stable_hasher::StableHasher;
3939

4040
use std::borrow::Cow;
41-
use std::cell::{RefCell, Cell};
41+
use std::cell::Cell;
4242
use std::{error, fmt};
4343
use std::sync::atomic::AtomicUsize;
4444
use std::sync::atomic::Ordering::SeqCst;
@@ -262,19 +262,22 @@ pub struct Handler {
262262
pub flags: HandlerFlags,
263263

264264
err_count: AtomicUsize,
265-
emitter: RefCell<Box<Emitter>>,
266-
continue_after_error: Cell<bool>,
267-
delayed_span_bug: RefCell<Option<Diagnostic>>,
265+
emitter: Lock<Box<Emitter + sync::Send>>,
266+
continue_after_error: LockCell<bool>,
267+
delayed_span_bug: Lock<Option<Diagnostic>>,
268268

269269
// This set contains the `DiagnosticId` of all emitted diagnostics to avoid
270270
// emitting the same diagnostic with extended help (`--teach`) twice, which
271271
// would be uneccessary repetition.
272-
tracked_diagnostic_codes: RefCell<FxHashSet<DiagnosticId>>,
272+
taught_diagnostics: Lock<FxHashSet<DiagnosticId>>,
273+
274+
/// Used to suggest rustc --explain <error code>
275+
emitted_diagnostic_codes: Lock<FxHashSet<DiagnosticId>>,
273276

274277
// This set contains a hash of every diagnostic that has been emitted by
275278
// this handler. These hashes is used to avoid emitting the same error
276279
// twice.
277-
emitted_diagnostics: RefCell<FxHashSet<u128>>,
280+
emitted_diagnostics: Lock<FxHashSet<u128>>,
278281
}
279282

280283
fn default_track_diagnostic(_: &Diagnostic) {}
@@ -315,7 +318,7 @@ impl Handler {
315318

316319
pub fn with_emitter(can_emit_warnings: bool,
317320
treat_err_as_bug: bool,
318-
e: Box<Emitter>)
321+
e: Box<Emitter + sync::Send>)
319322
-> Handler {
320323
Handler::with_emitter_and_flags(
321324
e,
@@ -326,15 +329,16 @@ impl Handler {
326329
})
327330
}
328331

329-
pub fn with_emitter_and_flags(e: Box<Emitter>, flags: HandlerFlags) -> Handler {
332+
pub fn with_emitter_and_flags(e: Box<Emitter + sync::Send>, flags: HandlerFlags) -> Handler {
330333
Handler {
331334
flags,
332335
err_count: AtomicUsize::new(0),
333-
emitter: RefCell::new(e),
334-
continue_after_error: Cell::new(true),
335-
delayed_span_bug: RefCell::new(None),
336-
tracked_diagnostic_codes: RefCell::new(FxHashSet()),
337-
emitted_diagnostics: RefCell::new(FxHashSet()),
336+
emitter: Lock::new(e),
337+
continue_after_error: LockCell::new(true),
338+
delayed_span_bug: Lock::new(None),
339+
taught_diagnostics: Lock::new(FxHashSet()),
340+
emitted_diagnostic_codes: Lock::new(FxHashSet()),
341+
emitted_diagnostics: Lock::new(FxHashSet()),
338342
}
339343
}
340344

@@ -348,7 +352,7 @@ impl Handler {
348352
/// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as
349353
/// the overall count of emitted error diagnostics.
350354
pub fn reset_err_count(&self) {
351-
self.emitted_diagnostics.replace(FxHashSet());
355+
*self.emitted_diagnostics.borrow_mut() = FxHashSet();
352356
self.err_count.store(0, SeqCst);
353357
}
354358

@@ -568,10 +572,10 @@ impl Handler {
568572
let _ = self.fatal(&s);
569573

570574
let can_show_explain = self.emitter.borrow().should_show_explain();
571-
let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty();
575+
let are_there_diagnostics = !self.emitted_diagnostic_codes.borrow().is_empty();
572576
if can_show_explain && are_there_diagnostics {
573577
let mut error_codes =
574-
self.tracked_diagnostic_codes.borrow()
578+
self.emitted_diagnostic_codes.borrow()
575579
.clone()
576580
.into_iter()
577581
.filter_map(|x| match x {
@@ -630,12 +634,13 @@ impl Handler {
630634
}
631635
}
632636

633-
/// `true` if a diagnostic with this code has already been emitted in this handler.
637+
/// `true` if we haven't taught a diagnostic with this code already.
638+
/// The caller must then teach the user about such a diagnostic.
634639
///
635640
/// Used to suppress emitting the same error multiple times with extended explanation when
636641
/// calling `-Zteach`.
637-
pub fn code_emitted(&self, code: &DiagnosticId) -> bool {
638-
self.tracked_diagnostic_codes.borrow().contains(code)
642+
pub fn must_teach(&self, code: &DiagnosticId) -> bool {
643+
self.taught_diagnostics.borrow_mut().insert(code.clone())
639644
}
640645

641646
pub fn force_print_db(&self, mut db: DiagnosticBuilder) {
@@ -651,7 +656,7 @@ impl Handler {
651656
});
652657

653658
if let Some(ref code) = diagnostic.code {
654-
self.tracked_diagnostic_codes.borrow_mut().insert(code.clone());
659+
self.emitted_diagnostic_codes.borrow_mut().insert(code.clone());
655660
}
656661

657662
let diagnostic_hash = {

src/librustdoc/core.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ use errors::emitter::{Emitter, EmitterWriter};
3535

3636
use std::cell::{RefCell, Cell};
3737
use std::mem;
38-
use rustc_data_structures::sync::Lrc;
38+
use rustc_data_structures::sync::{self, Lrc};
3939
use std::rc::Rc;
4040
use std::path::PathBuf;
4141

@@ -163,7 +163,7 @@ pub fn run_core(search_paths: SearchPaths,
163163
};
164164

165165
let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping()));
166-
let emitter: Box<dyn Emitter> = match error_format {
166+
let emitter: Box<dyn Emitter + sync::Send> = match error_format {
167167
ErrorOutputType::HumanReadable(color_config) => Box::new(
168168
EmitterWriter::stderr(
169169
color_config,

0 commit comments

Comments
 (0)