GraphiteEditor/Graphite · error · syn::Error

ExtractField only works on structs with named fields

Error message

ExtractField only works on structs with named fields

What it means

The `ExtractField` derive only supports structs with named fields because it generates a `field_types()` introspection listing each field's name, type, and source line (used for editor message documentation). Tuple structs and unit structs have no field names to report, so the derive aborts with this compile-time error.

Source

Thrown at proc-macros/src/extract_fields.rs:17

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

pub fn derive_extract_field_impl(input: TokenStream) -> syn::Result<TokenStream> {
	let input = parse2::<DeriveInput>(input)?;
	let struct_name = &input.ident;
	let generics = &input.generics;
	let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();

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

	let fields = match &input.data {
		Data::Struct(data) => match &data.fields {
			Fields::Named(fields) => &fields.named,
			_ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs with named fields")),
		},
		_ => return Err(syn::Error::new(Span::call_site(), "ExtractField only works on structs")),
	};

	let mut field_line = Vec::new();
	// Extract field names and types as strings at compile time
	let field_info = fields
		.iter()
		.map(|field| {
			let ident = field.ident.as_ref().unwrap();
			let name = ident.to_string();
			let ty = clean_rust_type_syntax(field.ty.to_token_stream().to_string());
			let line = ident.span().start().line;
			field_line.push(line);
			(name, ty)
		})
		.collect::<Vec<_>>();

View on GitHub (pinned to c507b35645)

Solutions

  1. Convert the tuple struct to named fields: `struct Foo { value: u32, name: String }`.
  2. If the type must stay a tuple struct, remove `ExtractField` from its derive list.
  3. For unit structs, remove the derive — there are no fields to extract.

Example fix

// before
#[derive(ExtractField)]
struct LayerSnapshot(u64, String);

// after
#[derive(ExtractField)]
struct LayerSnapshot {
	id: u64,
	name: String,
}
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Applying `#[derive(ExtractField)]` to a tuple struct (`struct Foo(u32, String);`) or a unit struct (`struct Marker;`). Only `Fields::Named` is accepted.

Common situations: Adding the derive to a newtype wrapper or marker type during a refactor, or applying a blanket `#[derive(Debug, Clone, ExtractField)]` via editor tooling/templating without checking the struct shape.

Related errors


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