[PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U

Alexandre Courbot posted 1 patch 10 months ago
There is a newer version of this series
rust/kernel/alloc/kbox.rs | 30 +++++++++++++++++++++++++++++-
1 file changed, 29 insertions(+), 1 deletion(-)
[PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Alexandre Courbot 10 months ago
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 <benno.lossin@proton.me>
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
From this discussion on Zulip [1].

Heavily inspired from the similar feature on `Arc`.

[1] https://rust-for-linux.zulipchat.com/#narrow/channel/291565-Help/topic/Trait.20objects.3F/with/510689662
---
Changes in v2:
- Use where clauses to improve readability.
- Fix build with rustc 1.78.
- Link to v1: https://lore.kernel.org/r/20250408-box_trait_objs-v1-1-58d8e78b0fb2@nvidia.com
---
 rust/kernel/alloc/kbox.rs | 30 +++++++++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
index b77d32f3a58bab5ec73c612bdaaba0d79bfdff65..b9a905cd4bd285782b0db284b6771aec03e0c10b 100644
--- a/rust/kernel/alloc/kbox.rs
+++ b/rust/kernel/alloc/kbox.rs
@@ -32,6 +32,8 @@
 ///
 /// When dropping a [`Box`], the value is also dropped and the heap memory is automatically freed.
 ///
+/// [`Box`]es can also be used to store trait objects by coercing their type.
+///
 /// # Examples
 ///
 /// ```
@@ -62,7 +64,33 @@
 /// `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<T: ?Sized, A: Allocator>(NonNull<T>, PhantomData<A>);
+#[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<T>,
+    PhantomData<A>,
+);
+
+// This is to allow coercion from `Box<T, A>` to `Box<U, A>` if `T` can be converted to the
+// dynamically-sized type (DST) `U`.
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T, U, A> core::ops::CoerceUnsized<Box<U, A>> for Box<T, A>
+where
+    T: ?Sized + core::marker::Unsize<U>,
+    U: ?Sized,
+    A: Allocator,
+{
+}
+
+// This is to allow `Box<U, A>` to be dispatched on when `Box<T, A>` can be coerced into `Box<U,
+// A>`.
+#[cfg(not(CONFIG_RUSTC_HAS_COERCE_POINTEE))]
+impl<T, U, A> core::ops::DispatchFromDyn<Box<U, A>> for Box<T, A>
+where
+    T: ?Sized + core::marker::Unsize<U>,
+    U: ?Sized,
+    A: Allocator,
+{
+}
 
 /// Type alias for [`Box`] with a [`Kmalloc`] allocator.
 ///

---
base-commit: 0af2f6be1b4281385b618cb86ad946eded089ac8
change-id: 20250408-box_trait_objs-02a700401f0b

Best regards,
-- 
Alexandre Courbot <acourbot@nvidia.com>
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Danilo Krummrich 10 months ago
On Fri, Apr 11, 2025 at 09:07:26PM +0900, Alexandre Courbot wrote:
> 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 <benno.lossin@proton.me>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>

I assume you have a specific use-case in nova-core for this? For this cycle, can
you get away without having this in nova-core?
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Alexandre Courbot 10 months ago
On Fri Apr 11, 2025 at 10:10 PM JST, Danilo Krummrich wrote:
> On Fri, Apr 11, 2025 at 09:07:26PM +0900, Alexandre Courbot wrote:
>> 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 <benno.lossin@proton.me>
>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>
> I assume you have a specific use-case in nova-core for this? For this cycle, can
> you get away without having this in nova-core?

That's correct, and our next nova-core iteration will likely depend on
this to provide some basic HAL. If this cannot make it for this cycle, I
guess I can always use Arc temporarily.
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Danilo Krummrich 10 months ago
On Fri, Apr 11, 2025 at 10:26:23PM +0900, Alexandre Courbot wrote:
> On Fri Apr 11, 2025 at 10:10 PM JST, Danilo Krummrich wrote:
> > On Fri, Apr 11, 2025 at 09:07:26PM +0900, Alexandre Courbot wrote:
> >> 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 <benno.lossin@proton.me>
> >> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> >
> > I assume you have a specific use-case in nova-core for this? For this cycle, can
> > you get away without having this in nova-core?
> 
> That's correct, and our next nova-core iteration will likely depend on
> this to provide some basic HAL. If this cannot make it for this cycle, I
> guess I can always use Arc temporarily.

I'd prefer to take this through the alloc tree (for this cycle), but this also
means you can't use it until the next cycle in nova. I assume that's just a
minor inconvinience?
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Alexandre Courbot 10 months ago
On Fri Apr 11, 2025 at 11:22 PM JST, Danilo Krummrich wrote:
> On Fri, Apr 11, 2025 at 10:26:23PM +0900, Alexandre Courbot wrote:
>> On Fri Apr 11, 2025 at 10:10 PM JST, Danilo Krummrich wrote:
>> > On Fri, Apr 11, 2025 at 09:07:26PM +0900, Alexandre Courbot wrote:
>> >> 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 <benno.lossin@proton.me>
>> >> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>> >
>> > I assume you have a specific use-case in nova-core for this? For this cycle, can
>> > you get away without having this in nova-core?
>> 
>> That's correct, and our next nova-core iteration will likely depend on
>> this to provide some basic HAL. If this cannot make it for this cycle, I
>> guess I can always use Arc temporarily.
>
> I'd prefer to take this through the alloc tree (for this cycle), but this also
> means you can't use it until the next cycle in nova. I assume that's just a
> minor inconvinience?

Yes, taking it through the alloc tree is fine, I will just work things
around (or delay the Falcon HAL, it's not like nova-core is going to be
anything useful in 6.16 anyway ^_^;) for the next cycle.

Thanks!
Alex.
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Benno Lossin 10 months ago
On Fri Apr 11, 2025 at 2:07 PM CEST, Alexandre Courbot wrote:
> 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 <benno.lossin@proton.me>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>

Reviewed-by: Benno Lossin <benno.lossin@proton.me>

> ---
> From this discussion on Zulip [1].
>
> Heavily inspired from the similar feature on `Arc`.
>
> [1] https://rust-for-linux.zulipchat.com/#narrow/channel/291565-Help/topic/Trait.20objects.3F/with/510689662
> ---
> Changes in v2:
> - Use where clauses to improve readability.
> - Fix build with rustc 1.78.
> - Link to v1: https://lore.kernel.org/r/20250408-box_trait_objs-v1-1-58d8e78b0fb2@nvidia.com
> ---
>  rust/kernel/alloc/kbox.rs | 30 +++++++++++++++++++++++++++++-
>  1 file changed, 29 insertions(+), 1 deletion(-)
>
> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
> index b77d32f3a58bab5ec73c612bdaaba0d79bfdff65..b9a905cd4bd285782b0db284b6771aec03e0c10b 100644
> --- a/rust/kernel/alloc/kbox.rs
> +++ b/rust/kernel/alloc/kbox.rs
> @@ -32,6 +32,8 @@
>  ///
>  /// When dropping a [`Box`], the value is also dropped and the heap memory is automatically freed.
>  ///
> +/// [`Box`]es can also be used to store trait objects by coercing their type.
> +///
>  /// # Examples

I agree with Miguel, you could move the added line above down here and
also provide a simple example.

---
Cheers,
Benno

>  ///
>  /// ```
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Alexandre Courbot 10 months ago
On Fri Apr 11, 2025 at 9:43 PM JST, Benno Lossin wrote:
> On Fri Apr 11, 2025 at 2:07 PM CEST, Alexandre Courbot wrote:
>> 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 <benno.lossin@proton.me>
>> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
>
> Reviewed-by: Benno Lossin <benno.lossin@proton.me>
>
>> ---
>> From this discussion on Zulip [1].
>>
>> Heavily inspired from the similar feature on `Arc`.
>>
>> [1] https://rust-for-linux.zulipchat.com/#narrow/channel/291565-Help/topic/Trait.20objects.3F/with/510689662
>> ---
>> Changes in v2:
>> - Use where clauses to improve readability.
>> - Fix build with rustc 1.78.
>> - Link to v1: https://lore.kernel.org/r/20250408-box_trait_objs-v1-1-58d8e78b0fb2@nvidia.com
>> ---
>>  rust/kernel/alloc/kbox.rs | 30 +++++++++++++++++++++++++++++-
>>  1 file changed, 29 insertions(+), 1 deletion(-)
>>
>> diff --git a/rust/kernel/alloc/kbox.rs b/rust/kernel/alloc/kbox.rs
>> index b77d32f3a58bab5ec73c612bdaaba0d79bfdff65..b9a905cd4bd285782b0db284b6771aec03e0c10b 100644
>> --- a/rust/kernel/alloc/kbox.rs
>> +++ b/rust/kernel/alloc/kbox.rs
>> @@ -32,6 +32,8 @@
>>  ///
>>  /// When dropping a [`Box`], the value is also dropped and the heap memory is automatically freed.
>>  ///
>> +/// [`Box`]es can also be used to store trait objects by coercing their type.
>> +///
>>  /// # Examples
>
> I agree with Miguel, you could move the added line above down here and
> also provide a simple example.

Oops, I completely forgot to address Miguel's comment, sorry about that.
Will send a new version.
Re: [PATCH v2] rust: alloc: allow coercion from `Box<T>` to `Box<dyn U>` if T implements U
Posted by Alice Ryhl 10 months ago
On Fri, Apr 11, 2025 at 2:07 PM Alexandre Courbot <acourbot@nvidia.com> wrote:
>
> 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 <benno.lossin@proton.me>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>

Reviewed-by: Alice Ryhl <aliceryhl@google.com>