{"record":{"id":"9c772148d47551fe","repo":"slint-ui/slint","slug":"the-structure-does-not-ends-in-vtable","errorCode":null,"errorMessage":"The structure does not ends in 'VTable'","messagePattern":"The structure does not ends in 'VTable'","errorType":"exception","errorClass":"proc_macro::Error","httpStatus":null,"severity":"error","filePath":"helper_crates/vtable/macro/macro.rs","lineNumber":183,"sourceCode":"*/\n#[proc_macro_attribute]\npub fn vtable(_attr: TokenStream, item: TokenStream) -> TokenStream {\n    let mut input = parse_macro_input!(item as ItemStruct);\n\n    let fields = if let Fields::Named(fields) = &mut input.fields {\n        fields\n    } else {\n        return Error::new(\n            proc_macro2::Span::call_site(),\n            \"Only supported for structure with named fields\",\n        )\n        .to_compile_error()\n        .into();\n    };\n\n    let vtable_name = input.ident.to_string();\n    if !vtable_name.ends_with(\"VTable\") {\n        return Error::new(input.ident.span(), \"The structure does not ends in 'VTable'\")\n            .to_compile_error()\n            .into();\n    }\n\n    let trait_name = Ident::new(&vtable_name[..vtable_name.len() - 6], input.ident.span());\n    let to_name = quote::format_ident!(\"{}TO\", trait_name);\n    let module_name = quote::format_ident!(\"{}_vtable_mod\", trait_name);\n    let static_vtable_macro_name = quote::format_ident!(\"{}_static\", vtable_name);\n\n    let vtable_name = input.ident.clone();\n\n    let mut drop_impls = Vec::new();\n\n    let mut generated_trait = ItemTrait {\n        attrs: input\n            .attrs\n            .iter()\n            .filter(|a| a.path().get_ident().as_ref().map(|i| *i == \"doc\").unwrap_or(false))","sourceCodeStart":165,"sourceCodeEnd":201,"githubUrl":"https://github.com/slint-ui/slint/blob/bb937076de3f7919766c1f25e2e969367cf77e9a/helper_crates/vtable/macro/macro.rs#L165-L201","documentation":"The #[vtable] macro derives the trait name by stripping a literal 'VTable' suffix from the struct's identifier (e.g. FooVTable -> trait Foo). A struct whose name does not end in 'VTable' breaks this derivation, so the macro rejects it at compile time.","triggerScenarios":"Annotating a named-field struct named e.g. `FooVt`, `FooTable`, or `Foo` with #[vtable].","commonSituations":"Renaming a vtable struct during refactoring and accidentally removing or altering the required 'VTable' suffix; inventing a new trait interface without following the naming convention.","solutions":["Rename the struct so it ends in 'VTable' (e.g. MyTraitVTable for trait MyTrait).","Ensure the part before 'VTable' is exactly the trait name you want, since it is used verbatim to generate the trait."],"exampleFix":"// before\n#[vtable]\nstruct MyTraitVT { init: fn(VRef<MyTraitVT>) }\n// after\n#[vtable]\nstruct MyTraitVTable { init: fn(VRef<MyTraitVTable>) }","handlingStrategy":"validation","validationCode":"assert!(struct_name.ends_with(\"VTable\"));","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Follow the naming convention TraitNameVTable for every #[vtable] struct.","Check the struct name after any rename refactor."],"tags":["proc-macro","naming","compile-time","rust"],"backgroundTag":"invalid-identifier-format","analyzedSha":"bb937076de3f7919766c1f25e2e969367cf77e9a","analyzedAt":"2026-09-16T01:37:20.251Z","contentChangedAt":"2026-09-16T01:37:20.251Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}