On Tue Oct 6, 2026 at 2:52 PM JST, Alexandre Courbot wrote:
> On Mon Sep 28, 2026 at 5:42 PM JST, Eliot Courtney wrote:
>> Add `Vec::try_push_init` for fallible initializers (`impl Init<T, E>`)
>> and a new sum error type `PushInitError<I, E>` that it returns. If
>> allocation fails, it hands back the original initializer. A From impl
>
> nit: missing `` around "From".
>
>> for `Error` lets callers decay the `PushInitError<I, E>` to a regular
>> Error if they want.
>>
>> Signed-off-by: Eliot Courtney <[email protected]>
>> ---
>>  rust/kernel/alloc/kvec.rs        | 55 
>> ++++++++++++++++++++++++++++++++++++++--
>>  rust/kernel/alloc/kvec/errors.rs | 30 ++++++++++++++++++++++
>>  2 files changed, 83 insertions(+), 2 deletions(-)
>>
>> diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
>> index c7546b9da4fa..a2b72a7779d9 100644
>> --- a/rust/kernel/alloc/kvec.rs
>> +++ b/rust/kernel/alloc/kvec.rs
>> @@ -52,10 +52,18 @@
>>      }, //
>>  };
>>  
>> -use pin_init::Zeroable;
>> +use pin_init::{
>> +    Init,
>> +    Zeroable, //
>> +};
>>  
>>  mod errors;
>> -pub use self::errors::{InsertError, PushError, RemoveError};
>> +pub use self::errors::{
>> +    InsertError,
>> +    PushError,
>> +    PushInitError,
>> +    RemoveError, //
>> +};
>>  
>>  /// Create a [`KVec`] containing the arguments.
>>  ///
>> @@ -359,6 +367,49 @@ pub fn push(&mut self, v: T, flags: Flags) -> 
>> Result<(), AllocError> {
>>          Ok(())
>>      }
>>  
>> +    /// Appends an element to the back of the [`Vec`] instance by 
>> initializing it in place.
>> +    ///
>> +    /// Unlike [`Vec::push`], the initializer may be fallible. If the 
>> allocation fails, the
>> +    /// original initializer `init` is handed back in 
>> [`PushInitError::AllocError`]. If the
>> +    /// initializer itself fails, its error is returned in 
>> [`PushInitError::InitError`].
>> +    ///
>> +    /// # Examples
>> +    ///
>> +    /// ```
>> +    /// struct Element {
>> +    ///     buf: KVec<u8>,
>
> It becomes a tad confusing when the element of a `KVec` is itself a
> `KVec`... Can we just use primitive types inside `Element`?

SGTM, added the failure case in the example as well.

>
>> +    /// }
>> +    ///
>> +    /// impl Element {
>> +    ///     fn new() -> impl Init<Self, Error> {
>> +    ///         try_init!(Element {
>> +    ///             buf: KVec::with_capacity(16, GFP_KERNEL)?,
>> +    ///         }? Error)
>> +    ///     }
>> +    /// }
>> +    ///
>> +    /// let mut v: KVec<Element> = KVec::new();
>> +    /// v.try_push_init(Element::new(), GFP_KERNEL)?;
>> +    /// assert!(v[0].buf.is_empty());
>> +    /// # Ok::<(), Error>(())
>> +    /// ```
>> +    pub fn try_push_init<I, E>(&mut self, init: I, flags: Flags) -> 
>> Result<(), PushInitError<I, E>>
>> +    where
>> +        I: Init<T, E>,
>> +    {
>> +        if self.reserve(1, flags).is_err() {
>> +            return Err(PushInitError::AllocError(init));
>> +        }
>> +        // SAFETY: The call to `reserve` was successful, so there is at 
>> least one spare slot.
>> +        unsafe { 
>> init.__init(self.spare_capacity_mut().as_mut_ptr().cast::<T>()) }
>
> I guess it comes down to the same but I'd feel safer if we could
> explicitly index the first element using `get_unchecked_mut(0)`:
>
>     unsafe { 
> init.__init(self.spare_capacity_mut().get_unchecked_mut(0).as_mut_ptr()) }
>
> (removing a cast is also nice I guess)

The file appears split on the convention here (get_unchecked_mut vs
get_mut_ptr + arithmetic + cast), but absolutely do not mind changing
this one here.

Reply via email to