Messages in this thread Patch in this message |  | | From | Danilo Krummrich <> | | Subject | [PATCH 03/24] rust: devres: add ForLt support to Devres | | Date | Tue, 28 Apr 2026 00:11:01 +0200 |
| |
Use ForLt::cast_ref() in Devres access methods, enabling lifetime shortening for types that are covariant over their lifetime parameter.
This is a no-op for 'static types, but prepares Devres for use with lifetime-parameterized types such as pci::Bar<'_, SIZE>.
Add DevresGuard as a wrapper around RevocableGuard that applies ForLt::cast_ref() on deref().
Signed-off-by: Danilo Krummrich <dakr@kernel.org> --- rust/kernel/devres.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-)
diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs index 9e5f93aed20c..7baabcdb1ad3 100644 --- a/rust/kernel/devres.rs +++ b/rust/kernel/devres.rs @@ -24,6 +24,7 @@ Arc, // }, types::{ + ForLt, ForeignOwnable, Opaque, // }, @@ -324,22 +325,26 @@ pub fn access<'a>(&'a self, dev: &'a Device<Bound>) -> Result<&'a T> { // SAFETY: `dev` being the same device as the device this `Devres` has been created for // proves that `self.data` hasn't been revoked and is guaranteed to not be revoked as long // as `dev` lives; `dev` lives at least as long as `self`. - Ok(unsafe { self.data().access() }) + Ok(<ForLt!(T)>::cast_ref(unsafe { self.data().access() })) } /// [`Devres`] accessor for [`Revocable::try_access`]. - pub fn try_access(&self) -> Option<RevocableGuard<'_, T>> { - self.data().try_access() + #[allow(clippy::type_complexity)] + pub fn try_access(&self) -> Option<DevresGuard<'_, ForLt!(T)>> { + self.data().try_access().map(DevresGuard) } /// [`Devres`] accessor for [`Revocable::try_access_with`]. pub fn try_access_with<R, F: FnOnce(&T) -> R>(&self, f: F) -> Option<R> { - self.data().try_access_with(f) + self.data() + .try_access_with(|data| f(<ForLt!(T)>::cast_ref(data))) } /// [`Devres`] accessor for [`Revocable::try_access_with_guard`]. pub fn try_access_with_guard<'a>(&'a self, guard: &'a rcu::Guard) -> Option<&'a T> { - self.data().try_access_with_guard(guard) + self.data() + .try_access_with_guard(guard) + .map(<ForLt!(T)>::cast_ref) } } @@ -365,6 +370,20 @@ fn drop(&mut self) { } } +/// Guard returned by [`Devres::try_access`]. +/// +/// Dereferences to `F::Of<'a>`, applying [`ForLt::cast_ref`] to shorten the lifetime of the +/// stored data to the guard's borrow lifetime. +pub struct DevresGuard<'a, F: ForLt>(RevocableGuard<'a, F::Of<'static>>); + +impl<'a, F: ForLt> core::ops::Deref for DevresGuard<'a, F> { + type Target = F::Of<'a>; + + fn deref(&self) -> &Self::Target { + F::cast_ref(&*self.0) + } +} + /// Consume `data` and [`Drop::drop`] `data` once `dev` is unbound. fn register_foreign<P>(dev: &Device<Bound>, data: P) -> Result where -- 2.54.0
|  |