rustc_error: make ErrorReported impossible to construct

There are a few places were we have to construct it, though, and a few
places that are more invasive to change. To do this, we create a
constructor with a long obvious name.
This commit is contained in:
mark 2022-01-22 18:49:12 -06:00
parent 461e807801
commit bb8d4307eb
104 changed files with 705 additions and 550 deletions

View file

@ -399,7 +399,7 @@ impl fmt::Display for ExplicitBug {
impl error::Error for ExplicitBug {}
pub use diagnostic::{Diagnostic, DiagnosticId, DiagnosticStyledString, SubDiagnostic};
pub use diagnostic_builder::DiagnosticBuilder;
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
use std::backtrace::Backtrace;
/// A handler deals with errors and other compiler output.
@ -644,8 +644,8 @@ impl Handler {
}
/// Emit all stashed diagnostics.
pub fn emit_stashed_diagnostics(&self) {
self.inner.borrow_mut().emit_stashed_diagnostics();
pub fn emit_stashed_diagnostics(&self) -> Option<ErrorGuaranteed> {
self.inner.borrow_mut().emit_stashed_diagnostics()
}
/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
@ -805,8 +805,8 @@ impl Handler {
FatalError.raise()
}
pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) {
self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span);
pub fn span_err(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
}
pub fn span_err_with_code(&self, span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId) {
@ -829,7 +829,7 @@ impl Handler {
}
#[track_caller]
pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) {
pub fn delay_span_bug(&self, span: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
self.inner.borrow_mut().delay_span_bug(span, msg)
}
@ -858,8 +858,8 @@ impl Handler {
self.inner.borrow_mut().fatal(msg)
}
pub fn err(&self, msg: &str) {
self.inner.borrow_mut().err(msg);
pub fn err(&self, msg: &str) -> ErrorGuaranteed {
self.inner.borrow_mut().err(msg)
}
pub fn warn(&self, msg: &str) {
@ -880,11 +880,15 @@ impl Handler {
self.inner.borrow().err_count()
}
pub fn has_errors(&self) -> bool {
self.inner.borrow().has_errors()
pub fn has_errors(&self) -> Option<ErrorGuaranteed> {
if self.inner.borrow().has_errors() { Some(ErrorGuaranteed(())) } else { None }
}
pub fn has_errors_or_lint_errors(&self) -> bool {
self.inner.borrow().has_errors_or_lint_errors()
pub fn has_errors_or_lint_errors(&self) -> Option<ErrorGuaranteed> {
if self.inner.borrow().has_errors_or_lint_errors() {
Some(ErrorGuaranteed(()))
} else {
None
}
}
pub fn has_errors_or_delayed_span_bugs(&self) -> bool {
self.inner.borrow().has_errors_or_delayed_span_bugs()
@ -915,13 +919,17 @@ impl Handler {
self.inner.borrow_mut().force_print_diagnostic(db)
}
pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) {
pub fn emit_diagnostic(&self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
self.inner.borrow_mut().emit_diagnostic(diagnostic)
}
fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into<MultiSpan>) {
fn emit_diag_at_span(
&self,
mut diag: Diagnostic,
sp: impl Into<MultiSpan>,
) -> Option<ErrorGuaranteed> {
let mut inner = self.inner.borrow_mut();
inner.emit_diagnostic(diag.set_span(sp));
inner.emit_diagnostic(diag.set_span(sp))
}
pub fn emit_artifact_notification(&self, path: &Path, artifact_type: &str) {
@ -990,13 +998,20 @@ impl HandlerInner {
}
/// Emit all stashed diagnostics.
fn emit_stashed_diagnostics(&mut self) {
fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
diags.iter().for_each(|diag| self.emit_diagnostic(diag));
let mut reported = None;
diags.iter().for_each(|diag| {
if diag.is_error() {
reported = Some(ErrorGuaranteed(()));
}
self.emit_diagnostic(diag);
});
reported
}
// FIXME(eddyb) this should ideally take `diagnostic` by value.
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) {
fn emit_diagnostic(&mut self, diagnostic: &Diagnostic) -> Option<ErrorGuaranteed> {
if diagnostic.level == Level::DelayedBug {
// FIXME(eddyb) this should check for `has_errors` and stop pushing
// once *any* errors were emitted (and truncate `delayed_span_bugs`
@ -1005,7 +1020,7 @@ impl HandlerInner {
self.delayed_span_bugs.push(diagnostic.clone());
if !self.flags.report_delayed_bugs {
return;
return Some(ErrorGuaranteed::unchecked_claim_error_was_emitted());
}
}
@ -1020,7 +1035,7 @@ impl HandlerInner {
if diagnostic.has_future_breakage() {
(*TRACK_DIAGNOSTICS)(diagnostic);
}
return;
return None;
}
// The `LintExpectationId` can be stable or unstable depending on when it was created.
@ -1029,16 +1044,16 @@ impl HandlerInner {
// a stable one by the `LintLevelsBuilder`.
if let Level::Expect(LintExpectationId::Unstable { .. }) = diagnostic.level {
self.unstable_expect_diagnostics.push(diagnostic.clone());
return;
return None;
}
(*TRACK_DIAGNOSTICS)(diagnostic);
if let Level::Expect(expectation_id) = diagnostic.level {
self.fulfilled_expectations.insert(expectation_id);
return;
return None;
} else if diagnostic.level == Allow {
return;
return None;
}
if let Some(ref code) = diagnostic.code {
@ -1068,8 +1083,12 @@ impl HandlerInner {
} else {
self.bump_err_count();
}
Some(ErrorGuaranteed::unchecked_claim_error_was_emitted())
} else {
self.bump_warn_count();
None
}
}
@ -1191,7 +1210,7 @@ impl HandlerInner {
}
#[track_caller]
fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) {
fn delay_span_bug(&mut self, sp: impl Into<MultiSpan>, msg: &str) -> ErrorGuaranteed {
// This is technically `self.treat_err_as_bug()` but `delay_span_bug` is called before
// incrementing `err_count` by one, so we need to +1 the comparing.
// FIXME: Would be nice to increment err_count in a more coherent way.
@ -1202,7 +1221,7 @@ impl HandlerInner {
let mut diagnostic = Diagnostic::new(Level::DelayedBug, msg);
diagnostic.set_span(sp.into());
diagnostic.note(&format!("delayed at {}", std::panic::Location::caller()));
self.emit_diagnostic(&diagnostic)
self.emit_diagnostic(&diagnostic).unwrap()
}
// FIXME(eddyb) note the comment inside `impl Drop for HandlerInner`, that's
@ -1221,20 +1240,20 @@ impl HandlerInner {
}
fn fatal(&mut self, msg: &str) -> FatalError {
self.emit_error(Fatal, msg);
self.emit(Fatal, msg);
FatalError
}
fn err(&mut self, msg: &str) {
self.emit_error(Error { lint: false }, msg);
fn err(&mut self, msg: &str) -> ErrorGuaranteed {
self.emit(Error { lint: false }, msg)
}
/// Emit an error; level should be `Error` or `Fatal`.
fn emit_error(&mut self, level: Level, msg: &str) {
fn emit(&mut self, level: Level, msg: &str) -> ErrorGuaranteed {
if self.treat_err_as_bug() {
self.bug(msg);
}
self.emit_diagnostic(&Diagnostic::new(level, msg));
self.emit_diagnostic(&Diagnostic::new(level, msg)).unwrap()
}
fn bug(&mut self, msg: &str) -> ! {
@ -1433,9 +1452,17 @@ pub fn add_elided_lifetime_in_path_suggestion(
);
}
// Useful type to use with `Result<>` indicate that an error has already
// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq)]
pub struct ErrorGuaranteed;
/// Useful type to use with `Result<>` indicate that an error has already
/// been reported to the user, so no need to continue checking.
#[derive(Clone, Copy, Debug, Encodable, Decodable, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct ErrorGuaranteed(());
impl ErrorGuaranteed {
/// To be used only if you really know what you are doing... ideally, we would find a way to
/// eliminate all calls to this method.
pub fn unchecked_claim_error_was_emitted() -> Self {
ErrorGuaranteed(())
}
}
rustc_data_structures::impl_stable_hash_via_hash!(ErrorGuaranteed);