diff --git a/impl/src/valid.rs b/impl/src/valid.rs index 66eb727..517e246 100644 --- a/impl/src/valid.rs +++ b/impl/src/valid.rs @@ -159,6 +159,7 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> { let mut source_field = None; let mut backtrace_field = None; let mut first_implicit_field = None; + let mut backtrace_type_field = None; for field in fields { if let Some(from) = field.attrs.from { if from_field.is_some() { @@ -187,6 +188,15 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> { } backtrace_field = Some(field); } + if field.is_backtrace() { + if backtrace_type_field.is_some() { + return Err(Error::new_spanned( + field.original, + "duplicate field having type: `Backtrace`", + )); + } + backtrace_type_field = Some(field); + } if let Some(transparent) = field.attrs.transparent { return Err(Error::new_spanned( transparent.original, @@ -205,6 +215,14 @@ fn check_field_attrs(fields: &[Field]) -> Result<()> { )); } } + if let (Some(a), Some(b)) = (backtrace_field, backtrace_type_field) { + if a.member != b.member { + return Err(Error::new_spanned( + a.original, + "only one backtrace field is allowed; found field with #[backtrace] and field with type `Backtrace`", + )); + } + } if let Some(from_field) = from_field { let has_unexpected_fields = fields.iter().any(|field| { field.attrs.from.is_none() diff --git a/tests/ui/from-backtrace-backtrace.stderr b/tests/ui/from-backtrace-backtrace.stderr index 5c0b9a3..fdf7619 100644 --- a/tests/ui/from-backtrace-backtrace.stderr +++ b/tests/ui/from-backtrace-backtrace.stderr @@ -1,5 +1,7 @@ -error: deriving From requires no fields other than source and backtrace - --> tests/ui/from-backtrace-backtrace.rs:9:5 - | -9 | #[from] - | ^^^^^^^ +error: only one backtrace field is allowed; found field with #[backtrace] and field with type `Backtrace` + --> tests/ui/from-backtrace-backtrace.rs:9:5 + | +9 | / #[from] +10 | | #[backtrace] +11 | | std::io::Error, + | |__________________^