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:
parent
461e807801
commit
bb8d4307eb
104 changed files with 705 additions and 550 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue