[PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`

Alexandre Courbot posted 4 patches 8 months, 1 week ago
There is a newer version of this series
[PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Alexandre Courbot 8 months, 1 week ago
Implement these two common traits, which allow generic types to store
either an owned value or a reference to it.

The implementation leverages `as_slice` and `as_mut_slice`.

Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
 rust/kernel/alloc/kvec.rs | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index 1a0dd852a468ccda6ea1b521bc1e7dbc8d7fc79c..45f813f69fe0f338a83c577752dd3ba1b3b2003f 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -8,6 +8,7 @@
     AllocError, Allocator, Box, Flags,
 };
 use core::{
+    borrow::{Borrow, BorrowMut},
     fmt,
     marker::PhantomData,
     mem::{ManuallyDrop, MaybeUninit},
@@ -890,6 +891,24 @@ fn deref_mut(&mut self) -> &mut [T] {
     }
 }
 
+impl<T, A> Borrow<[T]> for Vec<T, A>
+where
+    A: Allocator,
+{
+    fn borrow(&self) -> &[T] {
+        self.as_slice()
+    }
+}
+
+impl<T, A> BorrowMut<[T]> for Vec<T, A>
+where
+    A: Allocator,
+{
+    fn borrow_mut(&mut self) -> &mut [T] {
+        self.as_mut_slice()
+    }
+}
+
 impl<T: Eq, A> Eq for Vec<T, A> where A: Allocator {}
 
 impl<T, I: SliceIndex<[T]>, A> Index<I> for Vec<T, A>

-- 
2.49.0
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Benno Lossin 8 months, 1 week ago
On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
> Implement these two common traits, which allow generic types to store
> either an owned value or a reference to it.

I don't understand the second part of the sentence.

> The implementation leverages `as_slice` and `as_mut_slice`.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
>  rust/kernel/alloc/kvec.rs | 19 +++++++++++++++++++
>  1 file changed, 19 insertions(+)

The code itself looks good.

---
Cheers,
Benno
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Alexandre Courbot 8 months, 1 week ago
Hi Benno,

On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
> On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
>> Implement these two common traits, which allow generic types to store
>> either an owned value or a reference to it.
>
> I don't understand the second part of the sentence.

I want to say that Borrow allows you to do something like:

    struct Foo<B: Borrow<u32>>(B);

    // `foo1` owns its value...
    let foo1 = Foo(0x12);

    let i = 0x24;
    // ... but `foo2` just borrows it, subject to the lifetime of `i`.
    let foo2 = Foo(&i);

And the implementations in this series also let you do:

    // `foo3`'s value is owned, but heap-allocated
    let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);

    let j = Arc::new(0x78, GFP_KERNEL)?;
    // `foo4`'s value is shared and its lifetime runtime-managed.
    let foo4 = Foo(j.clone());
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Benno Lossin 8 months, 1 week ago
On Mon Jun 2, 2025 at 3:13 AM CEST, Alexandre Courbot wrote:
> Hi Benno,
>
> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
>> On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
>>> Implement these two common traits, which allow generic types to store
>>> either an owned value or a reference to it.
>>
>> I don't understand the second part of the sentence.
>
> I want to say that Borrow allows you to do something like:
>
>     struct Foo<B: Borrow<u32>>(B);
>
>     // `foo1` owns its value...
>     let foo1 = Foo(0x12);
>
>     let i = 0x24;
>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
>     let foo2 = Foo(&i);
>
> And the implementations in this series also let you do:
>
>     // `foo3`'s value is owned, but heap-allocated
>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
>
>     let j = Arc::new(0x78, GFP_KERNEL)?;
>     // `foo4`'s value is shared and its lifetime runtime-managed.
>     let foo4 = Foo(j.clone());

How about something like:

    Implement `Borrow<[T]>` and `BorrowMut<[T]>` for `Vec<T>`. This allows
    `Vec<T>` to be used in generic APIs asking for types implementing those
    traits. `[T; N]` and `&mut [T]` also implement those traits allowing
    users to use either owned, borrowed and heap-owned values.

Also note this paragraph from the docs:

    In particular `Eq`, `Ord` and `Hash` must be equivalent for borrowed
    and owned values: `x.borrow() == y.borrow()` should give the same
    result as `x == y`.

(This holds for the types that you implement it for, but I wanted to
mention it)

---
Cheers,
Benno
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Alexandre Courbot 8 months ago
On Wed Jun 4, 2025 at 4:34 PM JST, Benno Lossin wrote:
> On Mon Jun 2, 2025 at 3:13 AM CEST, Alexandre Courbot wrote:
>> Hi Benno,
>>
>> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
>>> On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
>>>> Implement these two common traits, which allow generic types to store
>>>> either an owned value or a reference to it.
>>>
>>> I don't understand the second part of the sentence.
>>
>> I want to say that Borrow allows you to do something like:
>>
>>     struct Foo<B: Borrow<u32>>(B);
>>
>>     // `foo1` owns its value...
>>     let foo1 = Foo(0x12);
>>
>>     let i = 0x24;
>>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
>>     let foo2 = Foo(&i);
>>
>> And the implementations in this series also let you do:
>>
>>     // `foo3`'s value is owned, but heap-allocated
>>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
>>
>>     let j = Arc::new(0x78, GFP_KERNEL)?;
>>     // `foo4`'s value is shared and its lifetime runtime-managed.
>>     let foo4 = Foo(j.clone());
>
> How about something like:
>
>     Implement `Borrow<[T]>` and `BorrowMut<[T]>` for `Vec<T>`. This allows
>     `Vec<T>` to be used in generic APIs asking for types implementing those
>     traits. `[T; N]` and `&mut [T]` also implement those traits allowing
>     users to use either owned, borrowed and heap-owned values.

This is super clear, and I think I'll just reuse this message as-is if
that's ok with you. Thanks!
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Benno Lossin 8 months ago
On Fri Jun 13, 2025 at 7:35 AM CEST, Alexandre Courbot wrote:
> On Wed Jun 4, 2025 at 4:34 PM JST, Benno Lossin wrote:
>> On Mon Jun 2, 2025 at 3:13 AM CEST, Alexandre Courbot wrote:
>>> Hi Benno,
>>>
>>> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
>>>> On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
>>>>> Implement these two common traits, which allow generic types to store
>>>>> either an owned value or a reference to it.
>>>>
>>>> I don't understand the second part of the sentence.
>>>
>>> I want to say that Borrow allows you to do something like:
>>>
>>>     struct Foo<B: Borrow<u32>>(B);
>>>
>>>     // `foo1` owns its value...
>>>     let foo1 = Foo(0x12);
>>>
>>>     let i = 0x24;
>>>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
>>>     let foo2 = Foo(&i);
>>>
>>> And the implementations in this series also let you do:
>>>
>>>     // `foo3`'s value is owned, but heap-allocated
>>>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
>>>
>>>     let j = Arc::new(0x78, GFP_KERNEL)?;
>>>     // `foo4`'s value is shared and its lifetime runtime-managed.
>>>     let foo4 = Foo(j.clone());
>>
>> How about something like:
>>
>>     Implement `Borrow<[T]>` and `BorrowMut<[T]>` for `Vec<T>`. This allows
>>     `Vec<T>` to be used in generic APIs asking for types implementing those
>>     traits. `[T; N]` and `&mut [T]` also implement those traits allowing
>>     users to use either owned, borrowed and heap-owned values.
>
> This is super clear, and I think I'll just reuse this message as-is if
> that's ok with you. Thanks!

Sure!

---
Cheers,
Benno
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Boqun Feng 8 months, 1 week ago
On Mon, Jun 02, 2025 at 10:13:22AM +0900, Alexandre Courbot wrote:
> Hi Benno,
> 
> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
> > On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
> >> Implement these two common traits, which allow generic types to store
> >> either an owned value or a reference to it.
> >
> > I don't understand the second part of the sentence.
> 
> I want to say that Borrow allows you to do something like:
> 
>     struct Foo<B: Borrow<u32>>(B);
> 
>     // `foo1` owns its value...
>     let foo1 = Foo(0x12);
> 
>     let i = 0x24;
>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
>     let foo2 = Foo(&i);
> 
> And the implementations in this series also let you do:
> 
>     // `foo3`'s value is owned, but heap-allocated
>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
> 
>     let j = Arc::new(0x78, GFP_KERNEL)?;
>     // `foo4`'s value is shared and its lifetime runtime-managed.
>     let foo4 = Foo(j.clone());

Maybe you could put these in the "# Examples" section before impl
blocks. E.g

	/// # Examples
	/// ```
	/// <you case above>
	/// ```
	impl<T, A> Borrow<[T]> for Vec<T, A> ...

Regards,
Boqun
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Alexandre Courbot 8 months ago
On Tue Jun 3, 2025 at 12:06 AM JST, Boqun Feng wrote:
> On Mon, Jun 02, 2025 at 10:13:22AM +0900, Alexandre Courbot wrote:
>> Hi Benno,
>> 
>> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
>> > On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
>> >> Implement these two common traits, which allow generic types to store
>> >> either an owned value or a reference to it.
>> >
>> > I don't understand the second part of the sentence.
>> 
>> I want to say that Borrow allows you to do something like:
>> 
>>     struct Foo<B: Borrow<u32>>(B);
>> 
>>     // `foo1` owns its value...
>>     let foo1 = Foo(0x12);
>> 
>>     let i = 0x24;
>>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
>>     let foo2 = Foo(&i);
>> 
>> And the implementations in this series also let you do:
>> 
>>     // `foo3`'s value is owned, but heap-allocated
>>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
>> 
>>     let j = Arc::new(0x78, GFP_KERNEL)?;
>>     // `foo4`'s value is shared and its lifetime runtime-managed.
>>     let foo4 = Foo(j.clone());
>
> Maybe you could put these in the "# Examples" section before impl
> blocks. E.g
>
> 	/// # Examples
> 	/// ```
> 	/// <you case above>
> 	/// ```
> 	impl<T, A> Borrow<[T]> for Vec<T, A> ...

I've started doing this, but it felt like I was writing down the obvious
as this kind of use is precisely what Borrow is intended for. I think
Benno's suggestion for the commit log addresses your request for
clarification, but let me add these on v2 anyway - we can always remove
them if we conclude they are unnecessary.
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Benno Lossin 8 months, 1 week ago
On Mon Jun 2, 2025 at 5:06 PM CEST, Boqun Feng wrote:
> On Mon, Jun 02, 2025 at 10:13:22AM +0900, Alexandre Courbot wrote:
>> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
>> > On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
>> >> Implement these two common traits, which allow generic types to store
>> >> either an owned value or a reference to it.
>> >
>> > I don't understand the second part of the sentence.
>> 
>> I want to say that Borrow allows you to do something like:
>> 
>>     struct Foo<B: Borrow<u32>>(B);
>> 
>>     // `foo1` owns its value...
>>     let foo1 = Foo(0x12);
>> 
>>     let i = 0x24;
>>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
>>     let foo2 = Foo(&i);
>> 
>> And the implementations in this series also let you do:
>> 
>>     // `foo3`'s value is owned, but heap-allocated
>>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
>> 
>>     let j = Arc::new(0x78, GFP_KERNEL)?;
>>     // `foo4`'s value is shared and its lifetime runtime-managed.
>>     let foo4 = Foo(j.clone());
>
> Maybe you could put these in the "# Examples" section before impl
> blocks. E.g
>
> 	/// # Examples
> 	/// ```
> 	/// <you case above>
> 	/// ```
> 	impl<T, A> Borrow<[T]> for Vec<T, A> ...

Does that get rendered in the docs? If not, I don't think we should do
it.

---
Cheers,
Benno
Re: [PATCH 1/4] rust: alloc: implement `Borrow` and `BorrowMut` for `Vec`
Posted by Boqun Feng 8 months, 1 week ago
On Mon, Jun 02, 2025 at 10:21:12PM +0200, Benno Lossin wrote:
> On Mon Jun 2, 2025 at 5:06 PM CEST, Boqun Feng wrote:
> > On Mon, Jun 02, 2025 at 10:13:22AM +0900, Alexandre Courbot wrote:
> >> On Mon Jun 2, 2025 at 1:11 AM JST, Benno Lossin wrote:
> >> > On Sun Jun 1, 2025 at 5:00 AM CEST, Alexandre Courbot wrote:
> >> >> Implement these two common traits, which allow generic types to store
> >> >> either an owned value or a reference to it.
> >> >
> >> > I don't understand the second part of the sentence.
> >> 
> >> I want to say that Borrow allows you to do something like:
> >> 
> >>     struct Foo<B: Borrow<u32>>(B);
> >> 
> >>     // `foo1` owns its value...
> >>     let foo1 = Foo(0x12);
> >> 
> >>     let i = 0x24;
> >>     // ... but `foo2` just borrows it, subject to the lifetime of `i`.
> >>     let foo2 = Foo(&i);
> >> 
> >> And the implementations in this series also let you do:
> >> 
> >>     // `foo3`'s value is owned, but heap-allocated
> >>     let foo3 = Arc::new(KBox::new(0x56, GFP_KERNEL)?);
> >> 
> >>     let j = Arc::new(0x78, GFP_KERNEL)?;
> >>     // `foo4`'s value is shared and its lifetime runtime-managed.
> >>     let foo4 = Foo(j.clone());
> >
> > Maybe you could put these in the "# Examples" section before impl
> > blocks. E.g
> >
> > 	/// # Examples
> > 	/// ```
> > 	/// <you case above>
> > 	/// ```
> > 	impl<T, A> Borrow<[T]> for Vec<T, A> ...
> 
> Does that get rendered in the docs? If not, I don't think we should do
> it.

It does. I just tried myself, in the "Trait Implementations" section,
if you provide a doc comment for an impl block, it will show under the
"impl line" of corresponding to that impl block, including ```code```.

Regards,
Boqun

> 
> ---
> Cheers,
> Benno