From 85f8e98dbb0135d2bc1999c6015cd374fe2c69fa Mon Sep 17 00:00:00 2001 From: Alexandre Courbot Date: Sat, 12 Apr 2025 15:29:13 +0900 Subject: rust: alloc: allow coercion from `Box` to `Box` if T implements U This enables the creation of trait objects backed by a Box, similarly to what can be done with the standard library. Suggested-by: Benno Lossin Reviewed-by: Alice Ryhl Reviewed-by: Benno Lossin Signed-off-by: Alexandre Courbot Link: https://lore.kernel.org/r/20250412-box_trait_objs-v3-1-f67ced62d520@nvidia.com Signed-off-by: Danilo Krummrich --- rust/kernel/alloc/kbox.rs | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) (limited to 'rust/kernel') diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs index b77d32f3a58b..e043bf2f4687 100644 --- a/rust/kernel/alloc/kbox.rs +++ b/rust/kernel/alloc/kbox.rs @@ -57,12 +57,50 @@ use pin_init::{InPlaceWrite, Init, PinInit, ZeroableOption}; /// assert!(KVBox::::new_uninit(GFP_KERNEL).is_ok()); /// ``` /// +/// [`Box`]es can also be used to store trait objects by coercing their type: +/// +/// ``` +/// trait FooTrait {} +/// +/// struct FooStruct; +/// impl FooTrait for FooStruct {} +/// +/// let _ = KBox::new(FooStruct, GFP_KERNEL)? as KBox; +/// # Ok::<(), Error>(()) +/// ``` +/// /// # Invariants /// /// `self.0` is always properly aligned and either points to memory allocated with `A` or, for /// zero-sized types, is a dangling, well aligned pointer. #[repr(transparent)] -pub struct Box(NonNull, PhantomData); +#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, derive(core::marker::CoercePointee))] +pub struct Box<#[cfg_attr(CONFIG_RUSTC_HAS_COERCE_POINTEE, pointee)] T: ?Sized, A: Allocator>( + NonNull, + PhantomData, +); + +// This is to allow coercion from `Box` to `Box` if `T` can be converted to the +// dynamically-sized type (DST) `U`. +#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] +impl core::ops::CoerceUnsized> for Box +where + T: ?Sized + core::marker::Unsize, + U: ?Sized, + A: Allocator, +{ +} + +// This is to allow `Box` to be dispatched on when `Box` can be coerced into `Box`. +#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))] +impl core::ops::DispatchFromDyn> for Box +where + T: ?Sized + core::marker::Unsize, + U: ?Sized, + A: Allocator, +{ +} /// Type alias for [`Box`] with a [`Kmalloc`] allocator. /// -- cgit v1.2.3