swc-project/swc · error
Binder for union type
Error message
Binder for union type
What it means
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).
Source
Thrown at crates/swc_macros_common/src/binder.rs:76
}
pub fn new_from(input: &'a DeriveInput) -> Self {
Self::new(&input.ident, &input.data, &input.attrs)
}
pub fn variants(&self) -> Vec<VariantBinder<'a>> {
match *self.body {
Data::Enum(DataEnum { ref variants, .. }) => {
let enum_name = &self.ident;
variants
.iter()
.map(|v| VariantBinder::new(Some(enum_name), &v.ident, &v.fields, &v.attrs))
.collect()
}
Data::Struct(DataStruct { ref fields, .. }) => {
vec![VariantBinder::new(None, self.ident, fields, self.attrs)]
}
Data::Union(_) => unimplemented!("Binder for union type"),
}
}
}
/// Variant.
#[derive(Debug, Clone)]
pub struct VariantBinder<'a> {
/// None for struct.
enum_name: Option<&'a Ident>,
/// Name of variant.
name: &'a Ident,
data: &'a Fields,
attrs: &'a [Attribute],
}
impl<'a> VariantBinder<'a> {
pub const fn new(
enum_name: Option<&'a Ident>,View on GitHub (pinned to 5176682b65)
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.
Example fix
// before: compile-time panic 'Binder for union type'
#[ast_node("BinaryOp")]
union Op {
add: u8,
sub: u8,
}
// after: model as an enum (or struct) — binder-supported
#[ast_node("BinaryOp")]
enum Op {
Add,
Sub,
} Defensive patterns
Strategy: validation
Validate before calling
# CI: fail when a union appears in files that also use swc derive macros
rg -l '#\[ast_node|derive\([^)]*(Spanned|Take)' src/ \
| xargs -r rg -n '^[[:space:]]*(pub[[:space:]]+)?union[[:space:]]' \
&& { echo 'union used with swc derive macro'; exit 1; } || true Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- union
- An element descriptor's .kind property must be either "metho
- An element descriptor's .placement property must be one of "
- A class descriptor's .kind property must be "class", but a d
- ${objectType} can't have a .${name} property.
AI-assisted analysis of swc-project/swc@5176682b65 (2026-08-17).
Data as JSON: /api/errors/ec6b2d4722ce3b78.
Report an issue: GitHub.