swc-project/swc · error
derive(Merge) does not support an enum
Error message
derive(Merge) does not support an enum
What it means
The #[derive(Merge)] macro from swc_config_macro generates merge code by matching on syn::Data; only structs with named or unnamed fields are supported. Deriving it on an enum reaches unimplemented!("derive(Merge) does not support an enum") at merge.rs:22, which panics during macro expansion — i.e. at compile time of the crate using the derive.
Source
Thrown at crates/swc_config_macro/src/merge.rs:22
use syn::{parse_quote, DeriveInput, Expr, Field, Fields, Stmt, Token};
pub fn expand(input: DeriveInput) -> TokenStream {
match &input.data {
syn::Data::Struct(s) => {
let body = call_merge_for_fields("e!(self), &s.fields);
let body = join_stmts(&body);
let ident = &input.ident;
parse_quote!(
#[automatically_derived]
impl swc_config::merge::Merge for #ident {
fn merge(&mut self, _other: Self) {
#body
}
}
)
}
syn::Data::Enum(_) => unimplemented!("derive(Merge) does not support an enum"),
syn::Data::Union(_) => unimplemented!("derive(Merge) does not support a union"),
}
}
fn call_merge_for_fields(obj: &dyn ToTokens, fields: &Fields) -> Vec<Stmt> {
fn call_merge(obj: &dyn ToTokens, idx: usize, f: &Field) -> Expr {
let r = quote!(_other);
let l = access_field(obj, idx, f);
let r = access_field(&r, idx, f);
parse_quote!(swc_config::merge::Merge::merge(&mut #l, #r))
}
match fields {
Fields::Named(fs) => fs
.named
.iter()
.enumerate()View on GitHub (pinned to d7d7434666)
Solutions
- Convert the enum into a struct whose fields are each merge-able (structs with named/unnamed fields are supported).
- Implement swc_config::merge::Merge manually for the enum with your chosen precedence (e.g. other wins when non-default).
- Wrap the enum in a struct and derive Merge on the wrapper, implementing Merge by hand for the inner enum.
- If Unit-like variants are involved, also see the unit-struct restriction.
Example fix
// before
#[derive(Merge)]
enum Mode { Fast, Slow }
// after
enum Mode { Fast, Slow }
impl swc_config::merge::Merge for Mode {
fn merge(&mut self, other: Self) {
// define precedence explicitly
if matches!(self, Mode::Fast) { *self = other; }
}
} Defensive patterns
Strategy: validation
Validate before calling
// The panic is at macro-expansion time; the only 'validation' is reviewing // the derive input shape before compiling: // - #[derive(Merge)] requires a struct (named or unnamed fields, at least one field). // - Enums and unit structs are rejected. // Fail fast in review/CI with a grep: // rg -U '#\[derive\([^)]*Merge[^)]*\)\s*(pub\s+)?enum' src/
Prevention
- Derive Merge only on structs with fields; for enums write a manual Merge impl with explicit precedence.
- If you need enum config options, model them as newtype structs over an inner enum and implement Merge for the inner type by hand.
- Add a CI grep/regex gate for `#[derive(...Merge...)]` immediately followed by `enum` or a unit struct body.
- Read the derive's docs (swc_config::merge) before applying it to new type shapes.
When it happens
Trigger: Annotating an enum with #[derive(Merge)] in a crate that depends on swc_config / swc_config_macro, e.g. trying to make a config enum overridable. rustc aborts with the macro's panic message during compilation.
Common situations: Defining SWC config option types (transforms, plugin options) as enums for ergonomics and assuming derive(Merge) behaves like serde derives; upgrading config types from structs to tagged enums; error appears as 'proc-macro derive panicked' in build output.
Related errors
- derive(Merge) does not support a unit struct
- Failed to resolve plugin path: {resolved_path:?}
- Syntax Error
- failed to get parent of {v:?}
- Plugin runner cannot detect plugin's schema version. Ensure
AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16).
Data as JSON: /api/errors/db4d59354e59197f.
Report an issue: GitHub.