From a2bea9990ed3a316c89d2826ca271121415124ae Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Sat, 17 Aug 2024 11:55:35 -0600 Subject: [PATCH 1/2] feat(Diagnostic): implement `Diagnostic` for `Infallible` --- src/diagnostic_impls.rs | 59 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + 2 files changed, 60 insertions(+) create mode 100644 src/diagnostic_impls.rs diff --git a/src/diagnostic_impls.rs b/src/diagnostic_impls.rs new file mode 100644 index 0000000..c13dc93 --- /dev/null +++ b/src/diagnostic_impls.rs @@ -0,0 +1,59 @@ +/*! +Default trait implementations for [`Diagnostic`]. +*/ + +use std::{convert::Infallible, fmt::Display, hint::unreachable_unchecked}; + +use crate::{Diagnostic, LabeledSpan, Severity, SourceCode}; + +// Since all trait methods for [`Diagnostic`] take a reference to `self`, there must be an instance of `Self`. +// However, since an instance of [`Infallible`] can never be constructed, these methods can never be called. +// Therefore, these methods are unreachable, and can be safely optimized away by the compiler. +#[allow(clippy::undocumented_unsafe_blocks)] +impl Diagnostic for Infallible { + fn code<'a>(&'a self) -> Option> { + unsafe { unreachable_unchecked() } + } + + fn severity(&self) -> Option { + unsafe { unreachable_unchecked() } + } + + fn help<'a>(&'a self) -> Option> { + unsafe { unreachable_unchecked() } + } + + fn url<'a>(&'a self) -> Option> { + unsafe { unreachable_unchecked() } + } + + fn source_code(&self) -> Option<&dyn SourceCode> { + unsafe { unreachable_unchecked() } + } + + fn labels(&self) -> Option + '_>> { + unsafe { unreachable_unchecked() } + } + + fn related<'a>(&'a self) -> Option + 'a>> { + unsafe { unreachable_unchecked() } + } + + fn diagnostic_source(&self) -> Option<&dyn Diagnostic> { + unsafe { unreachable_unchecked() } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::Report; + + /// Test that [`Infallible`] implements [`Diagnostic`] by seeing if a function that's generic over `Diagnostic` + /// will accept `Infallible` as a type parameter. + #[test] + fn infallible() { + let _ = Report::new::; + } +} diff --git a/src/lib.rs b/src/lib.rs index a42f4fa..cbb28bf 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -788,6 +788,7 @@ pub use protocol::*; mod chain; mod diagnostic_chain; +mod diagnostic_impls; mod error; mod eyreish; #[cfg(feature = "fancy-base")] From 35d0f077c1afca8eaea792e19e1268945f71fb89 Mon Sep 17 00:00:00 2001 From: Cass Fridkin Date: Mon, 19 Aug 2024 21:47:30 -0600 Subject: [PATCH 2/2] fix(Diagnostic): remove usage of unsafe code from `Infallible` impl --- src/diagnostic_impls.rs | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/src/diagnostic_impls.rs b/src/diagnostic_impls.rs index c13dc93..aebe56b 100644 --- a/src/diagnostic_impls.rs +++ b/src/diagnostic_impls.rs @@ -2,45 +2,41 @@ Default trait implementations for [`Diagnostic`]. */ -use std::{convert::Infallible, fmt::Display, hint::unreachable_unchecked}; +use std::{convert::Infallible, fmt::Display}; use crate::{Diagnostic, LabeledSpan, Severity, SourceCode}; -// Since all trait methods for [`Diagnostic`] take a reference to `self`, there must be an instance of `Self`. -// However, since an instance of [`Infallible`] can never be constructed, these methods can never be called. -// Therefore, these methods are unreachable, and can be safely optimized away by the compiler. -#[allow(clippy::undocumented_unsafe_blocks)] impl Diagnostic for Infallible { fn code<'a>(&'a self) -> Option> { - unsafe { unreachable_unchecked() } + match *self {} } fn severity(&self) -> Option { - unsafe { unreachable_unchecked() } + match *self {} } fn help<'a>(&'a self) -> Option> { - unsafe { unreachable_unchecked() } + match *self {} } fn url<'a>(&'a self) -> Option> { - unsafe { unreachable_unchecked() } + match *self {} } fn source_code(&self) -> Option<&dyn SourceCode> { - unsafe { unreachable_unchecked() } + match *self {} } fn labels(&self) -> Option + '_>> { - unsafe { unreachable_unchecked() } + match *self {} } fn related<'a>(&'a self) -> Option + 'a>> { - unsafe { unreachable_unchecked() } + match *self {} } fn diagnostic_source(&self) -> Option<&dyn Diagnostic> { - unsafe { unreachable_unchecked() } + match *self {} } }