zkat / miette

Fancy extension for std::error::Error with pretty, detailed diagnostic printing.
https://docs.rs/miette
Apache License 2.0
1.98k stars 113 forks source link

feat!(blanket_impls): impl `Diagnostic` for &T and Box<T> #367

Open TheLostLambda opened 5 months ago

TheLostLambda commented 5 months ago

Partially addresses #366

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.

TheLostLambda commented 5 months ago

Uh oh, this make have broken more than I thought... Let's hold off for the moment :sweat_smile:

EDIT: I think it's fine... Turns out typoing unwrap() for unwrap_err() really does make a difference...

TheLostLambda commented 5 months ago

Confirmed to be working well for me!

This let me go from:

use miette::Diagnostic;
use std::fmt::Debug;

pub trait UnwrapDiagnostic<E> {
    fn unwrap_diagnostic(self) -> E;
}

impl<T: Debug, E: Diagnostic> UnwrapDiagnostic<E> for Result<T, E> {
    fn unwrap_diagnostic(self) -> E {
        self.unwrap_err()
    }
}

impl<T: Debug, E: Diagnostic> UnwrapDiagnostic<E> for Result<T, Box<E>> {
    fn unwrap_diagnostic(self) -> E {
        *self.unwrap_err()
    }
}

macro_rules! assert_miette_snapshot {
    ($diag:expr) => {{
        use insta::{with_settings, assert_snapshot};
        use miette::{GraphicalReportHandler, GraphicalTheme};
        use crate::testing_tools::UnwrapDiagnostic;

        let mut out = String::new();
        GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
            .with_width(80)
            .render_report(&mut out, &$diag.unwrap_diagnostic())
            .unwrap();
        with_settings!({
            description => stringify!($diag)
        }, {
            assert_snapshot!(out);
        });
    }};
}

pub(crate) use assert_miette_snapshot;

To just:

macro_rules! assert_miette_snapshot {
    ($diag:expr) => {{
        use insta::{with_settings, assert_snapshot};
        use miette::{GraphicalReportHandler, GraphicalTheme};

        let mut out = String::new();
        GraphicalReportHandler::new_themed(GraphicalTheme::unicode_nocolor())
            .with_width(80)
            .render_report(&mut out, &$diag.unwrap_err())
            .unwrap();
        with_settings!({
            description => stringify!($diag)
        }, {
            assert_snapshot!(out);
        });
    }};
}

pub(crate) use assert_miette_snapshot;