diem/diem · error
#[derive(NumVariants)] can only be used on an enum
Error message
#[derive(NumVariants)] can only be used on an enum
What it means
This is a proc-macro compile-time error from the `num-variants` derive crate. `#[derive(NumVariants)]` generates a constant counting the enum's variants, so it is only valid on enums; applying it to a struct or union makes `compute_num_variants` emit a `syn::Error` at the item's span.
Source
Thrown at crates/num-variants/src/lib.rs:53
let name = input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let num_variants = compute_num_variants(&input.data, input_span)?;
let expanded = quote! {
impl #impl_generics #name #ty_generics #where_clause {
/// The number of variants in this enum.
pub const #const_name: usize = #num_variants;
}
};
Ok(expanded)
}
/// Computes the number of variants for an enum.
fn compute_num_variants(data: &Data, span: Span) -> Result<usize> {
match data {
Data::Enum(data) => Ok(data.variants.len()),
Data::Struct(_) | Data::Union(_) => Err(Error::new(
span,
"#[derive(NumVariants)] can only be used on an enum",
)),
}
}
/// Computes the name of the constant.
fn compute_const_name(attrs: Vec<Attribute>) -> Result<Ident> {
let mut const_names: Vec<_> = attrs
.iter()
.filter(|attr| attr.path.is_ident("num_variants"))
.map(|attr| match attr.parse_meta() {
Ok(Meta::NameValue(MetaNameValue {
lit: Lit::Str(lit), ..
})) => Ok((attr.span(), lit.parse::<Ident>()?)),
_ => Err(Error::new(
attr.span(),
"must be of the form #[num_variants = \"FOO\"]",View on GitHub (pinned to fc4714a8ea)
Solutions
- Remove `#[derive(NumVariants)]` from the struct/union
- Move the derive to an enum if that was the intent
- Hand-write the constant instead of deriving it
Example fix
// before
#[derive(NumVariants)]
pub struct MyStruct { a: u8 }
// after
pub struct MyStruct { a: u8 } // derive removed; NumVariants only works on enums Defensive patterns
Strategy: type-guard
Validate before calling
// compile-time: only attach the derive to enums
enum MyEnum { A, B } Type guard
// Verify at the item site: the annotated item must be `enum ...`, not struct/union
Prevention
- Only apply NumVariants to enum declarations
- Review derive lists when refactoring enums into structs
- Let CI compiler errors catch misuse early
When it happens
Trigger: Adding `#[derive(NumVariants)]` to a `struct` or `union` and compiling the crate.
Common situations: Copy-pasting the derive onto a struct by accident; refactoring an enum into a struct while leaving the derive in place.
Related errors
- Incorrect macro input
- #[derive(ValidCryptoMaterial)] is only defined for enums
- #[derive(PublicKey)] is only defined for enums
- #[derive(PrivateKey)] is only defined for enums
- Could not find attribute {}
AI-assisted analysis of diem/diem@fc4714a8ea (2026-09-04).
Data as JSON: /api/errors/11becbafab13228a.
Report an issue: GitHub.