{"record":{"id":"51ad1273989d9e2d","repo":"GraphiteEditor/Graphite","slug":"only-use-imports-and-command-functions-may-appea","errorCode":null,"errorMessage":"only `use` imports and command functions may appear in an #[editor_commands] module","messagePattern":"only `use` imports and command functions may appear in an #\\[editor_commands\\] module","errorType":"validation","errorClass":"syn::Error","httpStatus":null,"severity":"error","filePath":"proc-macros/src/editor_commands.rs","lineNumber":26,"sourceCode":"\tif !attr.is_empty() {\n\t\treturn Err(Error::new(attr.span(), \"#[editor_commands] takes no arguments\"));\n\t}\n\tfor attr in &module.attrs {\n\t\tif !attr.path().is_ident(\"doc\") {\n\t\t\treturn Err(Error::new(attr.span(), \"the #[editor_commands] module may not have other attributes\"));\n\t\t}\n\t}\n\tlet Some((_, items)) = module.content else {\n\t\treturn Err(Error::new(module.mod_token.span, \"#[editor_commands] requires a module with an inline body\"));\n\t};\n\n\tlet mut imports: Vec<ItemUse> = Vec::new();\n\tlet mut functions: Vec<ItemFn> = Vec::new();\n\tfor item in items {\n\t\tmatch item {\n\t\t\tItem::Use(import) => imports.push(import),\n\t\t\tItem::Fn(function) => functions.push(function),\n\t\t\tother => return Err(Error::new(other.span(), \"only `use` imports and command functions may appear in an #[editor_commands] module\")),\n\t\t}\n\t}\n\n\tlet mut variants = TokenStream::new();\n\tlet mut stubs = TokenStream::new();\n\tlet mut arms = TokenStream::new();\n\n\tfor function in &functions {\n\t\tfor attr in &function.attrs {\n\t\t\tif !attr.path().is_ident(\"doc\") {\n\t\t\t\treturn Err(Error::new(\n\t\t\t\t\tattr.span(),\n\t\t\t\t\t\"command functions may not have attributes; anything that doesn't fit the `fn name(args…) -> Message` contract belongs in a plain impl block\",\n\t\t\t\t));\n\t\t\t}\n\t\t}\n\t\tif !matches!(function.vis, Visibility::Inherited) {\n\t\t\treturn Err(Error::new(","sourceCodeStart":8,"sourceCodeEnd":44,"githubUrl":"https://github.com/GraphiteEditor/Graphite/blob/c507b356453361e31638b8bff8f6d46b6da2961e/proc-macros/src/editor_commands.rs#L8-L44","documentation":"The #[editor_commands] macro only understands two kinds of items inside its module: `use` imports and plain command functions. Any other item (struct, enum, const, static, impl block, nested module, macro invocation) hits the catch-all arm and is rejected with this compile-time error, because the macro would otherwise silently drop the item when it regenerates the module.","triggerScenarios":"Putting a `struct`, `impl`, `const`, `static`, `trait`, nested `mod`, or macro call inside the `#[editor_commands]` module body. The match on parsed items only has arms for `Item::Use` and `Item::Fn`.","commonSituations":"Growing a command module over time until someone adds a shared helper struct, a const for a default value, or an impl of a convenience method — all of which must live outside the macro module. Also hit when a merge accidentally leaves a test module inside.","solutions":["Move the non-`use`/non-`fn` item out of the #[editor_commands] module to the surrounding scope or a plain module.","If the item is a helper the commands need, import it with a `use` statement instead of defining it inline.","If the item is a test module (`#[cfg(test)] mod tests`), relocate it outside the attributed module."],"exampleFix":"// before\n#[editor_commands]\nmod commands {\n\tstruct LayerRef(u64); // rejected item\n\tfn select_layer(l: LayerRef) -> Message { ... }\n}\n\n// after\nstruct LayerRef(u64);\n#[editor_commands]\nmod commands {\n\tuse super::LayerRef;\n\tfn select_layer(l: LayerRef) -> Message { ... }\n}","handlingStrategy":"validation","validationCode":null,"typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep only `use` imports and plain command fns inside the #[editor_commands] module.","Put structs, consts, impls, and test modules in a sibling plain module.","Treat 'item does not generate a command' as a signal to move it out, not to work around the macro."],"tags":["rust","proc-macro","editor-commands","module-items"],"backgroundTag":"proc-macro-input-validation","analyzedSha":"c507b356453361e31638b8bff8f6d46b6da2961e","analyzedAt":"2026-08-16T21:57:18.596Z","schemaVersion":2},"datasetVersion":"2026-08-16T23:17:17.608Z"}