On Sun May 17, 2026 at 1:01 AM BST, Danilo Krummrich wrote: > Generalize Registration<T> to Registration<F: ForLt> and > Device::registration_data<F: ForLt>() to return Pin<&F::Of<'_>>. > > The stored 'static lifetime is shortened to the borrow lifetime of &self > via ForLt::cast_ref; ForLt's covariance guarantee makes this sound. > > Signed-off-by: Danilo Krummrich <[email protected]> > --- > drivers/gpu/nova-core/driver.rs | 4 +- > rust/kernel/auxiliary.rs | 68 +++++++++++++++++---------- > samples/rust/rust_driver_auxiliary.rs | 8 ++-- > 3 files changed, 52 insertions(+), 28 deletions(-) > > [snip] > > @@ -389,43 +399,51 @@ struct RegistrationData<T> { > /// This type represents the registration of a [`struct auxiliary_device`]. > When its parent device > /// is unbound, the corresponding auxiliary device will be unregistered from > the system. > /// > -/// The type parameter `T` is the type of the registration data owned by the > registering (parent) > -/// driver. It can be accessed by the auxiliary driver through > -/// [`Device::registration_data()`]. > +/// The type parameter `F` is a [`ForLt`](trait@ForLt) encoding of the > registration > +/// data type. For non-lifetime-parameterized types, use > [`ForLt!(T)`](macro@ForLt). > +/// The data can be accessed by the auxiliary driver through > [`Device::registration_data()`]. > /// > /// # Invariants > /// > /// `self.adev` always holds a valid pointer to an initialized and registered > /// [`struct auxiliary_device`] whose `registration_data_rust` field points > to a > -/// valid `Pin<KBox<RegistrationData<T>>>`. > -pub struct Registration<T: 'static> { > +/// valid `Pin<KBox<RegistrationData<F::Of<'static>>>>`. > +pub struct Registration<F: ForLt> { > adev: NonNull<bindings::auxiliary_device>, > - _data: PhantomData<T>, > + _data: PhantomData<F>, > } > > -impl<T: Send + Sync + 'static> Registration<T> { > +impl<F: ForLt> Registration<F> > +where > + for<'a> F::Of<'a>: Send + Sync, > +{ > /// Create and register a new auxiliary device with the given > registration data. > /// > /// The `data` is owned by the registration and can be accessed through > the auxiliary device > /// via [`Device::registration_data()`]. > - pub fn new<E>( > - parent: &device::Device<device::Bound>, > + pub fn new<'bound, E>( > + parent: &'bound device::Device<device::Bound>, > name: &CStr, > id: u32, > modname: &CStr, > - data: impl PinInit<T, E>, > + data: impl PinInit<F::Of<'bound>, E>, > ) -> Result<Devres<Self>>
I think this is unsound for the reason that I gave in another email https://lore.kernel.org/rust-for-linux/[email protected]/. Best, Gary > where > Error: From<E>, > { > let data = KBox::pin_init::<Error>( > try_pin_init!(RegistrationData { > - type_id: TypeId::of::<T>(), > + type_id: TypeId::of::<F::Of<'static>>(), > data <- data, > }), > GFP_KERNEL, > )?; > > + // SAFETY: Lifetimes are erased and do not affect layout, so > RegistrationData<F::Of<'bound>> > + // and RegistrationData<F::Of<'static>> have identical > representation. > + let data: Pin<KBox<RegistrationData<F::Of<'static>>>> = > + unsafe { core::mem::transmute(data) }; > + > let boxed: KBox<Opaque<bindings::auxiliary_device>> = > KBox::zeroed(GFP_KERNEL)?; > let adev = boxed.get(); > > @@ -455,7 +473,9 @@ pub fn new<E>( > if ret != 0 { > // SAFETY: `registration_data` was set above via > `into_foreign()`. > drop(unsafe { > - > Pin::<KBox<RegistrationData<T>>>::from_foreign((*adev).registration_data_rust) > + Pin::<KBox<RegistrationData<F::Of<'static>>>>::from_foreign( > + (*adev).registration_data_rust, > + ) > }); > > // SAFETY: `adev` is guaranteed to be a valid pointer to a > @@ -478,7 +498,7 @@ pub fn new<E>( > } > }
