On Thu May 21, 2026 at 8:52 AM BST, Alvin Sun wrote: > Auto-add `type ThisModule: ::kernel::ModuleMetadata;` as a required > associated type on the trait side if not already defined, and > auto-insert `type ThisModule = crate::LocalModule;` on the impl side > if not explicitly provided, eliminating the need to manually declare > and implement `ThisModule` in every vtable trait and impl. > > Signed-off-by: Alvin Sun <[email protected]>
Suggested-by: Gary Guo <[email protected]> Link: https://lore.kernel.org/all/[email protected] > --- > rust/macros/lib.rs | 6 ++++++ > rust/macros/vtable.rs | 38 +++++++++++++++++++++++++++++++++++++- > 2 files changed, 43 insertions(+), 1 deletion(-) > > diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs > index 2cfd59e0f9e7c..d35e45ea745c0 100644 > --- a/rust/macros/lib.rs > +++ b/rust/macros/lib.rs > @@ -176,6 +176,12 @@ pub fn module(input: TokenStream) -> TokenStream { > /// > /// This macro should not be used when all functions are required. > /// > +/// Additionally, this macro automatically handles the `ThisModule` > +/// associated type: on the trait side, `type ThisModule: ModuleMetadata;` > +/// is added as a required associated type if not already defined; on the > +/// impl side, `type ThisModule = LocalModule;` is automatically inserted > +/// if not explicitly defined. > +/// > /// # Examples > /// > /// ``` > diff --git a/rust/macros/vtable.rs b/rust/macros/vtable.rs > index c6510b0c4ea1d..d3d0e9cbd7172 100644 > --- a/rust/macros/vtable.rs > +++ b/rust/macros/vtable.rs > @@ -23,6 +23,7 @@ > > fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> { > let mut gen_items = Vec::new(); > + let mut has_this_module = false; > > gen_items.push(parse_quote! { > /// A marker to prevent implementors from forgetting to use > [`#[vtable]`](vtable) > @@ -30,6 +31,28 @@ fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> { > const USE_VTABLE_ATTR: (); > }); > > + // Detect existing type ThisModule so we don't add a duplicate. > + for i in &item.items { > + if let TraitItem::Type(type_item) = i { > + if type_item.ident == "ThisModule" { > + has_this_module = true; > + } > + } > + } > + > + // Add `type ThisModule: ModuleMetadata` as a required associated type if > + // the trait does not already define it. No default is used because > + // `associated_type_defaults` is unstable (issue #29661). I don't think this is relevant. What's the sensible default anyway? > + if !has_this_module { Perhaps just make this an one liner : if !item.items.iter().any(|i| matches!(item, TraitItem::Type(t) if t.ident == "ThisModule")) { > + gen_items.push(parse_quote! { > + /// The module implementing this vtable trait. > + /// > + /// Automatically set to `crate::LocalModule` by the `#[vtable]` > + /// impl macro. > + type ThisModule: ::kernel::ModuleMetadata; > + }); > + } > + > for item in &item.items { > if let TraitItem::Fn(fn_item) = item { > let name = &fn_item.sig.ident; > @@ -58,18 +81,31 @@ fn handle_trait(mut item: ItemTrait) -> Result<ItemTrait> > { > fn handle_impl(mut item: ItemImpl) -> Result<ItemImpl> { > let mut gen_items = Vec::new(); > let mut defined_consts = HashSet::new(); > + let mut defined_types = HashSet::new(); I'd just rename `defined_consts` to `defined_items` to reuse the same set as there cannot be assoc items with same name anyway. Best, Gary > > - // Iterate over all user-defined constants to gather any possible > explicit overrides. > + // Iterate over all user-defined constants and types to gather any > possible explicit overrides. > for item in &item.items { > if let ImplItem::Const(const_item) = item { > defined_consts.insert(const_item.ident.clone()); > } > + if let ImplItem::Type(type_item) = item { > + defined_types.insert(type_item.ident.clone()); > + } > } > > gen_items.push(parse_quote! { > const USE_VTABLE_ATTR: () = (); > }); > > + // Auto-insert `type ThisModule = crate::LocalModule` if not explicitly > defined. > + // `crate::LocalModule` resolves to the real module type (via `module!`) > or a > + // dummy fallback in non-module contexts (e.g., doctests). > + if !defined_types.contains(&parse_quote!(ThisModule)) { > + gen_items.push(parse_quote! { > + type ThisModule = crate::LocalModule; > + }); > + } > + > for item in &item.items { > if let ImplItem::Fn(fn_item) = item { > let name = &fn_item.sig.ident;
