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


Reply via email to