* [RFC PATCH 0/7] Introduce HasField infrastructure
@ 2026-01-28 21:53 Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 1/7] rust: types: Introduce HasField trait and derive macro Boqun Feng
` (8 more replies)
0 siblings, 9 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
Currently we have a few similar places where we use a `Has*` trait to
describe that a data structure has some types of field in it so that the
containing type can do something with it. There are also a `impl_has_*!`
macro to help implement the trait. While it's working, but it's less
ergonomic to me, especially considering the amount of the work we need
to do for something new (e.g. rcu_head).
Therefore here is the effort to unify them into a proc-macro based
solution. `Field` and `HasField` traits are introduced to generify the
"Has A" relationship, and a derive macro `#[derive(HasField)]` is also
added to support automatically implementing `HasField` trait.
This series convert a few users (Work, HrTimer) and introduce a new
`Field` type `RcuHead`. These improvements demonstrate how this
infrastructure can be used.
Some future work is still needed: using `HasField` for `DelayedWork` and
`ListLink` is still missing. Also it's possible to clean up `HasWork`
trait as well.
One known issue is that `#[derive(HasField)]` doesn't play alone with
`#[pin_data]` at the moment, for example:
#[derive(HasField)]
#[pin_data]
struct Foo { .. }
works, but
#[pin_data]
#[derive(HasField)]
struct Foo { .. }
doesn't. Maybe it's by design or maybe something could be improved by
pin-init.
The patchset is based on today's rust/rust-next, top commit is:
a7c013f77953 ('Merge patch series "refactor Rust proc macros with `syn`"')
Regards,
Boqun
Boqun Feng (7):
rust: types: Introduce HasField trait and derive macro
rust: time: hrtimer: Make `HasField` a super-trait of `HasHrTimer`
rust: workqueue: Add HasField support for Work
drivers: android: binder: Replace `impl_has_work!` with
`#[derive(HasField)]`
rust: sync: Completion: Replace `impl_has_work!` with
`#[derive(HasField)]`
rust: work: Remove `impl_has_work!`
rust: sync: rcu: Introduce RcuHead
drivers/android/binder/process.rs | 6 +-
rust/kernel/field.rs | 73 ++++++++++++++++++++
rust/kernel/lib.rs | 1 +
rust/kernel/prelude.rs | 4 +-
rust/kernel/sync/completion.rs | 8 +--
rust/kernel/sync/rcu.rs | 69 ++++++++++++++++++-
rust/kernel/time/hrtimer.rs | 70 ++++---------------
rust/kernel/workqueue.rs | 109 +++++++++++-------------------
rust/macros/field.rs | 85 +++++++++++++++++++++++
rust/macros/lib.rs | 11 +++
10 files changed, 299 insertions(+), 137 deletions(-)
create mode 100644 rust/kernel/field.rs
create mode 100644 rust/macros/field.rs
--
2.50.1 (Apple Git-155)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [RFC PATCH 1/7] rust: types: Introduce HasField trait and derive macro
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 2/7] rust: time: hrtimer: Make `HasField` a super-trait of `HasHrTimer` Boqun Feng
` (7 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
In order to unify all the `Has*` infrastrutures, a generic `HasField`
trait is added along with a derive macro `#[derive(HasField)]` which
allows generate implementation of `HasField` automatically, e.g.
#[derive(HasField)]
struct Base {
a: i32;
b: i32;
#[field]
f1: Field<Base, 1>,
#[field]
f2: Field<Base, 2>,
}
two implementations `impl HasField<Base, Field<Base, 1>>` and `impl
HasField<Base, Field<Base, 2>>` will be generated with `&raw mut` and
`container_of!()`.
This simplifies the usage of the current `Has*` traits, namely `HasWork`
and `HasHrTimer`, and eases the introduction of more `Field` type in the
future.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
rust/kernel/field.rs | 73 ++++++++++++++++++++++++++++++++++++
rust/kernel/lib.rs | 1 +
rust/kernel/prelude.rs | 4 +-
rust/macros/field.rs | 85 ++++++++++++++++++++++++++++++++++++++++++
rust/macros/lib.rs | 11 ++++++
5 files changed, 173 insertions(+), 1 deletion(-)
create mode 100644 rust/kernel/field.rs
create mode 100644 rust/macros/field.rs
diff --git a/rust/kernel/field.rs b/rust/kernel/field.rs
new file mode 100644
index 000000000000..347387731d71
--- /dev/null
+++ b/rust/kernel/field.rs
@@ -0,0 +1,73 @@
+// SPDX-License-Identifier: GPL-2.0
+
+//! Field types to describe a field inside a struct.
+
+/// A field.
+///
+/// The generic type `T` is usually the type that contains the field. For some field types, it
+/// needs to be generic over the type containing it, because it needs to be initialized with
+/// container-type-specific callbacks. For other types, simply implement [`Field<T>`] for all `T`
+/// to indicate there is no restriction.
+pub trait Field<T>: Sized {}
+
+/// A struct `T` that has a field `F`.
+///
+/// # Safety
+///
+/// The methods [`raw_get_field()`] and [`field_container_of()`] must return valid pointers and
+/// must be true inverses of each other; that is, they must satisfy the following invariants: -
+/// `field_container_of(raw_get_field(ptr)) == ptr` for any `ptr: *mut Self`. -
+/// `raw_get_field(field_container_of(ptr)) == ptr` for any `ptr: *mut Field<T>`.
+///
+/// Use [`macros::HasField`] to generate the impls automatically.
+///
+/// # Examples
+///
+/// ```
+/// # use core::marker::PhantomData;
+/// use kernel::{
+/// macros::HasField,
+/// field::{
+/// Field,
+/// HasField, //
+/// }, //
+/// };
+///
+/// struct Work<T, const ID: u64> {
+/// _x: isize,
+/// _inner: PhantomData<T>,
+/// }
+///
+/// // Declare that `Work` is a `Field`.
+/// impl<T, const ID: u64> Field<T> for Work<T, ID> {}
+///
+/// #[derive(HasField)]
+/// struct B {
+/// #[field]
+/// w: Work<B, 2>,
+/// a: i32,
+/// }
+///
+/// const _: () = {
+/// const fn assert_has_field<T: HasField<T, Work<T, 2>>>() { }
+/// assert_has_field::<B>();
+/// };
+/// ```
+///
+/// [`raw_get_field()`]: HasField::raw_get_field
+/// [`field_container_of()`]: HasField::field_container_of
+pub unsafe trait HasField<T, F: Field<T>> {
+ /// Returns a pointer to the [`Field<T>`] field.
+ ///
+ /// # Safety
+ ///
+ /// The provided pointer must point at a valid struct of type `Self`.
+ unsafe fn raw_get_field(ptr: *mut Self) -> *mut F;
+
+ /// Returns a pointer to the struct containing [`Field<T>`] field.
+ ///
+ /// # Safety
+ ///
+ /// The pointer must point at a [`Field<T>`] field in a struct of type `Self`.
+ unsafe fn field_container_of(ptr: *mut F) -> *mut Self;
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index f812cf120042..36259aac1843 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -93,6 +93,7 @@
pub mod drm;
pub mod error;
pub mod faux;
+pub mod field;
#[cfg(CONFIG_RUST_FW_LOADER_ABSTRACTIONS)]
pub mod firmware;
pub mod fmt;
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 2877e3f7b6d3..3668ef42046b 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -25,10 +25,12 @@
pub use crate::alloc::{flags::*, Box, KBox, KVBox, KVVec, KVec, VBox, VVec, Vec};
#[doc(no_inline)]
-pub use macros::{export, fmt, kunit_tests, module, vtable};
+pub use macros::{export, fmt, kunit_tests, module, vtable, HasField};
pub use pin_init::{init, pin_data, pin_init, pinned_drop, InPlaceWrite, Init, PinInit, Zeroable};
+pub use super::field::{Field, HasField};
+
pub use super::{build_assert, build_error};
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
diff --git a/rust/macros/field.rs b/rust/macros/field.rs
new file mode 100644
index 000000000000..3d32e5089f27
--- /dev/null
+++ b/rust/macros/field.rs
@@ -0,0 +1,85 @@
+// SPDX-License-Identifier: GPL-2.0
+
+use proc_macro2::{Span, TokenStream};
+use quote::quote;
+use syn::{
+ spanned::Spanned, Data, DataStruct, DeriveInput, Error, Fields, Generics, Ident, Result, Type,
+};
+
+fn impl_has_field(base: &Ident, field: &Ident, ty: &Type, generics: &Generics) -> TokenStream {
+ let (impl_generics, type_generics, where_clause) = generics.split_for_impl();
+
+ quote!(
+ // SAFETY: The implementation of `raw_get_field()` only compiles if the field has the
+ // right type.
+ unsafe impl #impl_generics
+ HasField<#base #type_generics, #ty>
+ for #base #type_generics
+ #where_clause {
+ #[inline(always)]
+ unsafe fn raw_get_field(ptr: *mut Self) -> *mut #ty {
+ // SAFETY: Per function safety requirement, the pointer is valid.
+ unsafe { &raw mut (*ptr).#field }
+ }
+
+ #[inline(always)]
+ unsafe fn field_container_of(ptr: *mut #ty) -> *mut Self {
+ // SAFETY: Per function safety requirement, the pointer is valid, and it points
+ // to the right field of the struct.
+ unsafe { kernel::container_of!(ptr, Self, #field) }
+ }
+ }
+ )
+}
+fn handle_struct(
+ ident: &Ident,
+ generics: &Generics,
+ st: &DataStruct,
+ span: Span,
+) -> Result<TokenStream> {
+ let mut impls = vec![];
+
+ if let Fields::Named(fields) = &st.fields {
+ for field in &fields.named {
+ let found = field
+ .attrs
+ .iter()
+ .find(|attr| attr.path().is_ident("field"));
+
+ if found.is_some() {
+ if let Some(name) = &field.ident {
+ impls.push(impl_has_field(ident, name, &field.ty, generics));
+ }
+ }
+ }
+
+ Ok(quote!(
+ #(#impls)*
+ ))
+ } else {
+ Err(Error::new(
+ span,
+ "`#[derive(HasField)]` only supports structs with named fields",
+ ))
+ }
+}
+
+pub(crate) fn has_field(input: DeriveInput) -> Result<TokenStream> {
+ let span = input.span();
+ let data = &input.data;
+ let ident = &input.ident;
+ let generics = &input.generics;
+
+ if let Data::Struct(st) = data {
+ let impls = handle_struct(ident, generics, st, span)?;
+
+ Ok(quote!(
+ #impls
+ ))
+ } else {
+ Err(Error::new_spanned(
+ input,
+ "`#[derive(HasField)]` only supports structs",
+ ))
+ }
+}
diff --git a/rust/macros/lib.rs b/rust/macros/lib.rs
index 85b7938c08e5..4fccca0e11af 100644
--- a/rust/macros/lib.rs
+++ b/rust/macros/lib.rs
@@ -13,6 +13,7 @@
mod concat_idents;
mod export;
+mod field;
mod fmt;
mod helpers;
mod kunit;
@@ -486,3 +487,13 @@ pub fn kunit_tests(attr: TokenStream, input: TokenStream) -> TokenStream {
.unwrap_or_else(|e| e.into_compile_error())
.into()
}
+
+/// Derives the implementation for `HasField`.
+///
+/// See the documentation of `HasField` for more information.
+#[proc_macro_derive(HasField, attributes(field))]
+pub fn has_field(input: TokenStream) -> TokenStream {
+ field::has_field(parse_macro_input!(input))
+ .unwrap_or_else(|e| e.into_compile_error())
+ .into()
+}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH 2/7] rust: time: hrtimer: Make `HasField` a super-trait of `HasHrTimer`
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 1/7] rust: types: Introduce HasField trait and derive macro Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 3/7] rust: workqueue: Add HasField support for Work Boqun Feng
` (6 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
This decouples the hrtimer mode part from the `HasField` part of a
`HasHrTimer`, `impl_has_hr_timer` also gets removed, as we can do:
#[has_field]
#[pin]
struct MyStruct {
a: i32,
#[field]
timer: HrTimer<MyStruct>,
}
impl HasHrTimer<MyStruct> for MyStruct {
type TimerMode = ...;
}
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
rust/kernel/time/hrtimer.rs | 70 ++++++++-----------------------------
1 file changed, 15 insertions(+), 55 deletions(-)
diff --git a/rust/kernel/time/hrtimer.rs b/rust/kernel/time/hrtimer.rs
index 856d2d929a00..eef6d60f5adb 100644
--- a/rust/kernel/time/hrtimer.rs
+++ b/rust/kernel/time/hrtimer.rs
@@ -98,6 +98,8 @@ unsafe impl<T> Send for HrTimer<T> {}
// on a timer from multiple threads.
unsafe impl<T> Sync for HrTimer<T> {}
+impl<T> Field<T> for HrTimer<T> {}
+
impl<T> HrTimer<T> {
/// Return an initializer for a new timer instance.
pub fn new() -> impl PinInit<Self>
@@ -417,17 +419,7 @@ pub unsafe trait HrTimerHandle {
}
/// Implemented by structs that contain timer nodes.
-///
-/// Clients of the timer API would usually safely implement this trait by using
-/// the [`crate::impl_has_hr_timer`] macro.
-///
-/// # Safety
-///
-/// Implementers of this trait must ensure that the implementer has a
-/// [`HrTimer`] field and that all trait methods are implemented according to
-/// their documentation. All the methods of this trait must operate on the same
-/// field.
-pub unsafe trait HasHrTimer<T> {
+pub trait HasHrTimer<T>: HasField<T, HrTimer<T>> {
/// The operational mode associated with this timer.
///
/// This defines how the expiration value is interpreted.
@@ -441,7 +433,11 @@ pub unsafe trait HasHrTimer<T> {
/// # Safety
///
/// `this` must be a valid pointer.
- unsafe fn raw_get_timer(this: *const Self) -> *const HrTimer<T>;
+ #[inline]
+ unsafe fn raw_get_timer(this: *const Self) -> *const HrTimer<T> {
+ // SAFETY: Per function safety requirement, `this` is a valid pointer.
+ unsafe { <Self as HasField<_, _>>::raw_get_field(this.cast_mut()) }.cast_const()
+ }
/// Return a pointer to the struct that is containing the [`HrTimer`] pointed
/// to by `ptr`.
@@ -452,9 +448,15 @@ pub unsafe trait HasHrTimer<T> {
/// # Safety
///
/// `ptr` must point to a [`HrTimer<T>`] field in a struct of type `Self`.
+ #[inline]
unsafe fn timer_container_of(ptr: *mut HrTimer<T>) -> *mut Self
where
- Self: Sized;
+ Self: Sized,
+ {
+ // SAFETY: Per function safety requirement, `ptr` is a valid pointer and points to a
+ // `HrTimer` field in a struct.
+ unsafe { <Self as HasField<_, _>>::field_container_of(ptr) }
+ }
/// Get pointer to the contained `bindings::hrtimer` struct.
///
@@ -731,48 +733,6 @@ pub fn forward_now(&mut self, duration: Delta) -> u64 {
}
}
-/// Use to implement the [`HasHrTimer<T>`] trait.
-///
-/// See [`module`] documentation for an example.
-///
-/// [`module`]: crate::time::hrtimer
-#[macro_export]
-macro_rules! impl_has_hr_timer {
- (
- impl$({$($generics:tt)*})?
- HasHrTimer<$timer_type:ty>
- for $self:ty
- {
- mode : $mode:ty,
- field : self.$field:ident $(,)?
- }
- $($rest:tt)*
- ) => {
- // SAFETY: This implementation of `raw_get_timer` only compiles if the
- // field has the right type.
- unsafe impl$(<$($generics)*>)? $crate::time::hrtimer::HasHrTimer<$timer_type> for $self {
- type TimerMode = $mode;
-
- #[inline]
- unsafe fn raw_get_timer(
- this: *const Self,
- ) -> *const $crate::time::hrtimer::HrTimer<$timer_type> {
- // SAFETY: The caller promises that the pointer is not dangling.
- unsafe { ::core::ptr::addr_of!((*this).$field) }
- }
-
- #[inline]
- unsafe fn timer_container_of(
- ptr: *mut $crate::time::hrtimer::HrTimer<$timer_type>,
- ) -> *mut Self {
- // SAFETY: As per the safety requirement of this function, `ptr`
- // is pointing inside a `$timer_type`.
- unsafe { ::kernel::container_of!(ptr, $timer_type, $field) }
- }
- }
- }
-}
-
mod arc;
pub use arc::ArcHrTimerHandle;
mod pin;
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH 3/7] rust: workqueue: Add HasField support for Work
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 1/7] rust: types: Introduce HasField trait and derive macro Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 2/7] rust: time: hrtimer: Make `HasField` a super-trait of `HasHrTimer` Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 4/7] drivers: android: binder: Replace `impl_has_work!` with `#[derive(HasField)]` Boqun Feng
` (5 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
Implement `HasWork` via `HasField` so that manually impl_has_work!() is
no longer needed.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
rust/kernel/workqueue.rs | 60 +++++++++++++++++++++++++---------------
1 file changed, 38 insertions(+), 22 deletions(-)
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 706e833e9702..2dcfd3eace39 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -34,19 +34,17 @@
//!
//! ```
//! use kernel::sync::Arc;
-//! use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
+//! use kernel::workqueue::{self, new_work, Work, WorkItem};
//!
+//! #[derive(HasField)]
//! #[pin_data]
//! struct MyStruct {
//! value: i32,
//! #[pin]
+//! #[field]
//! work: Work<MyStruct>,
//! }
//!
-//! impl_has_work! {
-//! impl HasWork<Self> for MyStruct { self.work }
-//! }
-//!
//! impl MyStruct {
//! fn new(value: i32) -> Result<Arc<Self>> {
//! Arc::pin_init(pin_init!(MyStruct {
@@ -76,23 +74,21 @@
//!
//! ```
//! use kernel::sync::Arc;
-//! use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
+//! use kernel::workqueue::{self, new_work, Work, WorkItem};
//!
+//! #[derive(HasField)]
//! #[pin_data]
//! struct MyStruct {
//! value_1: i32,
//! value_2: i32,
//! #[pin]
+//! #[field]
//! work_1: Work<MyStruct, 1>,
//! #[pin]
+//! #[field]
//! work_2: Work<MyStruct, 2>,
//! }
//!
-//! impl_has_work! {
-//! impl HasWork<Self, 1> for MyStruct { self.work_1 }
-//! impl HasWork<Self, 2> for MyStruct { self.work_2 }
-//! }
-//!
//! impl MyStruct {
//! fn new(value_1: i32, value_2: i32) -> Result<Arc<Self>> {
//! Arc::pin_init(pin_init!(MyStruct {
@@ -188,6 +184,11 @@
use crate::{
alloc::{AllocError, Flags},
container_of,
+ field::{
+ Field,
+ HasField, //
+ },
+ macros::HasField,
prelude::*,
sync::Arc,
sync::LockClassKey,
@@ -349,9 +350,11 @@ pub fn try_spawn<T: 'static + Send + FnOnce()>(
/// A helper type used in [`try_spawn`].
///
/// [`try_spawn`]: Queue::try_spawn
+#[derive(HasField)]
#[pin_data]
struct ClosureWork<T> {
#[pin]
+ #[field]
work: Work<ClosureWork<T>>,
func: Option<T>,
}
@@ -534,19 +537,17 @@ pub unsafe fn raw_get(ptr: *const Self) -> *mut bindings::work_struct {
/// Declares that a type contains a [`Work<T, ID>`].
///
-/// The intended way of using this trait is via the [`impl_has_work!`] macro. You can use the macro
-/// like this:
+/// The intended way of using this trait is via the `#[derive(HasField)]` macro. You can use the
+/// macro like this:
///
-/// ```no_run
-/// use kernel::workqueue::{impl_has_work, Work};
+/// ```
+/// use kernel::workqueue::Work;
///
+/// #[derive(HasField)]
/// struct MyWorkItem {
+/// #[field]
/// work_field: Work<MyWorkItem, 1>,
/// }
-///
-/// impl_has_work! {
-/// impl HasWork<MyWorkItem, 1> for MyWorkItem { self.work_field }
-/// }
/// ```
///
/// Note that since the [`Work`] type is annotated with an id, you can have several `work_struct`
@@ -559,7 +560,6 @@ pub unsafe fn raw_get(ptr: *const Self) -> *mut bindings::work_struct {
/// - `work_container_of(raw_get_work(ptr)) == ptr` for any `ptr: *mut Self`.
/// - `raw_get_work(work_container_of(ptr)) == ptr` for any `ptr: *mut Work<T, ID>`.
///
-/// [`impl_has_work!`]: crate::impl_has_work
/// [`raw_get_work`]: HasWork::raw_get_work
/// [`work_container_of`]: HasWork::work_container_of
pub unsafe trait HasWork<T, const ID: u64 = 0> {
@@ -627,8 +627,24 @@ unsafe fn work_container_of(
}
pub use impl_has_work;
-impl_has_work! {
- impl{T} HasWork<Self> for ClosureWork<T> { self.work }
+impl<T, const ID: u64> Field<T> for Work<T, ID> {}
+
+/// SAFETY: Per the safety requirement of `HasField`, `raw_get_field()` and `field_container_of()`
+/// return valid pointers and are true inverses of each other, hence the implementation below
+/// fulfills `HasWork`'s safety requirement as well.
+unsafe impl<T: HasField<T, Work<T, ID>>, const ID: u64> HasWork<T, ID> for T {
+ #[inline]
+ unsafe fn raw_get_work(ptr: *mut Self) -> *mut Work<T, ID> {
+ // SAFETY: Per the function safety requirement, `ptr` is a valid pointer.
+ unsafe { <T as HasField<T, Work<T, ID>>>::raw_get_field(ptr) }
+ }
+
+ #[inline]
+ unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self {
+ // SAFETY: Per the function safety requirement, `ptr` is a valid pointer, and it points to
+ // a work field in struct `T`.
+ unsafe { <T as HasField<T, Work<T, ID>>>::field_container_of(ptr) }
+ }
}
/// Links for a delayed work item.
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH 4/7] drivers: android: binder: Replace `impl_has_work!` with `#[derive(HasField)]`
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
` (2 preceding siblings ...)
2026-01-28 21:53 ` [RFC PATCH 3/7] rust: workqueue: Add HasField support for Work Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 5/7] rust: sync: Completion: " Boqun Feng
` (4 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
`#[derive(HasField)]` offers less code and better ergonomic for defining
a struct with a Work in it. Hence replace the current usage of
`impl_has_work!()`.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
drivers/android/binder/process.rs | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/android/binder/process.rs b/drivers/android/binder/process.rs
index 132055b4790f..2a2510e3a0cb 100644
--- a/drivers/android/binder/process.rs
+++ b/drivers/android/binder/process.rs
@@ -423,6 +423,7 @@ fn new() -> Self {
/// Strictly speaking, there can be multiple of these per process. There is one for each binder fd
/// that a process has opened, so processes using several binder contexts have several `Process`
/// objects. This ensures that the contexts are fully separated.
+#[derive(HasField)]
#[pin_data]
pub(crate) struct Process {
pub(crate) ctx: Arc<Context>,
@@ -451,6 +452,7 @@ pub(crate) struct Process {
// Work node for deferred work item.
#[pin]
+ #[field]
defer_work: Work<Process>,
// Links for process list in Context.
@@ -460,10 +462,6 @@ pub(crate) struct Process {
pub(crate) stats: BinderStats,
}
-kernel::impl_has_work! {
- impl HasWork<Process> for Process { self.defer_work }
-}
-
kernel::list::impl_list_arc_safe! {
impl ListArcSafe<0> for Process { untracked; }
}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH 5/7] rust: sync: Completion: Replace `impl_has_work!` with `#[derive(HasField)]`
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
` (3 preceding siblings ...)
2026-01-28 21:53 ` [RFC PATCH 4/7] drivers: android: binder: Replace `impl_has_work!` with `#[derive(HasField)]` Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 6/7] rust: work: Remove `impl_has_work!` Boqun Feng
` (3 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
`#[derive(HasField)]` offers less code and better ergnomic for defining
a struct with a Work in it. Hence replace the current usage of
`impl_has_work!()`.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
rust/kernel/sync/completion.rs | 8 +++-----
1 file changed, 3 insertions(+), 5 deletions(-)
diff --git a/rust/kernel/sync/completion.rs b/rust/kernel/sync/completion.rs
index c50012a940a3..c4af58924fe3 100644
--- a/rust/kernel/sync/completion.rs
+++ b/rust/kernel/sync/completion.rs
@@ -17,20 +17,18 @@
///
/// ```
/// use kernel::sync::{Arc, Completion};
-/// use kernel::workqueue::{self, impl_has_work, new_work, Work, WorkItem};
+/// use kernel::workqueue::{self, new_work, Work, WorkItem};
///
+/// #[derive(HasField)]
/// #[pin_data]
/// struct MyTask {
/// #[pin]
+/// #[field]
/// work: Work<MyTask>,
/// #[pin]
/// done: Completion,
/// }
///
-/// impl_has_work! {
-/// impl HasWork<Self> for MyTask { self.work }
-/// }
-///
/// impl MyTask {
/// fn new() -> Result<Arc<Self>> {
/// let this = Arc::pin_init(pin_init!(MyTask {
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH 6/7] rust: work: Remove `impl_has_work!`
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
` (4 preceding siblings ...)
2026-01-28 21:53 ` [RFC PATCH 5/7] rust: sync: Completion: " Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 7/7] rust: sync: rcu: Introduce RcuHead Boqun Feng
` (2 subsequent siblings)
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
Now all in-tree users of `impl_has_work!()` are converted to use
`#[derive(HasField)]`, hence remove it.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
rust/kernel/workqueue.rs | 53 ++--------------------------------------
1 file changed, 2 insertions(+), 51 deletions(-)
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 2dcfd3eace39..37fbf348c760 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -578,55 +578,6 @@ pub unsafe trait HasWork<T, const ID: u64 = 0> {
unsafe fn work_container_of(ptr: *mut Work<T, ID>) -> *mut Self;
}
-/// Used to safely implement the [`HasWork<T, ID>`] trait.
-///
-/// # Examples
-///
-/// ```
-/// use kernel::sync::Arc;
-/// use kernel::workqueue::{self, impl_has_work, Work};
-///
-/// struct MyStruct<'a, T, const N: usize> {
-/// work_field: Work<MyStruct<'a, T, N>, 17>,
-/// f: fn(&'a [T; N]),
-/// }
-///
-/// impl_has_work! {
-/// impl{'a, T, const N: usize} HasWork<MyStruct<'a, T, N>, 17>
-/// for MyStruct<'a, T, N> { self.work_field }
-/// }
-/// ```
-#[macro_export]
-macro_rules! impl_has_work {
- ($(impl$({$($generics:tt)*})?
- HasWork<$work_type:ty $(, $id:tt)?>
- for $self:ty
- { self.$field:ident }
- )*) => {$(
- // SAFETY: The implementation of `raw_get_work` only compiles if the field has the right
- // type.
- unsafe impl$(<$($generics)+>)? $crate::workqueue::HasWork<$work_type $(, $id)?> for $self {
- #[inline]
- unsafe fn raw_get_work(ptr: *mut Self) -> *mut $crate::workqueue::Work<$work_type $(, $id)?> {
- // SAFETY: The caller promises that the pointer is not dangling.
- unsafe {
- ::core::ptr::addr_of_mut!((*ptr).$field)
- }
- }
-
- #[inline]
- unsafe fn work_container_of(
- ptr: *mut $crate::workqueue::Work<$work_type $(, $id)?>,
- ) -> *mut Self {
- // SAFETY: The caller promises that the pointer points at a field of the right type
- // in the right kind of struct.
- unsafe { $crate::container_of!(ptr, Self, $field) }
- }
- }
- )*};
-}
-pub use impl_has_work;
-
impl<T, const ID: u64> Field<T> for Work<T, ID> {}
/// SAFETY: Per the safety requirement of `HasField`, `raw_get_field()` and `field_container_of()`
@@ -746,8 +697,8 @@ pub unsafe trait HasDelayedWork<T, const ID: u64 = 0>: HasWork<T, ID> {}
/// Used to safely implement the [`HasDelayedWork<T, ID>`] trait.
///
-/// This macro also implements the [`HasWork`] trait, so you do not need to use [`impl_has_work!`]
-/// when using this macro.
+/// This macro also implements the [`HasWork`] trait, so you do not need to use `#[has_field]` when
+/// using this macro.
///
/// # Examples
///
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [RFC PATCH 7/7] rust: sync: rcu: Introduce RcuHead
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
` (5 preceding siblings ...)
2026-01-28 21:53 ` [RFC PATCH 6/7] rust: work: Remove `impl_has_work!` Boqun Feng
@ 2026-01-28 21:53 ` Boqun Feng
2026-02-04 14:20 ` [RFC PATCH 0/7] Introduce HasField infrastructure Gary Guo
2026-02-17 1:21 ` Joel Fernandes
8 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-01-28 21:53 UTC (permalink / raw)
To: linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Boqun Feng, Gary Guo, Björn Roy Baron, Benno Lossin,
Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
In order to support RCU delay free (call_rcu() and kfree_rcu()), the
abstraction of the `rcu_head` is introduced. Types that want to support
RCU delay free can specify a `RcuHead<T>` in it, e.g.
#[derive(HasField)]
struct Foo {
a: i32,
b: i32,
#[field]
rcu_head: RcuHead,
}
A wrapper `WithRcuHead<T>` is also provided for users that want to
specify a generic `T` with a rcu_head.
Signed-off-by: Boqun Feng <boqun.feng@gmail.com>
---
rust/kernel/sync/rcu.rs | 69 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 68 insertions(+), 1 deletion(-)
diff --git a/rust/kernel/sync/rcu.rs b/rust/kernel/sync/rcu.rs
index a32bef6e490b..694ca2f54953 100644
--- a/rust/kernel/sync/rcu.rs
+++ b/rust/kernel/sync/rcu.rs
@@ -4,7 +4,14 @@
//!
//! C header: [`include/linux/rcupdate.h`](srctree/include/linux/rcupdate.h)
-use crate::{bindings, types::NotThreadSafe};
+use crate::{
+ bindings,
+ field::{Field, HasField},
+ macros::HasField,
+ types::{NotThreadSafe, Opaque},
+};
+
+use core::ops::Deref;
/// Evidence that the RCU read side lock is held on the current thread/CPU.
///
@@ -50,3 +57,63 @@ fn drop(&mut self) {
pub fn read_lock() -> Guard {
Guard::new()
}
+
+/// RCU head for call backs.
+///
+/// # Examples
+///
+/// Use `#[derive(HasField)]` macro to specify a struct has a RCU head.
+///
+/// ```
+/// use kernel::sync::rcu::RcuHead;
+///
+/// #[derive(HasField)]
+/// struct Foo {
+/// a: i32,
+/// #[field]
+/// rcu_head: RcuHead,
+/// b: i32,
+/// }
+///
+/// const _: () = {
+/// const fn assert_has_field<T: HasField<T, RcuHead>>() { }
+/// assert_has_field::<Foo>();
+/// };
+/// ```
+#[repr(transparent)]
+pub struct RcuHead(Opaque<bindings::callback_head>);
+
+impl<T> Field<T> for RcuHead {}
+
+// SAFETY: `callback_head` doesn't hold anything local to the current execution context, so it's
+// safe to transfer to another execution context.
+unsafe impl Send for RcuHead {}
+// SAFETY: `callback_head` should only be used when it's in the destructor, and accesses to it are
+// already unsafe, hence make it `Sync`.
+unsafe impl Sync for RcuHead {}
+
+/// A wrapper that adds an `RcuHead` on `T`.
+#[derive(HasField)]
+pub struct WithRcuHead<T> {
+ #[field]
+ head: RcuHead,
+ data: T,
+}
+
+impl<T> WithRcuHead<T> {
+ /// Creates a new wrapper on `T` with `RcuHead`.
+ pub fn new(data: T) -> Self {
+ Self {
+ head: RcuHead(Opaque::zeroed()),
+ data,
+ }
+ }
+}
+
+impl<T> Deref for WithRcuHead<T> {
+ type Target = T;
+
+ fn deref(&self) -> &Self::Target {
+ &self.data
+ }
+}
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/7] Introduce HasField infrastructure
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
` (6 preceding siblings ...)
2026-01-28 21:53 ` [RFC PATCH 7/7] rust: sync: rcu: Introduce RcuHead Boqun Feng
@ 2026-02-04 14:20 ` Gary Guo
2026-02-05 20:47 ` Boqun Feng
2026-02-17 1:21 ` Joel Fernandes
8 siblings, 1 reply; 12+ messages in thread
From: Gary Guo @ 2026-02-04 14:20 UTC (permalink / raw)
To: Boqun Feng, linux-kernel, rust-for-linux, rcu
Cc: Greg Kroah-Hartman, Arve Hjønnevåg, Todd Kjos,
Christian Brauner, Carlos Llamas, Alice Ryhl, Miguel Ojeda,
Gary Guo, Björn Roy Baron, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Paul E. McKenney,
Frederic Weisbecker, Neeraj Upadhyay, Joel Fernandes,
Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
On Wed Jan 28, 2026 at 9:53 PM GMT, Boqun Feng wrote:
> Currently we have a few similar places where we use a `Has*` trait to
> describe that a data structure has some types of field in it so that the
> containing type can do something with it. There are also a `impl_has_*!`
> macro to help implement the trait. While it's working, but it's less
> ergonomic to me, especially considering the amount of the work we need
> to do for something new (e.g. rcu_head).
>
> Therefore here is the effort to unify them into a proc-macro based
> solution. `Field` and `HasField` traits are introduced to generify the
> "Has A" relationship, and a derive macro `#[derive(HasField)]` is also
> added to support automatically implementing `HasField` trait.
>
> This series convert a few users (Work, HrTimer) and introduce a new
> `Field` type `RcuHead`. These improvements demonstrate how this
> infrastructure can be used.
>
> Some future work is still needed: using `HasField` for `DelayedWork` and
> `ListLink` is still missing. Also it's possible to clean up `HasWork`
> trait as well.
>
> One known issue is that `#[derive(HasField)]` doesn't play alone with
> `#[pin_data]` at the moment, for example:
>
> #[derive(HasField)]
> #[pin_data]
> struct Foo { .. }
>
> works, but
>
> #[pin_data]
> #[derive(HasField)]
> struct Foo { .. }
>
> doesn't. Maybe it's by design or maybe something could be improved by
> pin-init.
>
>
> The patchset is based on today's rust/rust-next, top commit is:
>
> a7c013f77953 ('Merge patch series "refactor Rust proc macros with `syn`"')
>
> Regards,
> Boqun
Hi Boqun,
Thanks for working on this.
You currently divide things into two traits, `Field<T>` which doesn't seem to be
doing anything (actually, why does this need to exist at all?) and
`HasField<T, F>` which defines all the field projection.
For some prior art that attempts to have fields, e.g. my field-projection
experiemnt crate
https://docs.rs/field-projection
and Benno's work on field-representing-types in the Rust language, we opt to
have a type to represent each field instead.
I think we should have a unified projection infrastructure in the kernel, for
both intrusive data structure and I/O projection and others, so I think it's
useful to have types representing fields (and projection in general, this could
also extend to the `register!` macro). For clarity, let me refer to this as
`field_of!(Base, foo)` and the trait is `Projection`.
With this infra, the `HasField` trait would simply looks like this:
trait HasField<Base, FieldType> {
type Field: Projection<Base = Base, Type = FieldType>;
}
and the macro derive would generate something like
impl HasField<MyStruct, Work<MyStruct>> {
type Field = field_of!(MyStruct, name_of_work_field);
}
Best,
Gary
>
> Boqun Feng (7):
> rust: types: Introduce HasField trait and derive macro
> rust: time: hrtimer: Make `HasField` a super-trait of `HasHrTimer`
> rust: workqueue: Add HasField support for Work
> drivers: android: binder: Replace `impl_has_work!` with
> `#[derive(HasField)]`
> rust: sync: Completion: Replace `impl_has_work!` with
> `#[derive(HasField)]`
> rust: work: Remove `impl_has_work!`
> rust: sync: rcu: Introduce RcuHead
>
> drivers/android/binder/process.rs | 6 +-
> rust/kernel/field.rs | 73 ++++++++++++++++++++
> rust/kernel/lib.rs | 1 +
> rust/kernel/prelude.rs | 4 +-
> rust/kernel/sync/completion.rs | 8 +--
> rust/kernel/sync/rcu.rs | 69 ++++++++++++++++++-
> rust/kernel/time/hrtimer.rs | 70 ++++---------------
> rust/kernel/workqueue.rs | 109 +++++++++++-------------------
> rust/macros/field.rs | 85 +++++++++++++++++++++++
> rust/macros/lib.rs | 11 +++
> 10 files changed, 299 insertions(+), 137 deletions(-)
> create mode 100644 rust/kernel/field.rs
> create mode 100644 rust/macros/field.rs
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/7] Introduce HasField infrastructure
2026-02-04 14:20 ` [RFC PATCH 0/7] Introduce HasField infrastructure Gary Guo
@ 2026-02-05 20:47 ` Boqun Feng
0 siblings, 0 replies; 12+ messages in thread
From: Boqun Feng @ 2026-02-05 20:47 UTC (permalink / raw)
To: Gary Guo
Cc: Boqun Feng, linux-kernel, rust-for-linux, rcu, Greg Kroah-Hartman,
Arve Hjønnevåg, Todd Kjos, Christian Brauner,
Carlos Llamas, Alice Ryhl, Miguel Ojeda, Björn Roy Baron,
Benno Lossin, Andreas Hindborg, Trevor Gross, Danilo Krummrich,
Paul E. McKenney, Frederic Weisbecker, Neeraj Upadhyay,
Joel Fernandes, Josh Triplett, Uladzislau Rezki, Steven Rostedt,
Mathieu Desnoyers, Lai Jiangshan, Zqiang, FUJITA Tomonori,
Lyude Paul, Thomas Gleixner, Anna-Maria Behnsen, John Stultz,
Stephen Boyd, Yury Norov (NVIDIA), Vitaly Wool, Tamir Duberstein,
Viresh Kumar, Daniel Almeida, Mitchell Levy, David Gow,
Peter Novak, José Expósito
On Wed, Feb 04, 2026 at 02:20:09PM +0000, Gary Guo wrote:
> On Wed Jan 28, 2026 at 9:53 PM GMT, Boqun Feng wrote:
> > Currently we have a few similar places where we use a `Has*` trait to
> > describe that a data structure has some types of field in it so that the
> > containing type can do something with it. There are also a `impl_has_*!`
> > macro to help implement the trait. While it's working, but it's less
> > ergonomic to me, especially considering the amount of the work we need
> > to do for something new (e.g. rcu_head).
> >
> > Therefore here is the effort to unify them into a proc-macro based
> > solution. `Field` and `HasField` traits are introduced to generify the
> > "Has A" relationship, and a derive macro `#[derive(HasField)]` is also
> > added to support automatically implementing `HasField` trait.
> >
> > This series convert a few users (Work, HrTimer) and introduce a new
> > `Field` type `RcuHead`. These improvements demonstrate how this
> > infrastructure can be used.
> >
> > Some future work is still needed: using `HasField` for `DelayedWork` and
> > `ListLink` is still missing. Also it's possible to clean up `HasWork`
> > trait as well.
> >
> > One known issue is that `#[derive(HasField)]` doesn't play alone with
> > `#[pin_data]` at the moment, for example:
> >
> > #[derive(HasField)]
> > #[pin_data]
> > struct Foo { .. }
> >
> > works, but
> >
> > #[pin_data]
> > #[derive(HasField)]
> > struct Foo { .. }
> >
> > doesn't. Maybe it's by design or maybe something could be improved by
> > pin-init.
> >
> >
> > The patchset is based on today's rust/rust-next, top commit is:
> >
> > a7c013f77953 ('Merge patch series "refactor Rust proc macros with `syn`"')
> >
> > Regards,
> > Boqun
>
> Hi Boqun,
>
> Thanks for working on this.
>
> You currently divide things into two traits, `Field<T>` which doesn't seem to be
> doing anything (actually, why does this need to exist at all?) and
> `HasField<T, F>` which defines all the field projection.
>
Oh, you're right, I don't need `Field<T>` right now. In a certain point,
it was used to constrain all "field types" must be generic over their
container type. But it's not the case now (see RcuHead).
> For some prior art that attempts to have fields, e.g. my field-projection
> experiemnt crate
>
> https://docs.rs/field-projection
>
> and Benno's work on field-representing-types in the Rust language, we opt to
> have a type to represent each field instead.
>
> I think we should have a unified projection infrastructure in the kernel, for
> both intrusive data structure and I/O projection and others, so I think it's
> useful to have types representing fields (and projection in general, this could
> also extend to the `register!` macro). For clarity, let me refer to this as
> `field_of!(Base, foo)` and the trait is `Projection`.
>
Yep, I actually have an example PR integrating that into workqueue:
https://github.com/Rust-for-Linux/field-projection/pull/2
(of course `Work` in that case should be generic over the containing
type, but that's easy to fix)
I guess the next question is: will you and Benno be willing to port
field-projection into kernel source (and keep it aligned with the
language feature), so we can switch to that?
Regards,
Boqun
> With this infra, the `HasField` trait would simply looks like this:
>
> trait HasField<Base, FieldType> {
> type Field: Projection<Base = Base, Type = FieldType>;
> }
>
> and the macro derive would generate something like
>
> impl HasField<MyStruct, Work<MyStruct>> {
> type Field = field_of!(MyStruct, name_of_work_field);
> }
>
> Best,
> Gary
>
[..]
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/7] Introduce HasField infrastructure
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
` (7 preceding siblings ...)
2026-02-04 14:20 ` [RFC PATCH 0/7] Introduce HasField infrastructure Gary Guo
@ 2026-02-17 1:21 ` Joel Fernandes
2026-02-27 15:00 ` Gary Guo
8 siblings, 1 reply; 12+ messages in thread
From: Joel Fernandes @ 2026-02-17 1:21 UTC (permalink / raw)
To: Boqun Feng
Cc: linux-kernel, rust-for-linux, rcu, Greg Kroah-Hartman, Alice Ryhl,
Miguel Ojeda, Gary Guo, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Paul E. McKenney,
Frederic Weisbecker, Neeraj Upadhyay, Josh Triplett,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Tamir Duberstein
On Wed, 28 Jan 2026 13:53:23 -0800, Boqun Feng wrote:
> Therefore here is the effort to unify them into a proc-macro based
> solution. Field and HasField traits are introduced to generify the
> "Has A" relationship, and a derive macro #[derive(HasField)] is also
> added to support automatically implementing HasField trait.
Hi Boqun,
One naming concern: the #[field] attribute feels ambiguous since in
Rust every struct member is already called a "field." When reading:
#[derive(HasField)]
struct MyStruct {
value: i32,
#[field]
work: Work<MyStruct>,
}
it's not immediately obvious why "work" gets #[field] but "value"
does not, as both are struct fields.
Would something like #[project] be clearer?
Similarly, HasField could become HasProjection or ProjectField to
better distinguish the trait's purpose from the general concept of fields.
--
Joel Fernandes
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [RFC PATCH 0/7] Introduce HasField infrastructure
2026-02-17 1:21 ` Joel Fernandes
@ 2026-02-27 15:00 ` Gary Guo
0 siblings, 0 replies; 12+ messages in thread
From: Gary Guo @ 2026-02-27 15:00 UTC (permalink / raw)
To: Joel Fernandes, Boqun Feng
Cc: linux-kernel, rust-for-linux, rcu, Greg Kroah-Hartman, Alice Ryhl,
Miguel Ojeda, Gary Guo, Benno Lossin, Andreas Hindborg,
Trevor Gross, Danilo Krummrich, Paul E. McKenney,
Frederic Weisbecker, Neeraj Upadhyay, Josh Triplett,
Uladzislau Rezki, Steven Rostedt, Mathieu Desnoyers,
Lai Jiangshan, Tamir Duberstein
On Tue Feb 17, 2026 at 1:21 AM GMT, Joel Fernandes wrote:
> On Wed, 28 Jan 2026 13:53:23 -0800, Boqun Feng wrote:
>> Therefore here is the effort to unify them into a proc-macro based
>> solution. Field and HasField traits are introduced to generify the
>> "Has A" relationship, and a derive macro #[derive(HasField)] is also
>> added to support automatically implementing HasField trait.
>
> Hi Boqun,
>
> One naming concern: the #[field] attribute feels ambiguous since in
> Rust every struct member is already called a "field." When reading:
>
> #[derive(HasField)]
> struct MyStruct {
> value: i32,
> #[field]
> work: Work<MyStruct>,
> }
>
> it's not immediately obvious why "work" gets #[field] but "value"
> does not, as both are struct fields.
>
> Would something like #[project] be clearer?
>
> Similarly, HasField could become HasProjection or ProjectField to
> better distinguish the trait's purpose from the general concept of fields.
This is not just for projection, but to establish has-a relation. A struct can
project into any of its fields, but for work/hrtimer use cases, it needs to be
able to find a specific field.
If we want a different name then I'd suggest `#[has]`.
Best,
Gary
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-02-27 15:00 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-01-28 21:53 [RFC PATCH 0/7] Introduce HasField infrastructure Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 1/7] rust: types: Introduce HasField trait and derive macro Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 2/7] rust: time: hrtimer: Make `HasField` a super-trait of `HasHrTimer` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 3/7] rust: workqueue: Add HasField support for Work Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 4/7] drivers: android: binder: Replace `impl_has_work!` with `#[derive(HasField)]` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 5/7] rust: sync: Completion: " Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 6/7] rust: work: Remove `impl_has_work!` Boqun Feng
2026-01-28 21:53 ` [RFC PATCH 7/7] rust: sync: rcu: Introduce RcuHead Boqun Feng
2026-02-04 14:20 ` [RFC PATCH 0/7] Introduce HasField infrastructure Gary Guo
2026-02-05 20:47 ` Boqun Feng
2026-02-17 1:21 ` Joel Fernandes
2026-02-27 15:00 ` Gary Guo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox