{"record":{"id":"f6b37423b58b168a","repo":"bevyengine/bevy","slug":"can-only-derive-variantdefaults-for-enums","errorCode":null,"errorMessage":"Can only derive VariantDefaults for enums","messagePattern":"Can only derive VariantDefaults for enums","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/bevy_ecs/macros/src/variant_defaults.rs","lineNumber":11,"sourceCode":"use bevy_macro_utils::fq_std::FQDefault;\nuse proc_macro::TokenStream;\nuse quote::{format_ident, quote, ToTokens};\nuse syn::{parse_macro_input, Data, DeriveInput};\n\npub(crate) fn derive_variant_defaults(input: TokenStream) -> TokenStream {\n    let ast = parse_macro_input!(input as DeriveInput);\n    let type_ident = &ast.ident;\n    let (impl_generics, type_generics, where_clause) = &ast.generics.split_for_impl();\n    let Data::Enum(data_enum) = &ast.data else {\n        panic!(\"Can only derive VariantDefaults for enums\");\n    };\n\n    let mut variant_defaults = Vec::new();\n    for variant in &data_enum.variants {\n        let variant_ident = &variant.ident;\n        let variant_name_lower = variant_ident.to_string().to_lowercase();\n        let variant_default_name = format_ident!(\"default_{}\", variant_name_lower);\n        match &variant.fields {\n            syn::Fields::Named(fields_named) => {\n                let fqdefault = FQDefault.into_token_stream();\n                let fields = fields_named.named.iter().map(|f| &f.ident);\n                variant_defaults.push(quote! {\n                    #[allow(missing_docs)]\n                    pub fn #variant_default_name() -> Self {\n                        Self::#variant_ident {\n                            #(#fields: #fqdefault::default(),)*\n                        }\n                    }","sourceCodeStart":1,"sourceCodeEnd":29,"githubUrl":"https://github.com/bevyengine/bevy/blob/396ca727080776bd313bb892423b7d94e03b81b4/crates/bevy_ecs/macros/src/variant_defaults.rs#L1-L29","documentation":"The `VariantDefaults` derive generates a `default_<variantname>()` constructor for every variant of an enum, using each field's `Default`. At variant_defaults.rs:10 the macro does `let Data::Enum(..) = &ast.data else { panic!(..) }`, so applying it to anything that is not an enum panics at compile time.","triggerScenarios":"`#[derive(VariantDefaults)]` on a `struct` or on a `union`. The let-else fails immediately after parsing the DeriveInput.","commonSituations":"Copy-pasting a derive list from an enum onto a struct during a refactor; IDE auto-import inserting every bevy derive; renaming an enum to a struct while keeping its derives.","solutions":["Move `#[derive(VariantDefaults)]` onto an enum type","Delete the derive from the struct/union if per-variant defaults make no sense there","If you want struct-wide defaults, use `#[derive(Default)]` instead"],"exampleFix":"// before\n#[derive(VariantDefaults)]\nstruct Config {\n    difficulty: f32,\n}\n\n// after\n#[derive(VariantDefaults, Default)]\nenum Difficulty {\n    #[default]\n    Easy,\n    Normal,\n    Hard,\n}","handlingStrategy":"validation","validationCode":"cargo check --workspace # panics in the derive at compile time with file/line of the item","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Reserve VariantDefaults for enum types","Keep derive lists per-type explicit rather than copy-pasted","Use #[derive(Default)] for struct defaults"],"tags":["rust","bevy","ecs","proc-macro","compile-time","enum"],"backgroundTag":"derive-macro-unsupported-type","analyzedSha":"396ca727080776bd313bb892423b7d94e03b81b4","analyzedAt":"2026-08-20T16:12:39.808Z","contentChangedAt":"2026-08-20T16:12:39.808Z","schemaVersion":2},"datasetVersion":"2026-09-08T20:17:18.057Z"}