{"record":{"id":"ec6b2d4722ce3b78","repo":"swc-project/swc","slug":"binder-for-union-type","errorCode":null,"errorMessage":"Binder for union type","messagePattern":"Binder for union type","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/swc_macros_common/src/binder.rs","lineNumber":76,"sourceCode":"    }\n\n    pub fn new_from(input: &'a DeriveInput) -> Self {\n        Self::new(&input.ident, &input.data, &input.attrs)\n    }\n\n    pub fn variants(&self) -> Vec<VariantBinder<'a>> {\n        match *self.body {\n            Data::Enum(DataEnum { ref variants, .. }) => {\n                let enum_name = &self.ident;\n                variants\n                    .iter()\n                    .map(|v| VariantBinder::new(Some(enum_name), &v.ident, &v.fields, &v.attrs))\n                    .collect()\n            }\n            Data::Struct(DataStruct { ref fields, .. }) => {\n                vec![VariantBinder::new(None, self.ident, fields, self.attrs)]\n            }\n            Data::Union(_) => unimplemented!(\"Binder for union type\"),\n        }\n    }\n}\n\n/// Variant.\n#[derive(Debug, Clone)]\npub struct VariantBinder<'a> {\n    /// None for struct.\n    enum_name: Option<&'a Ident>,\n    /// Name of variant.\n    name: &'a Ident,\n    data: &'a Fields,\n    attrs: &'a [Attribute],\n}\n\nimpl<'a> VariantBinder<'a> {\n    pub const fn new(\n        enum_name: Option<&'a Ident>,","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/swc-project/swc/blob/5176682b65416c6b5de6b47379ae1588ea3ecb3f/crates/swc_macros_common/src/binder.rs#L58-L94","documentation":"swc_macros_common supplies the derive-macro engine behind SWC's AST macros (#[ast_node(...)], Spanned, Take, and their serde impls). Binder::variants() decomposes the annotated item into per-variant binders: Data::Enum yields one VariantBinder per variant and Data::Struct one binder for the struct — Data::Union falls into the unimplemented!(\"Binder for union type\") arm, so applying any binder-backed derive to a Rust union panics during macro expansion (at compile time).","triggerScenarios":"Writing `union U { a: u32, b: f32 }` in a crate and putting a swc derive on it — e.g. #[ast_node(\"Tag\")], #[derive(Spanned)], #[derive(Take)], or the swc-flavored Serialize/Deserialize — invokes Binder::variants() on a union and panics.","commonSituations":"Adding an FFI-style or layout-sensitive union to an AST crate whose convention is to annotate every node with #[ast_node]; copy-pasting an existing node's attribute block onto a new union item; third-party crates deriving swc traits over memory-layout types.","solutions":["Model the data as a struct or an enum instead — both are fully supported by the binder.","Remove the swc derive(s) from the union and implement the required traits manually.","Wrap the union in a plain struct and derive the traits on the wrapper only."],"exampleFix":"// before: compile-time panic 'Binder for union type'\n#[ast_node(\"BinaryOp\")]\nunion Op {\n    add: u8,\n    sub: u8,\n}\n\n// after: model as an enum (or struct) — binder-supported\n#[ast_node(\"BinaryOp\")]\nenum Op {\n    Add,\n    Sub,\n}","handlingStrategy":"validation","validationCode":"# CI: fail when a union appears in files that also use swc derive macros\nrg -l '#\\[ast_node|derive\\([^)]*(Spanned|Take)' src/ \\\n  | xargs -r rg -n '^[[:space:]]*(pub[[:space:]]+)?union[[:space:]]' \\\n  && { echo 'union used with swc derive macro'; exit 1; } || true","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Prefer enums or structs over unions for AST node data — swc's binder supports only those","Run cargo expand on newly added node types to confirm the derive expands cleanly","Add the CI grep above so a union can never sneak into derived types"],"tags":["proc-macro","derive","union","compile-time","swc-macros-common"],"backgroundTag":"derive-macro-unsupported-input","analyzedSha":"5176682b65416c6b5de6b47379ae1588ea3ecb3f","analyzedAt":"2026-08-17T16:16:52.067Z","contentChangedAt":"2026-08-17T16:16:52.067Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}