From bb8d4307eb723850e98bcb52d71d860a4aba220a Mon Sep 17 00:00:00 2001 From: mark Date: Sat, 22 Jan 2022 18:49:12 -0600 Subject: 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. --- compiler/rustc_errors/src/diagnostic_builder.rs | 6 +- compiler/rustc_errors/src/lib.rs | 95 ++++++++++++++++--------- 2 files changed, 64 insertions(+), 37 deletions(-) (limited to 'compiler/rustc_errors/src') diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 98b8b2a569e..72471638a96 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -128,7 +128,7 @@ impl EmissionGuarantee for ErrorGuaranteed { DiagnosticBuilderState::Emittable(handler) => { db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - handler.emit_diagnostic(&db.inner.diagnostic); + let guar = handler.emit_diagnostic(&db.inner.diagnostic); // Only allow a guarantee if the `level` wasn't switched to a // non-error - the field isn't `pub`, but the whole `Diagnostic` @@ -139,7 +139,7 @@ impl EmissionGuarantee for ErrorGuaranteed { from `DiagnosticBuilder`", db.inner.diagnostic.level, ); - ErrorGuaranteed + guar.unwrap() } // `.emit()` was previously called, disallowed from repeating it, // but can take advantage of the previous `.emit()`'s guarantee @@ -154,7 +154,7 @@ impl EmissionGuarantee for ErrorGuaranteed { became non-error ({:?}), after original `.emit()`", db.inner.diagnostic.level, ); - ErrorGuaranteed + ErrorGuaranteed::unchecked_claim_error_was_emitted() } } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 345247b0700..c719e4910ce 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -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 { + 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, msg: &str) { - self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span); + pub fn span_err(&self, span: impl Into, 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, msg: &str, code: DiagnosticId) { @@ -829,7 +829,7 @@ impl Handler { } #[track_caller] - pub fn delay_span_bug(&self, span: impl Into, msg: &str) { + pub fn delay_span_bug(&self, span: impl Into, 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 { + 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 { + 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 { self.inner.borrow_mut().emit_diagnostic(diagnostic) } - fn emit_diag_at_span(&self, mut diag: Diagnostic, sp: impl Into) { + fn emit_diag_at_span( + &self, + mut diag: Diagnostic, + sp: impl Into, + ) -> Option { 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 { let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::>(); - 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 { 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, msg: &str) { + fn delay_span_bug(&mut self, sp: impl Into, 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); -- cgit 1.4.1-3-g733a5