databendlabs/databend · error

unions are not supported

Error message

unions are not supported

What it means

A compile-time guard in the derive macro's emit_walk_body: derive(Walk)/derive(WalkMut) can only be applied to structs and enums. This error fires when the macro is invoked on a syn::Data::Union, because there is no defined traversal order for union fields; the derive expansion fails at compile time.

Solutions

  1. Refactor the AST node to avoid union types in positions processed by the Walk/WalkMut derive, since emit_walk_body only handles structs and enums.
  2. Implement Walk/WalkMut manually for the affected type instead of using the derive.
  3. Restructure the union as an enum with tagged variants so the derive can enumerate cases.
Defensive patterns

Strategy: validation

When it happens

Trigger: Thrown at src/query/ast/visit_derive/src/lib.rs:85 when the library encounters an invalid state.

Common situations: See trigger scenarios.


AI-assisted analysis of databendlabs/databend@288d84d76e (2026-09-11). Data as JSON: /api/errors/59acf73c5d559123. Report an issue: GitHub.

Appendix: source

Thrown at src/query/ast/visit_derive/src/lib.rs:85

            #[automatically_derived]
            impl #impl_generics crate::visit::Walk for #ident #ty_generics #where_clause {
                fn walk<V: crate::visit::Visitor + ?Sized>(
                    &self,
                    visitor: &mut V,
                ) -> std::result::Result<crate::visit::VisitControl<V::Break>, V::Error> {
                    #walk_body
                    Ok(crate::visit::VisitControl::Continue)
                }
            }
        })
    }
}

fn emit_walk_body(data: &Data, mutable: bool) -> syn::Result<TokenStream2> {
    match data {
        Data::Struct(data) => emit_struct_body(data, mutable),
        Data::Enum(data) => emit_enum_body(data, mutable),
        Data::Union(data) => Err(Error::new(
            data.union_token.span(),
            "unions are not supported",
        )),
    }
}

fn emit_struct_body(data: &DataStruct, mutable: bool) -> syn::Result<TokenStream2> {
    let access = |member: TokenStream2| {
        if mutable {
            quote!(&mut self.#member)
        } else {
            quote!(&self.#member)
        }
    };

    let stmts = match &data.fields {
        Fields::Named(fields) => fields
            .named

View on GitHub (pinned to 288d84d76e)