Skip to content

Commit

Permalink
feat!(blanket_impls): impl Diagnostic for &T and Box<T>
Browse files Browse the repository at this point in the history
Brings things in line with best practices as described in "Rust for
Rustaceans" when it comes to "Ergonomic Trait Implementations" in Chapter
3. Practically means that people can pass more types to any functions
taking either `dyn Diagnostic` or `impl Diagnostic`.

BREAKING CHANGE: Added blanket impls may overlap with manual user impls.
If these impls are just hacks to achieve the same as the blanket ones do,
then they can simply be removed. If the impls for `T` and `&T` differ
semantically, then the user would need to employ the newtype pattern to
avoid overlap.
  • Loading branch information
TheLostLambda committed Apr 23, 2024
1 parent ea4296d commit a8cb8fa
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
42 changes: 42 additions & 0 deletions src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,48 @@ pub trait Diagnostic: std::error::Error {
}
}

macro_rules! blanket_ref_impls {
($($ref_type:ty),+ $(,)?) => {
$(
impl<T: Diagnostic> Diagnostic for $ref_type {
fn code<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).code()
}

fn severity(&self) -> Option<Severity> {
(**self).severity()
}

fn help<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).help()
}

fn url<'a>(&'a self) -> Option<Box<dyn Display + 'a>> {
(**self).url()
}

fn source_code(&self) -> Option<&dyn SourceCode> {
(**self).source_code()
}

fn labels(&self) -> Option<Box<dyn Iterator<Item = LabeledSpan> + '_>> {
(**self).labels()
}

fn related<'a>(&'a self) -> Option<Box<dyn Iterator<Item = &'a dyn Diagnostic> + 'a>> {
(**self).related()
}

fn diagnostic_source(&self) -> Option<&dyn Diagnostic> {
(**self).diagnostic_source()
}
}
)+
};
}

blanket_ref_impls!(&T, Box<T>);

macro_rules! box_error_impls {
($($box_type:ty),*) => {
$(
Expand Down
13 changes: 13 additions & 0 deletions tests/test_blanket.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
use miette::{Diagnostic, MietteDiagnostic};

fn assert_diagnostic<T: Diagnostic>() {}

#[test]
fn test_ref() {
assert_diagnostic::<&MietteDiagnostic>()
}

#[test]
fn test_box() {
assert_diagnostic::<Box<MietteDiagnostic>>()
}

0 comments on commit a8cb8fa

Please sign in to comment.