[PATCH 1/4] rust: mem: add DropGuard

From: Mohamed Osama

Date: Sun Sep 27 2026 - 06:46:34 EST


Vendor DropGuard from the Rust standard library and re-export it
from kernel::mem.

DropGuard runs a FnOnce callback when the guard is dropped and provides
dismiss() to take ownership of the wrapped value without running the
cleanup callback.

The kernel version removes unstable const-trait machinery from the
upstream implementation and adds #[inline] where appropriate.

Suggested-by: Gary Guo <gary@xxxxxxxxxxx>
Signed-off-by: Mohamed Osama <mohamed.osama189110@xxxxxxxxx>
---
rust/kernel/mem.rs | 2 +
rust/kernel/std_vendor.rs | 87 +++++++++++++++++++++++++++++++++++++++
2 files changed, 89 insertions(+)

diff --git a/rust/kernel/mem.rs b/rust/kernel/mem.rs
index f2d4cdf87d00..7f8ddd96f907 100644
--- a/rust/kernel/mem.rs
+++ b/rust/kernel/mem.rs
@@ -4,6 +4,8 @@

use crate::prelude::*;

+pub use crate::std_vendor::DropGuard;
+
/// Transmute between two types.
///
/// Use this instead of [`core::mem::transmute`] when it is known that sizes are identical but this
diff --git a/rust/kernel/std_vendor.rs b/rust/kernel/std_vendor.rs
index abbab5050cc5..21a26b4eec71 100644
--- a/rust/kernel/std_vendor.rs
+++ b/rust/kernel/std_vendor.rs
@@ -7,6 +7,9 @@
//! "Apache-2.0 OR MIT" and adapted for kernel use. For copyright details,
//! see <https://github.com/rust-lang/rust/blob/master/COPYRIGHT>.

+use core::mem::ManuallyDrop;
+use core::ops::{Deref, DerefMut};
+
/// [`std::dbg`], but using [`pr_info`] instead of [`eprintln`].
///
/// Prints and returns the value of a given expression for quick and dirty
@@ -162,3 +165,87 @@ macro_rules! dbg {
($($crate::dbg!($val)),+,)
};
}
+
+/// Wraps a value and runs a closure when dropped.
+///
+/// This is useful for running cleanup code when leaving a scope.
+///
+/// The [`DropGuard::dismiss`] function can be used to take ownership of the wrapped
+/// value without running the cleanup function.
+#[doc(alias = "ScopeGuard")]
+#[doc(alias = "defer")]
+pub struct DropGuard<T, F>
+where
+ F: FnOnce(T),
+{
+ inner: ManuallyDrop<T>,
+ f: ManuallyDrop<F>,
+}
+
+impl<T, F> DropGuard<T, F>
+where
+ F: FnOnce(T),
+{
+ /// Creates a new `DropGuard`.
+ #[inline]
+ #[must_use]
+ pub fn new(inner: T, f: F) -> Self {
+ Self {
+ inner: ManuallyDrop::new(inner),
+ f: ManuallyDrop::new(f),
+ }
+ }
+
+ /// Consumes the `DropGuard`, returning the wrapped value without
+ /// running the cleanup function.
+ #[inline]
+ pub fn dismiss(guard: Self) -> T {
+ let mut guard = ManuallyDrop::new(guard);
+
+ // SAFETY: We have taken ownership of the guard and prevent its destructor from running.
+ let value = unsafe { ManuallyDrop::take(&mut guard.inner) };
+
+ // SAFETY: We have taken ownership of the guard.
+ unsafe { ManuallyDrop::drop(&mut guard.f) };
+
+ value
+ }
+}
+
+impl<T, F> Deref for DropGuard<T, F>
+where
+ F: FnOnce(T),
+{
+ type Target = T;
+
+ #[inline]
+ fn deref(&self) -> &T {
+ &self.inner
+ }
+}
+
+impl<T, F> DerefMut for DropGuard<T, F>
+where
+ F: FnOnce(T),
+{
+ #[inline]
+ fn deref_mut(&mut self) -> &mut T {
+ &mut self.inner
+ }
+}
+
+impl<T, F> Drop for DropGuard<T, F>
+where
+ F: FnOnce(T),
+{
+ #[inline]
+ fn drop(&mut self) {
+ // SAFETY: `DropGuard` is in the process of being dropped.
+ let inner = unsafe { ManuallyDrop::take(&mut self.inner) };
+
+ // SAFETY: `DropGuard` is in the process of being dropped.
+ let f = unsafe { ManuallyDrop::take(&mut self.f) };
+
+ f(inner);
+ }
+}
--
2.43.0