diff options
| author | Nicholas Nethercote <n.nethercote@gmail.com> | 2023-12-18 16:31:15 +1100 |
|---|---|---|
| committer | Nicholas Nethercote <n.nethercote@gmail.com> | 2023-12-19 09:52:02 +1100 |
| commit | f5459201e0f4f751bc30d890107942774ebf68fb (patch) | |
| tree | 8679ed5ff867a3baedd5bd9edc6dec53e1725149 /compiler/rustc_errors/src | |
| parent | 3a5f28f7e821a2325e9dbdb4ff40cd9ff417f065 (diff) | |
| download | rust-f5459201e0f4f751bc30d890107942774ebf68fb.tar.gz rust-f5459201e0f4f751bc30d890107942774ebf68fb.zip | |
Add `EmitResult` associated type to `EmissionGuarantee`.
This lets different error levels share the same return type from `emit_*`. - A lot of inconsistencies in the `DiagCtxt` API are removed. - `Noted` is removed. - `FatalAbort` is introduced for fatal errors (abort via `raise`), replacing the `EmissionGuarantee` impl for `!`. - `Bug` is renamed `BugAbort` (to avoid clashing with `Level::Bug` and to mirror `FatalAbort`), and modified to work in the new way with bug errors (abort via panic). - Various diagnostic creators and emitters updated to the new, better signatures. Note that `DiagCtxt::bug` no longer needs to call `panic_any`, because `emit` handles that. Also shorten the obnoxiously long `diagnostic_builder_emit_producing_guarantee` name.
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 64 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 36 |
2 files changed, 46 insertions, 54 deletions
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 59e5c1f352f..1c83250e017 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -101,11 +101,15 @@ rustc_data_structures::static_assert_size!( /// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee" /// (or "proof") token that the emission happened. pub trait EmissionGuarantee: Sized { + /// This exists so that bugs and fatal errors can both result in `!` (an + /// abort) when emitted, but have different aborting behaviour. + type EmitResult = Self; + /// Implementation of `DiagnosticBuilder::emit`, fully controlled by each /// `impl` of `EmissionGuarantee`, to make it impossible to create a value - /// of `Self` without actually performing the emission. + /// of `Self::EmitResult` without actually performing the emission. #[track_caller] - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self; + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult; } impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { @@ -119,7 +123,7 @@ impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. impl EmissionGuarantee for ErrorGuaranteed { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -160,7 +164,7 @@ impl EmissionGuarantee for ErrorGuaranteed { // FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well? impl EmissionGuarantee for () { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -174,34 +178,15 @@ impl EmissionGuarantee for () { } } -/// Marker type which enables implementation of `create_note` and `emit_note` functions for -/// note-without-error struct diagnostics. -#[derive(Copy, Clone)] -pub struct Noted; - -impl EmissionGuarantee for Noted { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { - match db.inner.state { - // First `.emit()` call, the `&DiagCtxt` is still available. - DiagnosticBuilderState::Emittable(dcx) => { - db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; - dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic); - } - // `.emit()` was previously called, disallowed from repeating it. - DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} - } - - Noted - } -} - /// Marker type which enables implementation of `create_bug` and `emit_bug` functions for -/// bug struct diagnostics. +/// bug diagnostics. #[derive(Copy, Clone)] -pub struct Bug; +pub struct BugAbort; + +impl EmissionGuarantee for BugAbort { + type EmitResult = !; -impl EmissionGuarantee for Bug { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -217,8 +202,15 @@ impl EmissionGuarantee for Bug { } } -impl EmissionGuarantee for ! { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { +/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for +/// fatal diagnostics. +#[derive(Copy, Clone)] +pub struct FatalAbort; + +impl EmissionGuarantee for FatalAbort { + type EmitResult = !; + + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -235,7 +227,7 @@ impl EmissionGuarantee for ! { } impl EmissionGuarantee for rustc_span::fatal_error::FatalError { - fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { match db.inner.state { // First `.emit()` call, the `&DiagCtxt` is still available. DiagnosticBuilderState::Emittable(dcx) => { @@ -313,8 +305,8 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// but there are various places that rely on continuing to use `self` /// after calling `emit`. #[track_caller] - pub fn emit(&mut self) -> G { - G::diagnostic_builder_emit_producing_guarantee(self) + pub fn emit(&mut self) -> G::EmitResult { + G::emit_producing_guarantee(self) } /// Emit the diagnostic unless `delay` is true, @@ -322,7 +314,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// /// See `emit` and `delay_as_bug` for details. #[track_caller] - pub fn emit_unless(&mut self, delay: bool) -> G { + pub fn emit_unless(&mut self, delay: bool) -> G::EmitResult { if delay { self.downgrade_to_delayed_bug(); } @@ -409,7 +401,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { /// In the meantime, though, callsites are required to deal with the "bug" /// locally in whichever way makes the most sense. #[track_caller] - pub fn delay_as_bug(&mut self) -> G { + pub fn delay_as_bug(&mut self) -> G::EmitResult { self.downgrade_to_delayed_bug(); self.emit() } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index a86a12506ad..93813458718 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -6,6 +6,7 @@ #![doc(rust_logo)] #![feature(rustdoc_internals)] #![feature(array_windows)] +#![feature(associated_type_defaults)] #![feature(extract_if)] #![feature(if_let_guard)] #![feature(let_chains)] @@ -401,7 +402,7 @@ pub use diagnostic::{ AddToDiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId, DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic, }; -pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, Noted}; +pub use diagnostic_builder::{BugAbort, DiagnosticBuilder, EmissionGuarantee, FatalAbort}; pub use diagnostic_impls::{ DiagnosticArgFromDisplay, DiagnosticSymbolList, ExpectedLifetimeParameter, IndicateAnonymousLifetime, InvalidFlushedDelayedDiagnosticLevel, LabelKind, @@ -907,7 +908,7 @@ impl DiagCtxt { &self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_fatal(msg); result.set_span(span); result @@ -921,7 +922,7 @@ impl DiagCtxt { span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, !> { + ) -> DiagnosticBuilder<'_, FatalAbort> { let mut result = self.struct_span_fatal(span, msg); result.code(code); result @@ -930,7 +931,10 @@ impl DiagCtxt { /// Construct a builder at the `Fatal` level with the `msg`. #[rustc_lint_diagnostics] #[track_caller] - pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> { + pub fn struct_fatal( + &self, + msg: impl Into<DiagnosticMessage>, + ) -> DiagnosticBuilder<'_, FatalAbort> { DiagnosticBuilder::new(self, Level::Fatal, msg) } @@ -1101,8 +1105,7 @@ impl DiagCtxt { } pub fn bug(&self, msg: impl Into<DiagnosticMessage>) -> ! { - DiagnosticBuilder::<diagnostic_builder::Bug>::new(self, Bug, msg).emit(); - panic::panic_any(ExplicitBug); + DiagnosticBuilder::<BugAbort>::new(self, Bug, msg).emit() } #[inline] @@ -1294,37 +1297,34 @@ impl DiagCtxt { pub fn create_fatal<'a>( &'a self, - fatal: impl IntoDiagnostic<'a, !>, - ) -> DiagnosticBuilder<'a, !> { + fatal: impl IntoDiagnostic<'a, FatalAbort>, + ) -> DiagnosticBuilder<'a, FatalAbort> { fatal.into_diagnostic(self, Level::Fatal) } - pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, !>) -> ! { + pub fn emit_fatal<'a>(&'a self, fatal: impl IntoDiagnostic<'a, FatalAbort>) -> ! { self.create_fatal(fatal).emit() } pub fn create_bug<'a>( &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> DiagnosticBuilder<'a, diagnostic_builder::Bug> { + bug: impl IntoDiagnostic<'a, BugAbort>, + ) -> DiagnosticBuilder<'a, BugAbort> { bug.into_diagnostic(self, Level::Bug) } - pub fn emit_bug<'a>( - &'a self, - bug: impl IntoDiagnostic<'a, diagnostic_builder::Bug>, - ) -> diagnostic_builder::Bug { + pub fn emit_bug<'a>(&'a self, bug: impl IntoDiagnostic<'a, BugAbort>) -> ! { self.create_bug(bug).emit() } - pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, Noted>) -> Noted { + pub fn emit_note<'a>(&'a self, note: impl IntoDiagnostic<'a, ()>) { self.create_note(note).emit() } pub fn create_note<'a>( &'a self, - note: impl IntoDiagnostic<'a, Noted>, - ) -> DiagnosticBuilder<'a, Noted> { + note: impl IntoDiagnostic<'a, ()>, + ) -> DiagnosticBuilder<'a, ()> { note.into_diagnostic(self, Level::Note) } |
