Re: [PATCH 1/6] rust: alloc: add Vec::push_init

"Danilo Krummrich" <[email protected]>
Newsgroups org.kernel.vger.rust-for-linux,dev.linux.lists.nova-gpu,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On Wed Aug 19, 2026 at 9:43 AM CEST, Eliot Courtney wrote:
> There's also some locations in other code that could use a VecView directly
> instead of taking a &mut Vec etc. Having a Vec-like thing that's guaranteed not
> to allocate also sounds potentially useful to me w.r.t. safety for contexts
> where you can't allocate/sleep.

Allocation in atomic context is still possible as long as we avoid memory
reclaim, e.g. with GFP_ATOMIC. However, this should generally be avoided, plus
there are also cases in non-atomic context where we can't have memory reclaim,
such as the DMA fence signaling critical section. So, I think this can a be a
useful API.

> If you think this approach is ok I can send it as a separate series. Codegen
> appears fine practically speaking AFAICT.

I think this is orthogonal from what you need in this series; also remember that
we need a user with real need for an API before we can introduce it.

It might have a use-case in DRM Jobqueue, where it could be used to handle
pre-allocation for ring buffer slots of jobs before entering the DMA fence
signaling critical section. However, I'm not convinced that Vec or a VecDeque
like type is the best solution for DRM Jobqueue in the first place.

> pub type Zero = ();
> pub type Succ<N> = (N,);
> pub type One = Succ<Zero>;
> pub type Two = Succ<One>;

That can produce annoying error messages, but without const generic expr it is
what it is.

> // Infallible (except for Init) push. `Zero` spare VecView has the fallible version.
> impl<'a, T, N: Count> VecView<'a, T, Succ<N>> {
>     pub fn push<E>(self, init: impl Init<T, E>) -> Result<VecView<'a, T, N>, E> {

We still want push() taking impl Init<T> and try_push() taking impl Init<T, E>,
so we get rid of the Result for impl Init<T, Infallible>.

> // Fallible but not allocating ops (can run out of space).
> impl<'a, T> VecView<'a, T> {
>     pub fn push<I: Init<T, E>, E>(&mut self, init: I) -> Result<(), PushInitError<I, E>> {
>         if *self.len == self.cap {
>             return Err(PushInitError::Full(init));
>         }
>
>         unsafe { init.__init(self.buf.as_ptr().add(*self.len)) }.map_err(PushInitError::Init)?;
>         *self.len += 1;
>
>         Ok(())
>     }
>
>     // Bodies as in the current KVec implementations.

We'd still need forwarding functions on Vec, so we don't force users to go
through view().

>     pub fn pop(&mut self) -> Option<T> { ... }
>     pub fn insert(&mut self, index: usize, element: T) -> Result<(), InsertError<T>> { ... }
>     pub fn remove(&mut self, i: usize) -> Result<T, RemoveError> { ... }
>     pub fn truncate(&mut self, len: usize) { ... }
>     pub fn retain(&mut self, f: impl FnMut(&mut T) -> bool) { ... }
>     pub fn drain_all(self) -> DrainAll<'a, T> { ... }
>     pub fn len(&self) -> usize { ... }
>     pub fn as_slice(&self) -> &[T] { ... }
>     pub fn as_mut_slice(&mut self) -> &mut [T] { ... }
>     pub fn spare_capacity(&self) -> usize { ... }
>     pub fn spare_capacity_mut(&mut self) -> &mut [MaybeUninit<T>] { ... }
>     pub unsafe fn commit(&mut self, additional: usize) { ... }
> }
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.