cleanup librustc_errors Handler code.

This commit is contained in:
Mazdak Farrokhzad
2019-09-23 22:28:14 +02:00
parent 62fc4d36df
commit f70665a846
5 changed files with 171 additions and 144 deletions

View File

@@ -302,6 +302,9 @@ pub struct Handler {
inner: Lock<HandlerInner>, inner: Lock<HandlerInner>,
} }
/// This inner struct exists to keep it all behind a single lock;
/// this is done to prevent possible deadlocks in a multi-threaded compiler,
/// as well as inconsistent state observation.
struct HandlerInner { struct HandlerInner {
flags: HandlerFlags, flags: HandlerFlags,
/// The number of errors that have been emitted, including duplicates. /// The number of errors that have been emitted, including duplicates.
@@ -382,52 +385,65 @@ impl Drop for HandlerInner {
} }
impl Handler { impl Handler {
pub fn with_tty_emitter(color_config: ColorConfig, pub fn with_tty_emitter(
can_emit_warnings: bool, color_config: ColorConfig,
treat_err_as_bug: Option<usize>, can_emit_warnings: bool,
cm: Option<Lrc<SourceMapperDyn>>) treat_err_as_bug: Option<usize>,
-> Handler { cm: Option<Lrc<SourceMapperDyn>>,
Handler::with_tty_emitter_and_flags( ) -> Self {
Self::with_tty_emitter_and_flags(
color_config, color_config,
cm, cm,
HandlerFlags { HandlerFlags {
can_emit_warnings, can_emit_warnings,
treat_err_as_bug, treat_err_as_bug,
.. Default::default() .. Default::default()
}) },
)
} }
pub fn with_tty_emitter_and_flags(color_config: ColorConfig, pub fn with_tty_emitter_and_flags(
cm: Option<Lrc<SourceMapperDyn>>, color_config: ColorConfig,
flags: HandlerFlags) cm: Option<Lrc<SourceMapperDyn>>,
-> Handler { flags: HandlerFlags,
) -> Self {
let emitter = Box::new(EmitterWriter::stderr( let emitter = Box::new(EmitterWriter::stderr(
color_config, cm, false, false, None, flags.external_macro_backtrace)); color_config,
Handler::with_emitter_and_flags(emitter, flags) cm,
false,
false,
None,
flags.external_macro_backtrace,
));
Self::with_emitter_and_flags(emitter, flags)
} }
pub fn with_emitter(can_emit_warnings: bool, pub fn with_emitter(
treat_err_as_bug: Option<usize>, can_emit_warnings: bool,
e: Box<dyn Emitter + sync::Send>) treat_err_as_bug: Option<usize>,
-> Handler { emitter: Box<dyn Emitter + sync::Send>,
) -> Self {
Handler::with_emitter_and_flags( Handler::with_emitter_and_flags(
e, emitter,
HandlerFlags { HandlerFlags {
can_emit_warnings, can_emit_warnings,
treat_err_as_bug, treat_err_as_bug,
.. Default::default() .. Default::default()
}) },
)
} }
pub fn with_emitter_and_flags(e: Box<dyn Emitter + sync::Send>, flags: HandlerFlags) -> Handler pub fn with_emitter_and_flags(
{ emitter: Box<dyn Emitter + sync::Send>,
Handler { flags: HandlerFlags
) -> Self {
Self {
flags, flags,
inner: Lock::new(HandlerInner { inner: Lock::new(HandlerInner {
flags, flags,
err_count: 0, err_count: 0,
deduplicated_err_count: 0, deduplicated_err_count: 0,
emitter: e, emitter,
continue_after_error: true, continue_after_error: true,
delayed_span_bugs: Vec::new(), delayed_span_bugs: Vec::new(),
taught_diagnostics: Default::default(), taught_diagnostics: Default::default(),
@@ -474,7 +490,8 @@ impl Handler {
"{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})", "{}:{}: already existing stashed diagnostic with (span = {:?}, key = {:?})",
file!(), line!(), span, key file!(), line!(), span, key
)); ));
inner.emit_explicit_bug(&old_diag); inner.emit_diag_at_span(old_diag, span);
panic!(ExplicitBug);
} }
} }
@@ -492,34 +509,35 @@ impl Handler {
self.inner.borrow_mut().emit_stashed_diagnostics(); self.inner.borrow_mut().emit_stashed_diagnostics();
} }
/// Construct a dummy builder with `Level::Cancelled`.
///
/// Using this will neither report anything to the user (e.g. a warning),
/// nor will compilation cancel as a result.
pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> { pub fn struct_dummy(&self) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Cancelled, "") DiagnosticBuilder::new(self, Level::Cancelled, "")
} }
pub fn struct_span_warn<S: Into<MultiSpan>>(&self, /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
sp: S, pub fn struct_span_warn(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> {
msg: &str) let mut result = self.struct_warn(msg);
-> DiagnosticBuilder<'_> { result.set_span(span);
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
result.set_span(sp);
if !self.flags.can_emit_warnings {
result.cancel();
}
result result
} }
pub fn struct_span_warn_with_code<S: Into<MultiSpan>>(&self,
sp: S, /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
msg: &str, /// Also include a code.
code: DiagnosticId) pub fn struct_span_warn_with_code(
-> DiagnosticBuilder<'_> { &self,
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); span: impl Into<MultiSpan>,
result.set_span(sp); msg: &str,
code: DiagnosticId,
) -> DiagnosticBuilder<'_> {
let mut result = self.struct_span_warn(span, msg);
result.code(code); result.code(code);
if !self.flags.can_emit_warnings {
result.cancel();
}
result result
} }
/// Construct a builder at the `Warning` level with the `msg`.
pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_warn(&self, msg: &str) -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Warning, msg); let mut result = DiagnosticBuilder::new(self, Level::Warning, msg);
if !self.flags.can_emit_warnings { if !self.flags.can_emit_warnings {
@@ -527,136 +545,141 @@ impl Handler {
} }
result result
} }
pub fn struct_span_err<S: Into<MultiSpan>>(&self,
sp: S, /// Construct a builder at the `Error` level at the given `span` and with the `msg`.
msg: &str) pub fn struct_span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> DiagnosticBuilder<'_> {
-> DiagnosticBuilder<'_> { let mut result = self.struct_err(msg);
let mut result = DiagnosticBuilder::new(self, Level::Error, msg); result.set_span(span);
result.set_span(sp);
result result
} }
pub fn struct_span_err_with_code<S: Into<MultiSpan>>(&self,
sp: S, /// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`.
msg: &str, pub fn struct_span_err_with_code(
code: DiagnosticId) &self,
-> DiagnosticBuilder<'_> { span: impl Into<MultiSpan>,
let mut result = DiagnosticBuilder::new(self, Level::Error, msg); msg: &str,
result.set_span(sp); code: DiagnosticId,
) -> DiagnosticBuilder<'_> {
let mut result = self.struct_span_err(span, msg);
result.code(code); result.code(code);
result result
} }
/// Construct a builder at the `Error` level with the `msg`.
// FIXME: This method should be removed (every error should have an associated error code). // FIXME: This method should be removed (every error should have an associated error code).
pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_err(&self, msg: &str) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Error, msg) DiagnosticBuilder::new(self, Level::Error, msg)
} }
pub fn struct_err_with_code(
/// Construct a builder at the `Error` level with the `msg` and the `code`.
pub fn struct_err_with_code(&self, msg: &str, code: DiagnosticId) -> DiagnosticBuilder<'_> {
let mut result = self.struct_err(msg);
result.code(code);
result
}
/// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
pub fn struct_span_fatal(
&self, &self,
span: impl Into<MultiSpan>,
msg: &str,
) -> DiagnosticBuilder<'_> {
let mut result = self.struct_fatal(msg);
result.set_span(span);
result
}
/// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`.
pub fn struct_span_fatal_with_code(
&self,
span: impl Into<MultiSpan>,
msg: &str, msg: &str,
code: DiagnosticId, code: DiagnosticId,
) -> DiagnosticBuilder<'_> { ) -> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Error, msg); let mut result = self.struct_span_fatal(span, msg);
result.code(code);
result
}
pub fn struct_span_fatal<S: Into<MultiSpan>>(&self,
sp: S,
msg: &str)
-> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
result.set_span(sp);
result
}
pub fn struct_span_fatal_with_code<S: Into<MultiSpan>>(&self,
sp: S,
msg: &str,
code: DiagnosticId)
-> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Fatal, msg);
result.set_span(sp);
result.code(code); result.code(code);
result result
} }
/// Construct a builder at the `Error` level with the `msg`.
pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> { pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_> {
DiagnosticBuilder::new(self, Level::Fatal, msg) DiagnosticBuilder::new(self, Level::Fatal, msg)
} }
pub fn span_fatal<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> FatalError { pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: &str) -> FatalError {
self.emit_diagnostic(Diagnostic::new(Fatal, msg).set_span(sp)); self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
self.abort_if_errors_and_should_abort();
FatalError FatalError
} }
pub fn span_fatal_with_code<S: Into<MultiSpan>>(&self,
sp: S, pub fn span_fatal_with_code(
msg: &str, &self,
code: DiagnosticId) span: impl Into<MultiSpan>,
-> FatalError { msg: &str,
self.emit_diagnostic(Diagnostic::new_with_code(Fatal, Some(code), msg).set_span(sp)); code: DiagnosticId,
self.abort_if_errors_and_should_abort(); ) -> FatalError {
self.emit_diag_at_span(Diagnostic::new_with_code(Fatal, Some(code), msg), span);
FatalError FatalError
} }
pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit_diagnostic(Diagnostic::new(Error, msg).set_span(sp)); pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
self.abort_if_errors_and_should_abort(); self.emit_diag_at_span(Diagnostic::new(Error, msg), span);
} }
pub fn mut_span_err<S: Into<MultiSpan>>(&self,
sp: S, pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
msg: &str) self.emit_diag_at_span(Diagnostic::new_with_code(Error, Some(code), msg), span);
-> DiagnosticBuilder<'_> {
let mut result = DiagnosticBuilder::new(self, Level::Error, msg);
result.set_span(sp);
result
} }
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
self.emit_diagnostic(Diagnostic::new_with_code(Error, Some(code), msg).set_span(sp)); pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: &str) {
self.abort_if_errors_and_should_abort(); self.emit_diag_at_span(Diagnostic::new(Warning, msg), span);
} }
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit_diagnostic(Diagnostic::new(Warning, msg).set_span(sp)); pub fn span_warn_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
self.abort_if_errors_and_should_abort(); self.emit_diag_at_span(Diagnostic::new_with_code(Warning, Some(code), msg), span);
} }
pub fn span_warn_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
self.emit_diagnostic(Diagnostic::new_with_code(Warning, Some(code), msg).set_span(sp)); pub fn span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ! {
self.abort_if_errors_and_should_abort(); self.inner.borrow_mut().span_bug(span, msg)
} }
pub fn span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) -> ! {
self.inner.borrow_mut().span_bug(sp, msg) pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) {
self.inner.borrow_mut().delay_span_bug(span, msg)
} }
pub fn delay_span_bug<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.inner.borrow_mut().delay_span_bug(sp, msg) pub fn span_bug_no_panic(&self, span: impl Into<MultiSpan>, msg: &str) {
self.emit_diag_at_span(Diagnostic::new(Bug, msg), span);
} }
pub fn span_bug_no_panic<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit_diagnostic(Diagnostic::new(Bug, msg).set_span(sp)); pub fn span_note_without_error(&self, span: impl Into<MultiSpan>, msg: &str) {
self.abort_if_errors_and_should_abort(); self.emit_diag_at_span(Diagnostic::new(Note, msg), span);
} }
pub fn span_note_without_error<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.emit_diagnostic(Diagnostic::new(Note, msg).set_span(sp)); pub fn span_note_diag(&self, span: Span, msg: &str) -> DiagnosticBuilder<'_> {
self.abort_if_errors_and_should_abort();
}
pub fn span_note_diag(&self,
sp: Span,
msg: &str)
-> DiagnosticBuilder<'_> {
let mut db = DiagnosticBuilder::new(self, Note, msg); let mut db = DiagnosticBuilder::new(self, Note, msg);
db.set_span(sp); db.set_span(span);
db db
} }
pub fn failure(&self, msg: &str) { pub fn failure(&self, msg: &str) {
self.inner.borrow_mut().failure(msg); self.inner.borrow_mut().failure(msg);
} }
pub fn fatal(&self, msg: &str) -> FatalError { pub fn fatal(&self, msg: &str) -> FatalError {
self.inner.borrow_mut().fatal(msg) self.inner.borrow_mut().fatal(msg)
} }
pub fn err(&self, msg: &str) { pub fn err(&self, msg: &str) {
self.inner.borrow_mut().err(msg); self.inner.borrow_mut().err(msg);
} }
pub fn warn(&self, msg: &str) { pub fn warn(&self, msg: &str) {
let mut db = DiagnosticBuilder::new(self, Warning, msg); let mut db = DiagnosticBuilder::new(self, Warning, msg);
db.emit(); db.emit();
} }
pub fn note_without_error(&self, msg: &str) { pub fn note_without_error(&self, msg: &str) {
let mut db = DiagnosticBuilder::new(self, Note, msg); DiagnosticBuilder::new(self, Note, msg).emit();
db.emit();
} }
pub fn bug(&self, msg: &str) -> ! { pub fn bug(&self, msg: &str) -> ! {
self.inner.borrow_mut().bug(msg) self.inner.borrow_mut().bug(msg)
} }
@@ -698,6 +721,12 @@ impl Handler {
self.inner.borrow_mut().emit_diagnostic(diagnostic) self.inner.borrow_mut().emit_diagnostic(diagnostic)
} }
fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
let mut inner = self.inner.borrow_mut();
inner.emit_diagnostic(diag.set_span(sp));
inner.abort_if_errors_and_should_abort();
}
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) { pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
self.inner.borrow_mut().emit_artifact_notification(path, artifact_type) self.inner.borrow_mut().emit_artifact_notification(path, artifact_type)
} }
@@ -837,17 +866,17 @@ impl HandlerInner {
} }
} }
fn span_bug<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) -> ! { fn span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ! {
self.emit_explicit_bug(Diagnostic::new(Bug, msg).set_span(sp)); self.emit_diag_at_span(Diagnostic::new(Bug, msg), sp);
}
fn emit_explicit_bug(&mut self, diag: &Diagnostic) -> ! {
self.emit_diagnostic(diag);
self.abort_if_errors_and_should_abort();
panic!(ExplicitBug); panic!(ExplicitBug);
} }
fn delay_span_bug<S: Into<MultiSpan>>(&mut self, sp: S, msg: &str) { fn emit_diag_at_span(&mut self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
self.emit_diagnostic(diag.set_span(sp));
self.abort_if_errors_and_should_abort();
}
fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
if self.treat_err_as_bug() { if self.treat_err_as_bug() {
// FIXME: don't abort here if report_delayed_bugs is off // FIXME: don't abort here if report_delayed_bugs is off
self.span_bug(sp, msg); self.span_bug(sp, msg);
@@ -862,18 +891,20 @@ impl HandlerInner {
} }
fn fatal(&mut self, msg: &str) -> FatalError { fn fatal(&mut self, msg: &str) -> FatalError {
if self.treat_err_as_bug() { self.emit_error(Fatal, msg);
self.bug(msg);
}
self.emit_diagnostic(&Diagnostic::new(Fatal, msg));
FatalError FatalError
} }
fn err(&mut self, msg: &str) { fn err(&mut self, msg: &str) {
self.emit_error(Error, msg);
}
/// Emit an error; level should be `Error` or `Fatal`.
fn emit_error(&mut self, level: Level, msg: &str,) {
if self.treat_err_as_bug() { if self.treat_err_as_bug() {
self.bug(msg); self.bug(msg);
} }
self.emit_diagnostic(&Diagnostic::new(Error, msg)); self.emit_diagnostic(&Diagnostic::new(level, msg));
} }
fn bug(&mut self, msg: &str) -> ! { fn bug(&mut self, msg: &str) -> ! {

View File

@@ -832,7 +832,7 @@ fn check_method_receiver<'fcx, 'tcx>(
} }
fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) { fn e0307(fcx: &FnCtxt<'fcx, 'tcx>, span: Span, receiver_ty: Ty<'_>) {
fcx.tcx.sess.diagnostic().mut_span_err( fcx.tcx.sess.diagnostic().struct_span_err(
span, span,
&format!("invalid `self` parameter type: {:?}", receiver_ty) &format!("invalid `self` parameter type: {:?}", receiver_ty)
).note("type of `self` must be `Self` or a type that dereferences to it") ).note("type of `self` must be `Self` or a type that dereferences to it")

View File

@@ -1041,10 +1041,6 @@ impl<'a> ExtCtxt<'a> {
pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) { pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: DiagnosticId) {
self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code); self.parse_sess.span_diagnostic.span_err_with_code(sp, msg, code);
} }
pub fn mut_span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str)
-> DiagnosticBuilder<'a> {
self.parse_sess.span_diagnostic.mut_span_err(sp, msg)
}
pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) { pub fn span_warn<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
self.parse_sess.span_diagnostic.span_warn(sp, msg); self.parse_sess.span_diagnostic.span_warn(sp, msg);
} }

