Factor out common emit_producing_guarantee code.

This commit is contained in:
Nicholas Nethercote 2023-12-18 17:02:37 +11:00
parent f5459201e0
commit 9ed87336b0

View File

@ -112,6 +112,22 @@ pub trait EmissionGuarantee: Sized {
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult; fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult;
} }
impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
/// Most `emit_producing_guarantee` functions use this as a starting point.
fn emit_producing_nothing(&mut self) {
match self.inner.state {
// First `.emit()` call, the `&DiagCtxt` is still available.
DiagnosticBuilderState::Emittable(dcx) => {
self.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
dcx.emit_diagnostic_without_consuming(&mut self.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
}
}
}
impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> { impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> {
/// Discard the guarantee `.emit()` would return, in favor of having the /// Discard the guarantee `.emit()` would return, in favor of having the
/// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there /// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there
@ -124,6 +140,7 @@ impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> {
// FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`.
impl EmissionGuarantee for ErrorGuaranteed { impl EmissionGuarantee for ErrorGuaranteed {
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
// Contrast this with `emit_producing_nothing`.
match db.inner.state { match db.inner.state {
// First `.emit()` call, the `&DiagCtxt` is still available. // First `.emit()` call, the `&DiagCtxt` is still available.
DiagnosticBuilderState::Emittable(dcx) => { DiagnosticBuilderState::Emittable(dcx) => {
@ -165,16 +182,7 @@ impl EmissionGuarantee for ErrorGuaranteed {
// FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well? // FIXME(eddyb) should there be a `Option<ErrorGuaranteed>` impl as well?
impl EmissionGuarantee for () { impl EmissionGuarantee for () {
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
match db.inner.state { db.emit_producing_nothing();
// 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 => {}
}
} }
} }
@ -187,17 +195,7 @@ impl EmissionGuarantee for BugAbort {
type EmitResult = !; type EmitResult = !;
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
match db.inner.state { db.emit_producing_nothing();
// 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 => {}
}
// Then panic. No need to return the marker type.
panic::panic_any(ExplicitBug); panic::panic_any(ExplicitBug);
} }
} }
@ -211,34 +209,14 @@ impl EmissionGuarantee for FatalAbort {
type EmitResult = !; type EmitResult = !;
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
match db.inner.state { db.emit_producing_nothing();
// 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 => {}
}
// Then fatally error, returning `!`
crate::FatalError.raise() crate::FatalError.raise()
} }
} }
impl EmissionGuarantee for rustc_span::fatal_error::FatalError { impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult { fn emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self::EmitResult {
match db.inner.state { db.emit_producing_nothing();
// 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 => {}
}
// Then fatally error..
rustc_span::fatal_error::FatalError rustc_span::fatal_error::FatalError
} }
} }