GraphiteEditor/Graphite · error · syn::Error

Tried to derive HierarchicalTree for non-enum

Error message

Tried to derive HierarchicalTree for non-enum

What it means

The `HierarchicalTree` derive generates DebugMessageTree formatting for editor messages and is implemented exclusively for enums (each variant becomes a tree node). Applying it to a struct or union fails this compile-time check because there are no variants to walk.

Source

Thrown at proc-macros/src/hierarchical_tree.rs:14

use crate::helpers::clean_rust_type_syntax;
use proc_macro2::{Span, TokenStream};
use quote::{ToTokens, quote};
use syn::{Data, DeriveInput, Fields, Type, parse2};

pub fn generate_hierarchical_tree(input: TokenStream) -> syn::Result<TokenStream> {
	let input = parse2::<DeriveInput>(input)?;
	let input_type = &input.ident;

	let line_number = input_type.span().start().line;

	let data = match &input.data {
		Data::Enum(data) => data,
		_ => return Err(syn::Error::new(Span::call_site(), "Tried to derive HierarchicalTree for non-enum")),
	};

	let build_message_tree: Result<Vec<_>, syn::Error> = data
		.variants
		.iter()
		.map(|variant| {
			let variant_type = &variant.ident;

			let has_child = variant
				.attrs
				.iter()
				.any(|attr| attr.path().get_ident().is_some_and(|ident| ident == "sub_discriminant" || ident == "child"));

			match &variant.fields {
				Fields::Unit => Ok(quote! {
					message_tree.add_variant(DebugMessageTree::new(stringify!(#variant_type)));
				}),
				Fields::Unnamed(fields) => {

View on GitHub (pinned to c507b35645)

Solutions

  1. Remove `HierarchicalTree` from the struct/union's derive list.
  2. If the type is really a message, model it as an enum with variants and keep the derive there.
  3. For structs used as variant payloads, derive it on the wrapping enum and let the generated code stringify the payload fields.

Example fix

// before
#[derive(HierarchicalTree)]
struct DocumentMessage {
	name: String,
}

// after
#[derive(HierarchicalTree)]
enum DocumentMessage {
	Rename { name: String },
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Adding `#[derive(HierarchicalTree)]` to a `struct` or `union`. The match on `input.data` only binds `Data::Enum`.

Common situations: A message type refactored from enum to struct (or vice versa: derive list copied from an enum onto a new struct payload type), or IDE auto-derive inserting the full standard derive list onto every new type.

Related errors


AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16). Data as JSON: /api/errors/9fc8a3c653211f5c. Report an issue: GitHub.