GraphiteEditor/Graphite · error · syn::Error
Expected type path
Error message
Expected type path
What it means
Inside `#[message_handler_data]`, when the context type argument `C` of `MessageHandler<M, C>` is a reference (`&T` / `&'a mut T`), the referenced element must itself be a plain type path so the macro can take its identifier for line-number lookup and `field_types()`/`path()` calls. A reference to a tuple, slice, or other non-path type fails here.
Source
Thrown at proc-macros/src/message_handler_data_attr.rs:72
MessageData::new(format!("{}", stringify!(#input_type)), #input_type::field_types(), #input_type::path(), #input_type::line_number())
}
}
}
}
syn::Type::Tuple(_) => quote! {
#input_item
impl #message_type {
pub fn message_handler_str() -> MessageData {
MessageData::new(format!("{}", stringify!(#input_type)), #input_type::field_types(), #input_type::path(), #input_type::line_number())
}
}
},
syn::Type::Reference(type_reference) => {
let message_type = call_site_ident(format!("{input_type}Message"));
let type_ident = match &*type_reference.elem {
syn::Type::Path(type_path) => &type_path.path.segments.first().unwrap().ident,
_ => return Err(syn::Error::new(type_reference.elem.span(), "Expected type path")),
};
let type_line_number = type_ident.span().start().line;
let tr = clean_rust_type_syntax(type_reference.to_token_stream().to_string());
quote! {
#input_item
impl #message_type {
pub fn message_handler_data_str() -> MessageData {
MessageData::new(format!("{}", #tr), #type_ident::field_types(), #type_ident::path(), #type_ident::line_number())
}
pub fn message_handler_str() -> MessageData {
MessageData::new(format!("{}", stringify!(#input_type)), #input_type::field_types(), #input_type::path(), #input_type::line_number())
}
}
}View on GitHub (pinned to c507b35645)
Solutions
- Use a named struct (or the conventional ToolMessageData type) as the referenced context: `&ToolMessageData`.
- Define `struct Ctx(u8, u8);` and use `&Ctx` so the inner element is a path.
- If the tuple form was intentional, use a plain tuple type `C = (u8, u8)` rather than a reference to one — the macro has a dedicated arm for tuple context types.
Example fix
// before
#[message_handler_data]
impl MessageHandler<BrushMessage, &(u64, String)> for BrushTool { ... }
// after
struct BrushContext {
layer: u64,
name: String,
}
#[message_handler_data]
impl MessageHandler<BrushMessage, &BrushContext> for BrushTool { ... } Defensive patterns
Strategy: validation
Prevention
- Use `&NamedStruct` (reference to a path) as the context type, never a reference to a tuple/slice.
- Introduce a named context struct for multi-field contexts.
When it happens
Trigger: Writing `impl MessageHandler<Msg, &(u8, u8)> for …`, `impl MessageHandler<Msg, &[Tool]…>` style reference-to-non-path context types. The match binds `Type::Reference` but the inner `elem` is not `Type::Path`.
Common situations: Changing a context parameter from a named data struct to an ad-hoc tuple or slice reference to 'simplify' a handler signature, especially for tools that previously shared a single context struct.
Related errors
- Expected impl implementation
- Expected trait implementation
- Expected MessageHandler trait
- Unsupported type format
- Failed to parse input type for #[implementation(...)]. Expec
AI-assisted analysis of GraphiteEditor/Graphite@c507b35645 (2026-08-16).
Data as JSON: /api/errors/1efe2579d5676a22.
Report an issue: GitHub.