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]> --- 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). + if !has_this_module { + 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(); - // 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; -- 2.43.0
