rust-lang/rust · error
cannot derive on union
Error message
cannot derive on union
What it means
`visitable_derive` (in rustc_macros/src/visitable.rs) generates `Walkable`/`MutWalkable` impls for the rustc_ast IR traversal by visiting each field ref/ref-mut. Unions have no per-field access pattern the generator can express, so the guard at visitable.rs:5 panics on `syn::Data::Union`.
Source
Thrown at compiler/rustc_macros/src/visitable.rs:6
use quote::quote;
use synstructure::BindingInfo;
pub(super) fn visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if let syn::Data::Union(_) = s.ast().data {
panic!("cannot derive on union")
}
let has_attr = |bind: &BindingInfo<'_>, name| {
let mut found = false;
bind.ast().attrs.iter().for_each(|attr| {
if !attr.path().is_ident("visitable") {
return;
}
let _ = attr.parse_nested_meta(|nested| {
if nested.path.is_ident(name) {
found = true;
}
Ok(())
});
});
found
};
View on GitHub (pinned to 22057b88b0)
Solutions
- Remove `#[derive(Visitable)]` from the union.
- Restructure the IR node as a struct or enum so the derive can enumerate fields/variants.
- Manually implement `Walkable`/`MutWalkable` to visit only the field indicated by an external discriminant.
Example fix
// before
#[derive(Visitable)]
union Node {
expr: Expr,
item: Item,
}
// after
#[derive(Visitable)]
enum Node {
Expr(Expr),
Item(Item),
} Defensive patterns
Strategy: validation
Validate before calling
// `visitable.rs` derive — same union rejection as the other TypeFoldable /
// TypeVisitable family members.
fn reject_union_for_derive(item: &syn::Item) -> Result<(), String> {
if let syn::Item::Union(u) = item {
return Err(format!(
"union `{}` cannot derive visitable; manual impl required",
u.ident));
}
Ok(())
} Type guard
fn visitable_derivable(item: &syn::Item) -> bool {
matches!(item, syn::Item::Struct(_) | syn::Item::Enum(_))
} Prevention
- Adopt a project-wide rule: derives that need to traverse fields are struct/enum only.
- Maintain a short allow-list of unions and their manual trait impls.
When it happens
Trigger: Annotating a `union` with `#[derive(Visitable)]` (the AST `Walkable`/`MutWalkable` derive used by rustc_ast/rustc_parse visitors); macro expansion matches the union arm and panics.
Common situations: Adding AST-walking derives to a union-shaped IR node during parser/AST refactoring. Copying a derive block from a struct AST node onto a union. Introducing a union for FFI inside AST code and inheriting nearby derives.
Related errors
- cannot derive on union
- cannot derive on union
- cannot derive on union
- cannot derive on union
- error parsing stable_hash
AI-assisted analysis of rust-lang/rust@22057b88b0 (2026-08-03).
Data as JSON: /data/errors/6ba0b3971bb7afda.json.
Report an issue: GitHub.