Skip to content

Commit

Permalink
Reject enums with attribute macros
Browse files Browse the repository at this point in the history
This patch checks if there is any top level attribute macro expansion,
and if there it, we report it as an error.

fixes: #1

Signed-off-by: Ahmed Abdelraoof <ahmed.abdelraoof@huawei.com>
  • Loading branch information
oddcoder committed Aug 19, 2024
1 parent 1695877 commit 7d84cb2
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 0 deletions.
15 changes: 15 additions & 0 deletions safe-discriminant-derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,28 @@ fn validate_all_variants(variants: impl Iterator<Item = Variant>) -> Result<()>
.unwrap_or(Ok(()))
}

/// Returns true if there is any #[x] where x is not `repr`
/// returns false otherwise.
fn contains_attribute_macros(attrs: &[Attribute]) -> bool {
attrs.iter().any(|attr| !attr.path().is_ident("repr"))
}
/// Constructs Discriminant trait implementation for given enum.
/// Returns error in one of two cases:
/// 1- No valid `#[repr(x)]` is found.
/// 2- Any of the enum variants is missing discriminant.
/// 3- contains any additional top level attribute macros.
fn derive_discriminant_inner(tagged_enum: ItemEnum) -> Result<TokenStream> {
let prim = get_enum_repr_prim(&tagged_enum.attrs, tagged_enum.ident.span())?;
validate_all_variants(tagged_enum.variants.into_iter())?;
if contains_attribute_macros(&tagged_enum.attrs) {
return Err(Error::new(
tagged_enum.ident.span(),
concat!(
"Discriminant is not compatiable with any top ",
"level `#[attr]` except `#[repr(_)]`."
),
));
}
let name = tagged_enum.ident;
let generics = tagged_enum.generics;
let derive = quote! {
Expand Down
12 changes: 12 additions & 0 deletions safe-discriminant/tests/fail/remove_repr_disc1.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use safe_discriminant::Discriminant;
use safe_discriminant_derive::remove_repr;

#[remove_repr]
#[derive(Discriminant)]
#[repr(u8)]
pub enum Foo {
A = 0,
B = 1,
}

fn main() {}
5 changes: 5 additions & 0 deletions safe-discriminant/tests/fail/remove_repr_disc1.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: Discriminant requires a `#[repr(x)] where x is one of u8, i8, u16, i16, u32, i32, u64, i64, u128, i128.
--> tests/fail/remove_repr_disc1.rs:7:10
|
7 | pub enum Foo {
| ^^^
12 changes: 12 additions & 0 deletions safe-discriminant/tests/fail/remove_repr_disc2.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use safe_discriminant::Discriminant;
use safe_discriminant_derive::remove_repr;

#[derive(Discriminant)]
#[remove_repr]
#[repr(u8)]
pub enum Foo {
A = 0,
B = 1,
}

fn main() {}
5 changes: 5 additions & 0 deletions safe-discriminant/tests/fail/remove_repr_disc2.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
error: Discriminant is not compatiable with any top level `#[attr]` except `#[repr(_)]`.
--> tests/fail/remove_repr_disc2.rs:7:10
|
7 | pub enum Foo {
| ^^^

0 comments on commit 7d84cb2

Please sign in to comment.