rust-for-linux.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] rust: add `#[macro_export_scoped]` for scoped declarative macro
@ 2026-08-11 12:25 Gary Guo
  2026-08-11 12:25 ` [PATCH 1/4] rust: macros: add `#[macro_export_scoped]` Gary Guo
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Gary Guo @ 2026-08-11 12:25 UTC (permalink / raw)
  To: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Breno Leitao, Luis Chamberlain, Russ Weight,
	Lyude Paul
  Cc: linux-kernel, rust-for-linux, driver-core, Gary Guo

Rust's declarative macro scoping rule is confusing because it was
historically purely textual scoped and the path-based scoping is added as
an afterthought.

`#[macro_export]` will make the macro available for use outside the crate,
but it also adds the macro to the root of crate. This has the issue where
it prevents us from cleanly put things in modules where they belong. Macro
2.0 is supposed to address this issue, but currently it seems that we are
unlikely to get macro 2.0 any time soon.

There is a way to approximate the scoping -- hide the macro from the crate
root using `#[doc(hidden)]`, and then re-export the macro from where they
are supposed to appear, and undo the `#[doc(hidden)]` with
`#[doc(inline)]`. We have used this approach for a few macros already.
This is not fully bullet-proof; users can still reference the items from
crate root, as it is hidden from documentation but is still present in name
resolution.

Introduce a macro `#[macro_export_scoped]`, that implements the above
trick, so people can create new properly-scoped macros easily. Also, adopt
a solution where we assign the macros non-guessable names, and then just
re-export them under intended name. This removes the possibility of
using the macro from incorrect path unintentionally.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
Gary Guo (4):
      rust: macros: add `#[macro_export_scoped]`
      rust: build_assert: remove macro from crate root
      rust: list: convert to use `#[macro_export_scoped]`
      rust: io: convert to use `#[macro_export_scoped]`

 rust/kernel/build_assert.rs            | 24 +++++----------
 rust/kernel/configfs.rs                |  4 +--
 rust/kernel/firmware.rs                |  4 +--
 rust/kernel/io.rs                      | 27 +++++++----------
 rust/kernel/list/arc.rs                |  4 +--
 rust/kernel/list/arc_field.rs          |  4 +--
 rust/kernel/list/impl_list_item_mod.rs | 14 ++++-----
 rust/kernel/ptr.rs                     |  6 +---
 rust/kernel/sync/atomic.rs             |  2 +-
 rust/macros/lib.rs                     | 25 ++++++++++++++++
 rust/macros/macro_export_scoped.rs     | 53 ++++++++++++++++++++++++++++++++++
 11 files changed, 108 insertions(+), 59 deletions(-)
---
base-commit: 6b8c8af514d739d0335f5579b585e02babe8a727
change-id: 20260811-macro_export_scoped-5ce38b5db968

Best regards,
--  
Gary Guo <gary@garyguo.net>


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH 1/4] rust: macros: add `#[macro_export_scoped]`
  2026-08-11 12:25 [PATCH 0/4] rust: add `#[macro_export_scoped]` for scoped declarative macro Gary Guo
@ 2026-08-11 12:25 ` Gary Guo
  2026-08-11 12:25 ` [PATCH 2/4] rust: build_assert: remove macro from crate root Gary Guo
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Gary Guo @ 2026-08-11 12:25 UTC (permalink / raw)
  To: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Breno Leitao, Luis Chamberlain, Russ Weight,
	Lyude Paul
  Cc: linux-kernel, rust-for-linux, driver-core, Gary Guo

Due to Rust macro scoping rules, macros that are exported with
`#[macro_export_scoped]` gets added to the crate root, and this causes the
crate root to get crowded with various macros.

We used a trick of `#[doc(hidden)]` + `#[doc(inline)] pub use` to make
these macros to appear to be only defined in the documentation, but this
does not actually prevent them from being referenced from crate root.

Create a macro `#[macro_export_scoped]`, that automates these definition
and re-export and also give these macro unique and non-guessable names.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/macros/lib.rs                 | 25 ++++++++++++++++++
 rust/macros/macro_export_scoped.rs | 53 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 0514fc7c0a55..6f8ef9043255 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -20,6 +20,7 @@
 mod for_lt;
 mod helpers;
 mod kunit;
