From bf06a532654515f2ea0536164adb991e8295be56 Mon Sep 17 00:00:00 2001 From: =?utf8?q?John=20K=C3=A5re=20Alsaker?= Date: Sat, 3 Mar 2018 06:20:26 +0100 Subject: [PATCH] Make Handler more thread-safe --- src/librustc/session/mod.rs | 10 ++++---- src/librustc_driver/test.rs | 10 ++++---- src/librustc_errors/lib.rs | 47 ++++++++++++++++++++----------------- src/librustdoc/core.rs | 4 ++-- 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index 696bd736594..2d7a256a369 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -26,7 +26,7 @@ use util::common::{duration_to_secs_str, ErrorReported}; use util::common::ProfileQueriesMsg; -use rustc_data_structures::sync::{Lrc, Lock, LockCell, OneThread, Once, RwLock}; +use rustc_data_structures::sync::{self, Lrc, Lock, LockCell, OneThread, Once, RwLock}; use syntax::ast::NodeId; use errors::{self, DiagnosticBuilder, DiagnosticId}; @@ -929,7 +929,7 @@ pub fn codegen_units(&self) -> usize { } pub fn teach(&self, code: &DiagnosticId) -> bool { - self.opts.debugging_opts.teach && !self.parse_sess.span_diagnostic.code_emitted(code) + self.opts.debugging_opts.teach && self.parse_sess.span_diagnostic.must_teach(code) } /// Are we allowed to use features from the Rust 2018 edition? @@ -983,7 +983,7 @@ pub fn build_session_with_codemap( let external_macro_backtrace = sopts.debugging_opts.external_macro_backtrace; - let emitter: Box = + let emitter: Box = match (sopts.error_format, emitter_dest) { (config::ErrorOutputType::HumanReadable(color_config), None) => Box::new( EmitterWriter::stderr( @@ -1188,7 +1188,7 @@ pub enum IncrCompSession { } pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { - let emitter: Box = match output { + let emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { Box::new(EmitterWriter::stderr(color_config, None, false, false)) } @@ -1203,7 +1203,7 @@ pub fn early_error(output: config::ErrorOutputType, msg: &str) -> ! { } pub fn early_warn(output: config::ErrorOutputType, msg: &str) { - let emitter: Box = match output { + let emitter: Box = match output { config::ErrorOutputType::HumanReadable(color_config) => { Box::new(EmitterWriter::stderr(color_config, None, false, false)) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 5aae895ccc4..04f6503d92d 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -28,7 +28,7 @@ use rustc::hir::map as hir_map; use rustc::session::{self, config}; use rustc::session::config::{OutputFilenames, OutputTypes}; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use syntax; use syntax::ast; use syntax::abi::Abi; @@ -88,13 +88,13 @@ fn emit(&mut self, db: &DiagnosticBuilder) { } } -fn errors(msgs: &[&str]) -> (Box, usize) { +fn errors(msgs: &[&str]) -> (Box, usize) { let v = msgs.iter().map(|m| m.to_string()).collect(); - (box ExpectErrorEmitter { messages: v } as Box, msgs.len()) + (box ExpectErrorEmitter { messages: v } as Box, msgs.len()) } fn test_env(source_string: &str, - args: (Box, usize), + args: (Box, usize), body: F) where F: FnOnce(Env) { @@ -104,7 +104,7 @@ fn test_env(source_string: &str, } fn test_env_impl(source_string: &str, - (emitter, expected_err_count): (Box, usize), + (emitter, expected_err_count): (Box, usize), body: F) where F: FnOnce(Env) { diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 8d5f9ac93f0..ce3efef08cc 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -33,12 +33,12 @@ use emitter::{Emitter, EmitterWriter}; -use rustc_data_structures::sync::{self, Lrc}; +use rustc_data_structures::sync::{self, Lrc, Lock, LockCell}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::stable_hasher::StableHasher; use std::borrow::Cow; -use std::cell::{RefCell, Cell}; +use std::cell::Cell; use std::{error, fmt}; use std::sync::atomic::AtomicUsize; use std::sync::atomic::Ordering::SeqCst; @@ -262,19 +262,22 @@ pub struct Handler { pub flags: HandlerFlags, err_count: AtomicUsize, - emitter: RefCell>, - continue_after_error: Cell, - delayed_span_bug: RefCell>, + emitter: Lock>, + continue_after_error: LockCell, + delayed_span_bug: Lock>, // This set contains the `DiagnosticId` of all emitted diagnostics to avoid // emitting the same diagnostic with extended help (`--teach`) twice, which // would be uneccessary repetition. - tracked_diagnostic_codes: RefCell>, + taught_diagnostics: Lock>, + + /// Used to suggest rustc --explain + emitted_diagnostic_codes: Lock>, // This set contains a hash of every diagnostic that has been emitted by // this handler. These hashes is used to avoid emitting the same error // twice. - emitted_diagnostics: RefCell>, + emitted_diagnostics: Lock>, } fn default_track_diagnostic(_: &Diagnostic) {} @@ -315,7 +318,7 @@ pub fn with_tty_emitter_and_flags(color_config: ColorConfig, pub fn with_emitter(can_emit_warnings: bool, treat_err_as_bug: bool, - e: Box) + e: Box) -> Handler { Handler::with_emitter_and_flags( e, @@ -326,15 +329,16 @@ pub fn with_emitter(can_emit_warnings: bool, }) } - pub fn with_emitter_and_flags(e: Box, flags: HandlerFlags) -> Handler { + pub fn with_emitter_and_flags(e: Box, flags: HandlerFlags) -> Handler { Handler { flags, err_count: AtomicUsize::new(0), - emitter: RefCell::new(e), - continue_after_error: Cell::new(true), - delayed_span_bug: RefCell::new(None), - tracked_diagnostic_codes: RefCell::new(FxHashSet()), - emitted_diagnostics: RefCell::new(FxHashSet()), + emitter: Lock::new(e), + continue_after_error: LockCell::new(true), + delayed_span_bug: Lock::new(None), + taught_diagnostics: Lock::new(FxHashSet()), + emitted_diagnostic_codes: Lock::new(FxHashSet()), + emitted_diagnostics: Lock::new(FxHashSet()), } } @@ -348,7 +352,7 @@ pub fn set_continue_after_error(&self, continue_after_error: bool) { /// tools that want to reuse a `Parser` cleaning the previously emitted diagnostics as well as /// the overall count of emitted error diagnostics. pub fn reset_err_count(&self) { - self.emitted_diagnostics.replace(FxHashSet()); + *self.emitted_diagnostics.borrow_mut() = FxHashSet(); self.err_count.store(0, SeqCst); } @@ -568,10 +572,10 @@ pub fn print_error_count(&self) { let _ = self.fatal(&s); let can_show_explain = self.emitter.borrow().should_show_explain(); - let are_there_diagnostics = !self.tracked_diagnostic_codes.borrow().is_empty(); + let are_there_diagnostics = !self.emitted_diagnostic_codes.borrow().is_empty(); if can_show_explain && are_there_diagnostics { let mut error_codes = - self.tracked_diagnostic_codes.borrow() + self.emitted_diagnostic_codes.borrow() .clone() .into_iter() .filter_map(|x| match x { @@ -630,12 +634,13 @@ pub fn emit_with_code(&self, msp: &MultiSpan, msg: &str, code: DiagnosticId, lvl } } - /// `true` if a diagnostic with this code has already been emitted in this handler. + /// `true` if we haven't taught a diagnostic with this code already. + /// The caller must then teach the user about such a diagnostic. /// /// Used to suppress emitting the same error multiple times with extended explanation when /// calling `-Zteach`. - pub fn code_emitted(&self, code: &DiagnosticId) -> bool { - self.tracked_diagnostic_codes.borrow().contains(code) + pub fn must_teach(&self, code: &DiagnosticId) -> bool { + self.taught_diagnostics.borrow_mut().insert(code.clone()) } pub fn force_print_db(&self, mut db: DiagnosticBuilder) { @@ -651,7 +656,7 @@ fn emit_db(&self, db: &DiagnosticBuilder) { }); if let Some(ref code) = diagnostic.code { - self.tracked_diagnostic_codes.borrow_mut().insert(code.clone()); + self.emitted_diagnostic_codes.borrow_mut().insert(code.clone()); } let diagnostic_hash = { diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index 97c4e859327..9fb024fd906 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -35,7 +35,7 @@ use std::cell::{RefCell, Cell}; use std::mem; -use rustc_data_structures::sync::Lrc; +use rustc_data_structures::sync::{self, Lrc}; use std::rc::Rc; use std::path::PathBuf; @@ -163,7 +163,7 @@ pub fn run_core(search_paths: SearchPaths, }; let codemap = Lrc::new(codemap::CodeMap::new(sessopts.file_path_mapping())); - let emitter: Box = match error_format { + let emitter: Box = match error_format { ErrorOutputType::HumanReadable(color_config) => Box::new( EmitterWriter::stderr( color_config, -- 2.44.0