{"record":{"id":"11becbafab13228a","repo":"diem/diem","slug":"derive-numvariants-can-only-be-used-on-an-enum","errorCode":null,"errorMessage":"#[derive(NumVariants)] can only be used on an enum","messagePattern":"#\\[derive\\(NumVariants\\)\\] can only be used on an enum","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/num-variants/src/lib.rs","lineNumber":53,"sourceCode":"    let name = input.ident;\n    let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();\n    let num_variants = compute_num_variants(&input.data, input_span)?;\n\n    let expanded = quote! {\n        impl #impl_generics #name #ty_generics #where_clause {\n            /// The number of variants in this enum.\n            pub const #const_name: usize = #num_variants;\n        }\n    };\n\n    Ok(expanded)\n}\n\n/// Computes the number of variants for an enum.\nfn compute_num_variants(data: &Data, span: Span) -> Result<usize> {\n    match data {\n        Data::Enum(data) => Ok(data.variants.len()),\n        Data::Struct(_) | Data::Union(_) => Err(Error::new(\n            span,\n            \"#[derive(NumVariants)] can only be used on an enum\",\n        )),\n    }\n}\n\n/// Computes the name of the constant.\nfn compute_const_name(attrs: Vec<Attribute>) -> Result<Ident> {\n    let mut const_names: Vec<_> = attrs\n        .iter()\n        .filter(|attr| attr.path.is_ident(\"num_variants\"))\n        .map(|attr| match attr.parse_meta() {\n            Ok(Meta::NameValue(MetaNameValue {\n                lit: Lit::Str(lit), ..\n            })) => Ok((attr.span(), lit.parse::<Ident>()?)),\n            _ => Err(Error::new(\n                attr.span(),\n                \"must be of the form #[num_variants = \\\"FOO\\\"]\",","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/diem/diem/blob/fc4714a8ea273b6efe8b13dbce72ea60aad9a16c/crates/num-variants/src/lib.rs#L35-L71","documentation":"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.","triggerScenarios":"Adding `#[derive(NumVariants)]` to a `struct` or `union` and compiling the crate.","commonSituations":"Copy-pasting the derive onto a struct by accident; refactoring an enum into a struct while leaving the derive in place.","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"],"exampleFix":"// before\n#[derive(NumVariants)]\npub struct MyStruct { a: u8 }\n// after\npub struct MyStruct { a: u8 } // derive removed; NumVariants only works on enums","handlingStrategy":"type-guard","validationCode":"// compile-time: only attach the derive to enums\nenum MyEnum { A, B }","typeGuard":"// Verify at the item site: the annotated item must be `enum ...`, not struct/union","tryCatchPattern":null,"preventionTips":["Only apply NumVariants to enum declarations","Review derive lists when refactoring enums into structs","Let CI compiler errors catch misuse early"],"tags":["proc-macro","compile-time","derive","rust"],"backgroundTag":"derive-macro-misuse","analyzedSha":"fc4714a8ea273b6efe8b13dbce72ea60aad9a16c","analyzedAt":"2026-09-04T21:07:05.890Z","contentChangedAt":"2026-09-04T21:07:05.890Z","schemaVersion":2},"datasetVersion":"2026-09-12T02:17:10.037Z"}