+mod macro_export_scoped;
 mod module;
 mod paste;
 mod vtable;
@@ -320,6 +321,30 @@ pub fn concat_idents(input: TokenStream) -> TokenStream {
     concat_idents::concat_idents(parse_macro_input!(input)).into()
 }
 
+/// Export a macro publicly, but from the current module instead of crate root.
+///
+/// # Examples
+///
+/// ```
+/// mod foo {
+///     #[kernel::macros::macro_export_scoped]
+///     macro_rules! my_macro {
+///         () => {}
+///     }
+/// }
+///
+/// foo::my_macro!();
+/// ```
+#[doc(hidden)]
+#[proc_macro_attribute]
+#[allow(non_snake_case)]
+pub fn macro_export_scoped(attr: TokenStream, input: TokenStream) -> TokenStream {
+    parse_macro_input!(attr as syn::parse::Nothing);
+    macro_export_scoped::macro_export_scoped(parse_macro_input!(input))
+        .unwrap_or_else(|e| e.into_compile_error())
+        .into()
+}
+
 /// Paste identifiers together.
 ///
 /// Within the `paste!` macro, identifiers inside `[<` and `>]` are concatenated together to form a
diff --git a/rust/macros/macro_export_scoped.rs b/rust/macros/macro_export_scoped.rs
new file mode 100644
index 000000000000..a14ee51d2d93
--- /dev/null
+++ b/rust/macros/macro_export_scoped.rs
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use std::hash::{
+    DefaultHasher,
+    Hash,
+    Hasher, //
+};
+
+use proc_macro2::TokenStream;
+use quote::{
+    format_ident,
+    quote, //
+};
+use syn::{
+    Error,
+    ItemMacro,
+    Result, //
+};
+
+pub(crate) fn macro_export_scoped(mut input: ItemMacro) -> Result<TokenStream> {
+    if !input.mac.path.is_ident("macro_rules") {
+        return Err(Error::new_spanned(
+            input,
+            "#[macro_export_scoped] can only be used on `macro_rules!`",
+        ));
+    }
+
+    let Some(name) = input.ident else {
+        Err(Error::new_spanned(
+            input,
+            "`macro_rules!` definition missing an identifier",
+        ))?
+    };
+
+    // Hash together file name and macro name to create a hash that is likely to be unique. Use
+    // `DefaultHasher::new` which is free from RNG so the build is still reproducible.
+    let mut hasher = DefaultHasher::new();
+    crate::helpers::file().hash(&mut hasher);
+    name.hash(&mut hasher);
+    let hash = hasher.finish();
+
+    let unique_name = format_ident!("macro_{name}_{hash:x}");
+    input.ident = Some(unique_name.clone());
+
+    Ok(quote!(
+        #[doc(hidden)]
+        #[macro_export]
+        #input
+
+        #[doc(inline)]
+        pub use #unique_name as #name;
+    ))
+}

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 2/4] rust: build_assert: remove macro from crate root
  2026-08-11 12:25 [PATCH 0/4] rust: add `#[macro_export_scoped]` for scoped declarative macro Gary Guo
  2026-08-11 12:25 ` [PATCH 1/4] rust: macros: add `#[macro_export_scoped]` Gary Guo
@ 2026-08-11 12:25 ` Gary Guo
  2026-08-11 12:25 ` [PATCH 3/4] rust: list: convert to use `#[macro_export_scoped]` Gary Guo
  2026-08-11 12:25 ` [PATCH 4/4] rust: io: " Gary Guo
  3 siblings, 0 replies; 5+ messages in thread
From: Gary Guo @ 2026-08-11 12:25 UTC (permalink / raw)
  To: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Breno Leitao, Luis Chamberlain, Russ Weight,
	Lyude Paul
  Cc: linux-kernel, rust-for-linux, driver-core, Gary Guo

Convert `build_assert` to use `#[macro_export_scoped]`. This removes the
macros from crate root of `kernel`. A few remaining mentions of the macros
from crate root are removed.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/kernel/build_assert.rs | 24 +++++++-----------------
 rust/kernel/configfs.rs     |  4 ++--
 rust/kernel/firmware.rs     |  4 ++--
 rust/kernel/ptr.rs          |  6 +-----
 rust/kernel/sync/atomic.rs  |  2 +-
 5 files changed, 13 insertions(+), 27 deletions(-)

