diff options
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`. |
