swc-project/swc · error

derive(Merge) does not support a unit struct

Error message

derive(Merge) does not support a unit struct

What it means

#[derive(Merge)] from swc_config_macro generates one Merge::merge call per struct field; a unit struct has no fields, so Fields::Unit reaches unimplemented!("derive(Merge) does not support a unit struct") at merge.rs:51 and the proc macro panics at compile time. Unit structs are rejected because there is nothing to merge and the derive chooses to fail loudly instead of generating a no-op.

Source

Thrown at crates/swc_config_macro/src/merge.rs:51

        parse_quote!(swc_config::merge::Merge::merge(&mut #l, #r))
    }

    match fields {
        Fields::Named(fs) => fs
            .named
            .iter()
            .enumerate()
            .map(|(idx, f)| call_merge(obj, idx, f))
            .map(|expr| Stmt::Expr(expr, Some(Token![;](fs.brace_token.span.join()))))
            .collect(),
        Fields::Unnamed(fs) => fs
            .unnamed
            .iter()
            .enumerate()
            .map(|(idx, f)| call_merge(obj, idx, f))
            .map(|expr| Stmt::Expr(expr, Some(Token![;](fs.paren_token.span.join()))))
            .collect(),
        Fields::Unit => unimplemented!("derive(Merge) does not support a unit struct"),
    }
}

View on GitHub (pinned to d7d7434666)

Solutions

  1. Implement Merge manually with a no-op: `impl Merge for X { fn merge(&mut self, _other: Self) {} }`.
  2. Or give the struct a field (e.g. `_priv: ()` or PhantomData) so the derive has something to merge.
  3. Remove the derive if the type never participates in config merging.
  4. Prefer explicit manual impls over derives for degenerate shapes.

Example fix

// before
#[derive(Merge)]
struct Marker;

// after
struct Marker;
impl swc_config::merge::Merge for Marker {
    fn merge(&mut self, _other: Self) {}
}
Defensive patterns

Strategy: validation

Validate before calling

// Unit structs are rejected at expansion time; validate the shape instead:
// a type deriving Merge must be `struct Name { .. }` or `struct Name(..)` with >=1 field.
// CI gate: flag derives on fieldless structs
//   rg -U '#\[derive\([^)]*Merge[^)]*\)\s*(pub\s+)?struct\s*\w+\s*;' src/

Prevention

When it happens

Trigger: Writing #[derive(Merge)] on a marker type like `struct Done;` in a crate using swc_config. Compilation of that crate fails with 'proc-macro derive panicked' and the message above.

Common situations: Adding marker/phantom types or state tags to config type hierarchies that already derive Merge; refactoring a fieldless tuple struct `struct X();`-adjacent shapes; the error confuses users because the type itself is trivial.

Related errors


AI-assisted analysis of swc-project/swc@d7d7434666 (2026-08-16). Data as JSON: /api/errors/cc447b4a35380277. Report an issue: GitHub.