diff --git a/rust/kernel/build_assert.rs b/rust/kernel/build_assert.rs
index c3acb9b68a65..4774c7fb6976 100644
--- a/rust/kernel/build_assert.rs
+++ b/rust/kernel/build_assert.rs
@@ -61,17 +61,11 @@
 //! undefined symbols and linker errors, it is not developer friendly to debug, so it is recommended
 //! to avoid it and prefer other two assertions where possible.
 
-#[doc(inline)]
-pub use crate::{
-    build_assert_macro as build_assert,
-    build_error,
-    const_assert,
-    static_assert, //
-};
-
 #[doc(hidden)]
 pub use build_error::build_error as build_error_fn;
 
+use macros::macro_export_scoped;
+
 /// Static assert (i.e. compile-time assert).
 ///
 /// Similar to C11 [`_Static_assert`] and C++11 [`static_assert`].
@@ -105,8 +99,7 @@
 /// static_assert!(f(40) == 42);
 /// static_assert!(f(40) == 42, "f(x) must add 2 to the given input.");
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! static_assert {
     ($condition:expr $(,$arg:literal)?) => {
         const _: () = ::core::assert!($condition $(,$arg)?);
@@ -134,8 +127,7 @@ macro_rules! static_assert {
 ///     const_assert!(size_of::<T>() > 0, "T cannot be ZST");
 /// }
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! const_assert {
     ($condition:expr $(,$arg:literal)?) => {
         const { ::core::assert!($condition $(,$arg)?) };
@@ -159,8 +151,7 @@ macro_rules! const_assert {
 /// assert_eq!(foo(usize::MAX - 1), usize::MAX); // OK.
 /// // foo(usize::MAX); // Fails to compile.
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! build_error {
     () => {{
         $crate::build_assert::build_error_fn("")
@@ -203,9 +194,8 @@ macro_rules! build_error {
 ///
 /// const _: () = const_bar(2);
 /// ```
-#[macro_export]
-#[doc(hidden)]
-macro_rules! build_assert_macro {
+#[macros::macro_export_scoped]
+macro_rules! build_assert {
     ($cond:expr $(,)?) => {{
         if !$cond {
             $crate::build_assert::build_error_fn(concat!("assertion failed: ", stringify!($cond)));
diff --git a/rust/kernel/configfs.rs b/rust/kernel/configfs.rs
index 2339c6467325..8660ce01d97f 100644
--- a/rust/kernel/configfs.rs
+++ b/rust/kernel/configfs.rs
@@ -511,7 +511,7 @@ pub trait GroupOperations {
     /// NOTE: "drop" in the name of this function is not related to the Rust drop term. Rather, the
     /// name is inherited from the callback name in the underlying C code.
     fn drop_item(&self, _child: ArcBorrow<'_, Group<Self::Child>>) {
-        kernel::build_error!(kernel::error::VTABLE_DEFAULT_ERROR)
+        build_error!(kernel::error::VTABLE_DEFAULT_ERROR)
     }
 }
 
@@ -660,7 +660,7 @@ pub trait AttributeOperations<const ID: u64 = 0> {
     /// Implementations should parse the value from `page` and update internal
     /// state to reflect the parsed value.
     fn store(_data: &Self::Data, _page: &[u8]) -> Result {
-        kernel::build_error!(kernel::error::VTABLE_DEFAULT_ERROR)
+        build_error!(kernel::error::VTABLE_DEFAULT_ERROR)
     }
 }
 
diff --git a/rust/kernel/firmware.rs b/rust/kernel/firmware.rs
index a18f8b84f3e3..1abc66b84ef2 100644
--- a/rust/kernel/firmware.rs
+++ b/rust/kernel/firmware.rs
@@ -325,7 +325,7 @@ const fn push_internal(mut self, bytes: &[u8]) -> Self {
     pub const fn push(self, s: &str) -> Self {
         // Check whether there has been an initial call to `next_entry()`.
         if N != 0 && self.n == 0 {
-            crate::build_error!("Must call next_entry() before push().");
+            build_error!("Must call next_entry() before push().");
         }
 
         self.push_internal(s.as_bytes())
@@ -369,7 +369,7 @@ pub const fn new_entry(self) -> Self {
         if this.n == N {
             this.buf
         } else {
-            crate::build_error!("Length mismatch.");
+            build_error!("Length mismatch.");
         }
     }
 }
diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
index 82acb531b17b..b6fb802c2e21 100644
--- a/rust/kernel/ptr.rs
+++ b/rust/kernel/ptr.rs
@@ -5,13 +5,9 @@
 pub mod projection;
 pub use crate::project_pointer as project;
 
-use core::mem::{
-    align_of,
-    size_of, //
-};
 use core::num::NonZero;
 
-use crate::const_assert;
+use crate::prelude::*;
 
 /// Type representing an alignment, which is always a power of two.
 ///
diff --git a/rust/kernel/sync/atomic.rs b/rust/kernel/sync/atomic.rs
index 9cd009d57e35..c62cb46798ff 100644
--- a/rust/kernel/sync/atomic.rs
+++ b/rust/kernel/sync/atomic.rs
@@ -25,7 +25,7 @@
 
 pub(crate) use internal::{AtomicArithmeticOps, AtomicBasicOps, AtomicExchangeOps};
 
-use crate::build_error;
+use crate::build_assert::build_error;
 use internal::AtomicRepr;
 use ordering::OrderingType;
 

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 3/4] rust: list: convert to use `#[macro_export_scoped]`
  2026-08-11 12:25 [PATCH 0/4] rust: add `#[macro_export_scoped]` for scoped declarative macro Gary Guo
  2026-08-11 12:25 ` [PATCH 1/4] rust: macros: add `#[macro_export_scoped]` Gary Guo
  2026-08-11 12:25 ` [PATCH 2/4] rust: build_assert: remove macro from crate root Gary Guo
@ 2026-08-11 12:25 ` Gary Guo
  2026-08-11 12:25 ` [PATCH 4/4] rust: io: " Gary Guo
  3 siblings, 0 replies; 5+ messages in thread
From: Gary Guo @ 2026-08-11 12:25 UTC (permalink / raw)
  To: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Breno Leitao, Luis Chamberlain, Russ Weight,
	Lyude Paul
  Cc: linux-kernel, rust-for-linux, driver-core, Gary Guo

Convert list macros that use `#[macro_export]` + `#[doc(hidden)]` trick to
use the `#[macro_export_scoped]` macro.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/kernel/list/arc.rs                |  4 +---
 rust/kernel/list/arc_field.rs          |  4 +---
 rust/kernel/list/impl_list_item_mod.rs | 14 +++++---------
 3 files changed, 7 insertions(+), 15 deletions(-)

diff --git a/rust/kernel/list/arc.rs b/rust/kernel/list/arc.rs
index 209b1173c826..9bb6d2e8104d 100644
--- a/rust/kernel/list/arc.rs
+++ b/rust/kernel/list/arc.rs
@@ -81,8 +81,7 @@ pub unsafe trait TryNewListArc<const ID: u64 = 0>: ListArcSafe<ID> {
 /// The `tracked_by` strategy is usually used by deferring to a field of type
 /// [`AtomicTracker`]. However, it is also possible to defer the tracking to another struct
 /// using also using this macro.
-#[macro_export]
-#[doc(hidden)]
+#[macros::macro_export_scoped]
 macro_rules! impl_list_arc_safe {
     (impl$({$($generics:tt)*})? ListArcSafe<$num:tt> for $t:ty { untracked; } $($rest:tt)*) => {
         impl$(<$($generics)*>)? $crate::list::ListArcSafe<$num> for $t {
@@ -127,7 +126,6 @@ fn try_new_list_arc(&self) -> bool {
 
     () => {};
 }
-pub use impl_list_arc_safe;
 
 /// A wrapper around [`Arc`] that's guaranteed unique for the given id.
 ///
diff --git a/rust/kernel/list/arc_field.rs b/rust/kernel/list/arc_field.rs
index 2ad8aea55993..b59e61e90fe1 100644
--- a/rust/kernel/list/arc_field.rs
+++ b/rust/kernel/list/arc_field.rs
@@ -65,8 +65,7 @@ pub unsafe fn assert_mut(&self) -> &mut T {
 }
 
 /// Defines getters for a [`ListArcField`].
-#[macro_export]
-#[doc(hidden)]
+#[macros::macro_export_scoped]
 macro_rules! define_list_arc_field_getter {
     ($pub:vis fn $name:ident(&self $(<$id:tt>)?) -> &$typ:ty { $field:ident }
      $($rest:tt)*
@@ -94,4 +93,3 @@ macro_rules! define_list_arc_field_getter {
 
     () => {};
 }
-pub use define_list_arc_field_getter;
diff --git a/rust/kernel/list/impl_list_item_mod.rs b/rust/kernel/list/impl_list_item_mod.rs
index 5a3eac9f3cf0..e3ec79089696 100644
--- a/rust/kernel/list/impl_list_item_mod.rs
+++ b/rust/kernel/list/impl_list_item_mod.rs
@@ -4,6 +4,8 @@
 
 //! Helpers for implementing list traits safely.
 
+use macros::macro_export_scoped;
+
 /// Declares that this type has a [`ListLinks<ID>`] field.
 ///
 /// This trait is only used to help implement [`ListItem`] safely. If [`ListItem`] is implemented
@@ -28,8 +30,7 @@ pub unsafe trait HasListLinks<const ID: u64 = 0> {
 }
 
 /// Implements the [`HasListLinks`] trait for the given type.
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! impl_has_list_links {
     ($(impl$({$($generics:tt)*})?
        HasListLinks$(<$id:tt>)?
@@ -55,7 +56,6 @@ unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut $crate::list::ListLinks$(<$
         }
     )*};
 }
-pub use impl_has_list_links;
 
 /// Declares that the [`ListLinks<ID>`] field in this struct is inside a
 /// [`ListLinksSelfPtr<T, ID>`].
@@ -74,8 +74,7 @@ pub unsafe trait HasSelfPtr<T: ?Sized, const ID: u64 = 0>
 }
 
 /// Implements the [`HasListLinks`] and [`HasSelfPtr`] traits for the given type.
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! impl_has_list_links_self_ptr {
     ($(impl$({$($generics:tt)*})?
        HasSelfPtr<$item_type:ty $(, $id:tt)?>
@@ -98,7 +97,6 @@ unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut $crate::list::ListLinks$(<$
         }
     )*};
 }
-pub use impl_has_list_links_self_ptr;
 
 /// Implements the [`ListItem`] trait for the given type.
 ///
@@ -182,8 +180,7 @@ unsafe fn raw_get_list_links(ptr: *mut Self) -> *mut $crate::list::ListLinks$(<$
 ///     }
 /// }
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! impl_list_item {
     (
         $(impl$({$($generics:tt)*})? ListItem<$num:tt> for $self:ty {
@@ -358,4 +355,3 @@ unsafe fn post_remove(me: *mut $crate::list::ListLinks<$num>) -> *const Self {
         }
     )*};
 }
-pub use impl_list_item;

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH 4/4] rust: io: convert to use `#[macro_export_scoped]`
  2026-08-11 12:25 [PATCH 0/4] rust: add `#[macro_export_scoped]` for scoped declarative macro Gary Guo
                   ` (2 preceding siblings ...)
  2026-08-11 12:25 ` [PATCH 3/4] rust: list: convert to use `#[macro_export_scoped]` Gary Guo
@ 2026-08-11 12:25 ` Gary Guo
  3 siblings, 0 replies; 5+ messages in thread
From: Gary Guo @ 2026-08-11 12:25 UTC (permalink / raw)
  To: Miguel Ojeda, Boqun Feng, Björn Roy Baron, Benno Lossin,
	Andreas Hindborg, Alice Ryhl, Trevor Gross, Danilo Krummrich,
	Daniel Almeida, Tamir Duberstein, Alexandre Courbot,
	Onur Özkan, Breno Leitao, Luis Chamberlain, Russ Weight,
	Lyude Paul
  Cc: linux-kernel, rust-for-linux, driver-core, Gary Guo

Convert I/O macros that use `#[macro_export]` + `#[doc(hidden)]` trick to
use the `#[macro_export_scoped]` macro.

Signed-off-by: Gary Guo <gary@garyguo.net>
---
 rust/kernel/io.rs | 27 ++++++++++-----------------
 1 file changed, 10 insertions(+), 17 deletions(-)

diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index 5ce9fd129068..891a27fe59b6 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -9,6 +9,8 @@
     mem::MaybeUninit, //
 };
 
+use macros::macro_export_scoped;
+
 use crate::{
     bindings,
     prelude::*,
@@ -1673,8 +1675,7 @@ pub unsafe fn project_view<U: ?Sized + KnownSize>(
 /// let nested: Mmio<'_, u32> = io_project!(whole, .field);
 /// # Ok::<(), Error>(()) }
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! io_project {
     ($io:expr, $($proj:tt)*) => {{
         #[allow(unused)]
@@ -1688,8 +1689,6 @@ macro_rules! io_project {
         unsafe { view.project_view(ptr) }
     }};
 }
-#[doc(inline)]
-pub use crate::io_project;
 
 /// Read from I/O memory.
 ///
@@ -1707,15 +1706,12 @@ macro_rules! io_project {
 /// let field: u32 = kernel::io::io_read!(mmio, [try: 2].field);
 /// # Ok::<(), Error>(()) }
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! io_read {
     ($io:expr, $($proj:tt)*) => {
-        $crate::io::Io::read_val($crate::io_project!($io, $($proj)*))
+        $crate::io::Io::read_val($crate::io::io_project!($io, $($proj)*))
     };
 }
-#[doc(inline)]
-pub use crate::io_read;
 
 /// Writes to I/O memory.
 ///
@@ -1734,21 +1730,18 @@ macro_rules! io_read {
 /// kernel::io::io_write!(mmio, [try: 2].field, 10);
 /// # Ok::<(), Error>(()) }
 /// ```
-#[macro_export]
-#[doc(hidden)]
+#[macro_export_scoped]
 macro_rules! io_write {
     (@parse [$io:expr] [$($proj:tt)*] [, $val:expr]) => {
-        $crate::io::Io::write_val($crate::io_project!($io, $($proj)*), $val)
+        $crate::io::Io::write_val($crate::io::io_project!($io, $($proj)*), $val)
     };
     (@parse [$io:expr] [$($proj:tt)*] [.$field:tt $($rest:tt)*]) => {
-        $crate::io_write!(@parse [$io] [$($proj)* .$field] [$($rest)*])
+        $crate::io::io_write!(@parse [$io] [$($proj)* .$field] [$($rest)*])
     };
     (@parse [$io:expr] [$($proj:tt)*] [[$flavor:ident: $index:expr] $($rest:tt)*]) => {
-        $crate::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($rest)*])
+        $crate::io::io_write!(@parse [$io] [$($proj)* [$flavor: $index]] [$($rest)*])
     };
     ($io:expr, $($rest:tt)*) => {
-        $crate::io_write!(@parse [$io] [] [$($rest)*])
+        $crate::io::io_write!(@parse [$io] [] [$($rest)*])
     };
 }
-#[doc(inline)]
-pub use crate::io_write;

-- 
2.54.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2026-08-11 12:26 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-11 12:25 [PATCH 0/4] rust: add `#[macro_export_scoped]` for scoped declarative macro Gary Guo
2026-08-11 12:25 ` [PATCH 1/4] rust: macros: add `#[macro_export_scoped]` Gary Guo
2026-08-11 12:25 ` [PATCH 2/4] rust: build_assert: remove macro from crate root Gary Guo
2026-08-11 12:25 ` [PATCH 3/4] rust: list: convert to use `#[macro_export_scoped]` Gary Guo
2026-08-11 12:25 ` [PATCH 4/4] rust: io: " Gary Guo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).