{"record":{"id":"d74077d7bd3ca772","repo":"swc-project/swc","slug":"ast-serde-on-enum-does-not-accept-any-argument","errorCode":null,"errorMessage":"#[ast_serde] on enum does not accept any argument","messagePattern":"#\\[ast_serde\\] on enum does not accept any argument","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/ast_node/src/lib.rs","lineNumber":106,"sourceCode":"///\n/// so the deserializer can decide which variant to use.\n///\n///\n/// `#[tag]` also supports wildcard like `#[tag(\"*\")]`. You can use this if\n/// there are two many variants.\n#[proc_macro_attribute]\npub fn ast_serde(\n    args: proc_macro::TokenStream,\n    input: proc_macro::TokenStream,\n) -> proc_macro::TokenStream {\n    let input: DeriveInput = parse(input).expect(\"failed to parse input as a DeriveInput\");\n\n    // we should use call_site\n    let mut item = TokenStream::new();\n    match input.data {\n        Data::Enum(..) => {\n            if !args.is_empty() {\n                panic!(\"#[ast_serde] on enum does not accept any argument\")\n            }\n\n            item.extend(quote!(\n                #[derive(::serde::Serialize, ::swc_common::DeserializeEnum)]\n                #[serde(untagged)]\n                #input\n            ));\n        }\n        _ => {\n            let args: Option<ast_node_macro::Args> = if args.is_empty() {\n                None\n            } else {\n                Some(parse(args).expect(\"failed to parse args of #[ast_serde]\"))\n            };\n\n            let serde_tag = match input.data {\n                Data::Struct(DataStruct {\n                    fields: Fields::Named(..),","sourceCodeStart":88,"sourceCodeEnd":124,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/ast_node/src/lib.rs#L88-L124","documentation":"Compile-time panic from the `ast_serde` proc-macro attribute in swc's ast_node crate. When `#[ast_serde]` is applied to an enum, the macro only generates `#[derive(Serialize, DeserializeEnum)] #[serde(untagged)]` and rejects any attribute arguments outright; arguments are only parsed (as `ast_node_macro::Args`) for structs. Passing anything on an enum aborts macro expansion.","triggerScenarios":"Writing `#[ast_serde(some_arg)]` or any parenthesized/list argument on an enum item; the enum branch checks `!args.is_empty()` and panics before generating code.","commonSituations":"Copying a `#[ast_serde(...)]` invocation that was written for a struct onto a new enum; assuming enums and structs share the same argument grammar; upgrading swc_ast_node versions where accepted syntax shifted.","solutions":["Remove all arguments and use a bare `#[ast_serde]` on the enum","If you need custom serde behavior for the enum, write manual Serialize/Deserialize impls instead of the macro","Keep struct-only arguments (e.g. field tags) on struct applications only"],"exampleFix":"// before\n#[ast_serde(tag = \"type\")]\npub enum Expr {\n    Num(f64),\n}\n\n// after\n#[ast_serde]\npub enum Expr {\n    Num(f64),\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep `#[ast_serde]` argument-free on enums; arguments are struct-only","Run `cargo check` in CI so macro misuse fails fast at compile time","Copy attribute usage from crates/ast_node tests rather than from struct invocations"],"tags":["rust","proc-macro","swc","serde","compile-time"],"backgroundTag":"proc-macro-misuse","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}