View File

@@ -384,7 +384,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
let attr = attr::find_by_name(item.attrs(), sym::derive) let attr = attr::find_by_name(item.attrs(), sym::derive)
.expect("`derive` attribute should exist"); .expect("`derive` attribute should exist");
let span = attr.span; let span = attr.span;
let mut err = self.cx.mut_span_err(span, let mut err = self.cx.struct_span_err(span,
"`derive` may only be applied to structs, enums and unions"); "`derive` may only be applied to structs, enums and unions");
if let ast::AttrStyle::Inner = attr.style { if let ast::AttrStyle::Inner = attr.style {
let trait_list = derives.iter() let trait_list = derives.iter()

View File

@@ -295,7 +295,7 @@ impl<'a, 'b> Context<'a, 'b> {
.filter(|fmt| fmt.precision_span.is_some()) .filter(|fmt| fmt.precision_span.is_some())
.count(); .count();
if self.names.is_empty() && !numbered_position_args && count != self.args.len() { if self.names.is_empty() && !numbered_position_args && count != self.args.len() {
e = self.ecx.mut_span_err( e = self.ecx.struct_span_err(
sp, sp,
&format!( &format!(
"{} positional argument{} in format string, but {}", "{} positional argument{} in format string, but {}",
@@ -336,7 +336,7 @@ impl<'a, 'b> Context<'a, 'b> {
sp = MultiSpan::from_span(self.fmtsp); sp = MultiSpan::from_span(self.fmtsp);
} }
e = self.ecx.mut_span_err(sp, e = self.ecx.struct_span_err(sp,
&format!("invalid reference to positional {} ({})", &format!("invalid reference to positional {} ({})",
arg_list, arg_list,
self.describe_num_args())); self.describe_num_args()));