linebender/druid · error
Data implementations cannot be derived from unions
Error message
Data implementations cannot be derived from unions
What it means
The Data derive in druid-derive supports structs and enums only. Applying #[derive(Data)] to a union is rejected at compile time with this error, anchored at the union keyword's span, because the derive generates no code for unions.
Solutions
- Rewrite the union as an enum with variants for each field view, or as a struct, and derive Data on that.
- Remove #[derive(Data)] from the union and manage that data outside the druid data tree.
- Wrap the union in a struct that derives Data, implementing Data manually for the union-accessing parts (e.g. via same() comparison).
Example fix
// before
#[derive(Data, Clone, Copy)]
union Value { i: i32, f: f32 }
// after
#[derive(Data, Clone, Copy)]
enum Value { Int(i32), Float(f32) } Defensive patterns
Strategy: validation
Validate before calling
// CI check: forbid Data derive on unions // grep-based guard (run before cargo build): // ! grep -rPzo '(?s)#[^ ]*derive\s*\([^)]*\bData\b[^)]*\)(?s:.)*?\bunion\b' src/
Prevention
- Never add #[derive(Data)] to union definitions.
- Use enums or structs for data-tree nodes reachable by druid.
- If FFI unions are needed, wrap them in a struct with a manual (non-derive) Data implementation.
- Run `cargo check` early; the proc-macro error names the union span directly.
When it happens
Trigger: Writing #[derive(Data)] on a `union` definition, either directly or via a macro that blindly forwards derive attributes to all items in a module.
Common situations: FFI-style code with repr(C) unions where someone tries to make the union part of an app-data tree, macro-generated code deriving Data on every item.
Understand the failure class
Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.
Related errors
- Unknown attribute
- Expected attribute list (the form #[data(one, two)])
- Duplicate attribute
- Expected attribute list (the form #[lens(one, two)])
- expected str, found... something else
AI-assisted analysis of linebender/druid@0f8b1195e4 (2026-09-10).
Data as JSON: /api/errors/18c51f72e3987968.
Report an issue: GitHub.
Appendix: source
Thrown at druid-derive/src/data.rs:17
// Copyright 2019 the Druid Authors
// SPDX-License-Identifier: Apache-2.0
//! The implementation for #[derive(Data)]
use crate::attr::{DataAttr, Field, FieldKind, Fields};
use quote::{quote, quote_spanned};
use syn::{spanned::Spanned, Data, DataEnum, DataStruct};
pub(crate) fn derive_data_impl(
input: syn::DeriveInput,
) -> Result<proc_macro2::TokenStream, syn::Error> {
match &input.data {
Data::Struct(s) => derive_struct(&input, s),
Data::Enum(e) => derive_enum(&input, e),
Data::Union(u) => Err(syn::Error::new(
u.union_token.span(),
"Data implementations cannot be derived from unions",
)),
}
}
fn derive_struct(
input: &syn::DeriveInput,
s: &DataStruct,
) -> Result<proc_macro2::TokenStream, syn::Error> {
let ident = &input.ident;
let impl_generics = generics_bounds(&input.generics);
let (_, ty_generics, where_clause) = &input.generics.split_for_impl();
let fields = Fields::<DataAttr>::parse_ast(&s.fields)?;
let diff = if fields.len() > 0 {
let same_fns = fieldsView on GitHub (pinned to 0f8b1195e4)