diff --git a/examples/simple.rs b/examples/simple.rs new file mode 100644 index 00000000..3753aae2 --- /dev/null +++ b/examples/simple.rs @@ -0,0 +1,22 @@ +use std::io; + +#[derive(Debug, snafu::Snafu)] +enum OuterError { + #[snafu(display("Get failed"))] + Get { source: GetError }, +} + +#[derive(Debug, snafu::Snafu)] +enum GetError { + #[snafu(display("IO failure"))] + Io { source: io::Error }, +} + +fn main() { + let err = io::Error::new(io::ErrorKind::BrokenPipe, "pipe is broken"); + let err = GetError::Io { source: err }; + let err = OuterError::Get { source: err }; + + println!("display normal: {err}"); + println!("display alt : {err:#}"); +} diff --git a/snafu-derive/src/lib.rs b/snafu-derive/src/lib.rs index b3b8b1b5..2a7fa44b 100644 --- a/snafu-derive/src/lib.rs +++ b/snafu-derive/src/lib.rs @@ -1796,6 +1796,7 @@ impl<'a> quote::ToTokens for DisplayImpl<'a> { .collect(); let display = Display { + crate_root: &self.0.crate_root, arms: &arms, original_generics: &self.0.provided_generics_without_defaults(), parameterized_error_name: &self.0.parameterized_name(), @@ -1989,6 +1990,7 @@ impl NamedStructInfo { let arm = quote! { #arm }; let display_impl = Display { + crate_root: &self.crate_root, arms: &[arm], original_generics: &original_generics, parameterized_error_name: ¶meterized_struct_name, diff --git a/snafu-derive/src/shared.rs b/snafu-derive/src/shared.rs index 0a668ad8..c860e6a2 100644 --- a/snafu-derive/src/shared.rs +++ b/snafu-derive/src/shared.rs @@ -461,6 +461,7 @@ pub mod display { const FORMATTER_ARG: StaticIdent = StaticIdent("__snafu_display_formatter"); pub(crate) struct Display<'a> { + pub(crate) crate_root: &'a dyn ToTokens, pub(crate) arms: &'a [TokenStream], pub(crate) original_generics: &'a [TokenStream], pub(crate) parameterized_error_name: &'a dyn ToTokens, @@ -470,6 +471,7 @@ pub mod display { impl ToTokens for Display<'_> { fn to_tokens(&self, stream: &mut TokenStream) { let Self { + crate_root, arms, original_generics, parameterized_error_name, @@ -487,6 +489,15 @@ pub mod display { match *self { #(#arms),* } + + if #FORMATTER_ARG.alternate() { + let chain = #crate_root::ChainCompat::new(self).skip(1); + for item in chain { + write!(#FORMATTER_ARG, ": {item}")?; + } + } + + Ok(()) } } }; @@ -561,7 +572,7 @@ pub mod display { let match_arm = quote! { #pattern_ident { #(ref #field_names),* } => { - write!(#FORMATTER_ARG, #format, #shorthand_assignments) + write!(#FORMATTER_ARG, #format, #shorthand_assignments)?; } };