diff --git a/impl/src/error.rs b/impl/src/error.rs index 5b69fe57..eb288f43 100644 --- a/impl/src/error.rs +++ b/impl/src/error.rs @@ -1,4 +1,4 @@ -use proc_macro2::TokenStream; +use proc_macro2::{Span, TokenStream}; use quote::quote; use syn::{spanned::Spanned as _, Error, Result}; @@ -390,7 +390,12 @@ fn parse_fields_impl<'input, 'state, P>( where P: Fn(&str, &syn::Field, usize) -> bool, { - let MultiFieldData { fields, infos, .. } = state.enabled_fields_data(); + let MultiFieldData { + fields, + infos, + variant_info, + .. + } = state.enabled_fields_data(); let iter = fields .iter() @@ -418,6 +423,11 @@ where if let Some((index, _, _)) = source { parsed_fields.source = Some(index); + } else if variant_info.forward { + return Err(syn::Error::new( + Span::call_site(), + "`#[error(forward)]` cannot be used when an error has no source", + )); } if let Some((index, _, _)) = backtrace { diff --git a/tests/compile_fail/error/forward_no_source_enum.rs b/tests/compile_fail/error/forward_no_source_enum.rs new file mode 100644 index 00000000..4d5e81d5 --- /dev/null +++ b/tests/compile_fail/error/forward_no_source_enum.rs @@ -0,0 +1,18 @@ +use derive_more::Error; + +#[derive(Debug, Error)] +#[error(forward)] +enum Foo { + Bar, + Baz { + source: Box<dyn Error + Send + 'static>, + }, +} + +impl ::core::fmt::Display for Foo { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(f, "") + } +} + +fn main() {} diff --git a/tests/compile_fail/error/forward_no_source_enum.stderr b/tests/compile_fail/error/forward_no_source_enum.stderr new file mode 100644 index 00000000..2e0d36de --- /dev/null +++ b/tests/compile_fail/error/forward_no_source_enum.stderr @@ -0,0 +1,7 @@ +error: `#[error(forward)]` cannot be used when an error has no source + --> tests/compile_fail/error/forward_no_source_enum.rs:3:17 + | +3 | #[derive(Debug, Error)] + | ^^^^^ + | + = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compile_fail/error/forward_no_source_struct.rs b/tests/compile_fail/error/forward_no_source_struct.rs new file mode 100644 index 00000000..f5f359b5 --- /dev/null +++ b/tests/compile_fail/error/forward_no_source_struct.rs @@ -0,0 +1,13 @@ +use derive_more::Error; + +#[derive(Debug, Error)] +#[error(forward)] +struct Foo; + +impl ::core::fmt::Display for Foo { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(f, "") + } +} + +fn main() {} diff --git a/tests/compile_fail/error/forward_no_source_struct.stderr b/tests/compile_fail/error/forward_no_source_struct.stderr new file mode 100644 index 00000000..9743137d --- /dev/null +++ b/tests/compile_fail/error/forward_no_source_struct.stderr @@ -0,0 +1,7 @@ +error: `#[error(forward)]` cannot be used when an error has no source + --> tests/compile_fail/error/forward_no_source_struct.rs:3:17 + | +3 | #[derive(Debug, Error)] + | ^^^^^ + | + = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/compile_fail/error/forward_no_source_variant.rs b/tests/compile_fail/error/forward_no_source_variant.rs new file mode 100644 index 00000000..8830cc2a --- /dev/null +++ b/tests/compile_fail/error/forward_no_source_variant.rs @@ -0,0 +1,19 @@ +use derive_more::Error; + +#[derive(Debug, Error)] +enum Foo { + #[error(forward)] + Bar, + #[error(forward)] + Baz { + source: Box<dyn Error + Send + 'static>, + }, +} + +impl ::core::fmt::Display for Foo { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + write!(f, "") + } +} + +fn main() {} diff --git a/tests/compile_fail/error/forward_no_source_variant.stderr b/tests/compile_fail/error/forward_no_source_variant.stderr new file mode 100644 index 00000000..e30f9d03 --- /dev/null +++ b/tests/compile_fail/error/forward_no_source_variant.stderr @@ -0,0 +1,7 @@ +error: `#[error(forward)]` cannot be used when an error has no source + --> tests/compile_fail/error/forward_no_source_variant.rs:3:17 + | +3 | #[derive(Debug, Error)] + | ^^^^^ + | + = note: this error originates in the derive macro `Error` (in Nightly builds, run with -Z macro-backtrace for more info)