diff options
| author | bors <bors@rust-lang.org> | 2022-03-28 11:08:23 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-03-28 11:08:23 +0000 |
| commit | 0e4524e5b4a9c5656fef69f532f96eb9959a1803 (patch) | |
| tree | f3b255fe605208ee5eafc4a41541eeada8a9e807 /compiler/rustc_errors/src | |
| parent | b3e46a9763d86a1681ddaaf0e60ce537302b9c92 (diff) | |
| parent | 928388bad20572e9ffa575319bb6d3b636bcdc69 (diff) | |
| download | rust-0e4524e5b4a9c5656fef69f532f96eb9959a1803.tar.gz rust-0e4524e5b4a9c5656fef69f532f96eb9959a1803.zip | |
Auto merge of #94789 - compiler-errors:fatal-never, r=eddyb
Make fatal DiagnosticBuilder yield `!` Fatal errors should really be fatal, so emitting them should cause us to exit at the same time. Fine with just throwing away these changes if they're not worthwhile. Also, maybe we want to use an uninhabited enum instead of `!`. r? `@eddyb` who has been working on `DiagnosticBuilder` stuff, feel free to reassign.
Diffstat (limited to 'compiler/rustc_errors/src')
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_builder.rs | 39 | ||||
| -rw-r--r-- | compiler/rustc_errors/src/lib.rs | 9 |
2 files changed, 44 insertions, 4 deletions
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index 088f6091528..853243ef3f0 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -198,6 +198,45 @@ impl EmissionGuarantee for () { } } +impl<'a> DiagnosticBuilder<'a, !> { + /// Convenience function for internal use, clients should use one of the + /// `struct_*` methods on [`Handler`]. + crate fn new_fatal(handler: &'a Handler, message: &str) -> Self { + let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message); + Self::new_diagnostic_fatal(handler, diagnostic) + } + + /// Creates a new `DiagnosticBuilder` with an already constructed + /// diagnostic. + crate fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self { + debug!("Created new diagnostic"); + Self { + inner: DiagnosticBuilderInner { + state: DiagnosticBuilderState::Emittable(handler), + diagnostic: Box::new(diagnostic), + }, + _marker: PhantomData, + } + } +} + +impl EmissionGuarantee for ! { + fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self { + match db.inner.state { + // First `.emit()` call, the `&Handler` is still available. + DiagnosticBuilderState::Emittable(handler) => { + db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation; + + handler.emit_diagnostic(&mut db.inner.diagnostic); + } + // `.emit()` was previously called, disallowed from repeating it. + DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {} + } + // Then fatally error, returning `!` + crate::FatalError.raise() + } +} + /// In general, the `DiagnosticBuilder` uses deref to allow access to /// the fields and methods of the embedded `diagnostic` in a /// transparent way. *However,* many of the methods are intended to diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 2f2f6ed1a5a..ec00910ec8b 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -8,6 +8,7 @@ #![feature(backtrace)] #![feature(if_let_guard)] #![feature(let_else)] +#![feature(never_type)] #![feature(nll)] #![feature(adt_const_params)] #![allow(incomplete_features)] @@ -758,7 +759,7 @@ impl Handler { &self, span: impl Into<MultiSpan>, msg: &str, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_, !> { let mut result = self.struct_fatal(msg); result.set_span(span); result @@ -770,15 +771,15 @@ impl Handler { span: impl Into<MultiSpan>, msg: &str, code: DiagnosticId, - ) -> DiagnosticBuilder<'_, ErrorGuaranteed> { + ) -> DiagnosticBuilder<'_, !> { let mut result = self.struct_span_fatal(span, msg); result.code(code); result } /// Construct a builder at the `Error` level with the `msg`. - pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, ErrorGuaranteed> { - DiagnosticBuilder::new_guaranteeing_error::<{ Level::Fatal }>(self, msg) + pub fn struct_fatal(&self, msg: &str) -> DiagnosticBuilder<'_, !> { + DiagnosticBuilder::new_fatal(self, msg) } /// Construct a builder at the `Help` level with the `msg`. |
