From: Danilo Krummrich <dakr@kernel.org>
To: Alexandre Courbot <acourbot@nvidia.com>
Cc: "Miguel Ojeda" <ojeda@kernel.org>,
"Alex Gaynor" <alex.gaynor@gmail.com>,
"Boqun Feng" <boqun.feng@gmail.com>,
"Gary Guo" <gary@garyguo.net>,
"Björn Roy Baron" <bjorn3_gh@protonmail.com>,
"Benno Lossin" <benno.lossin@proton.me>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
"Joel Fernandes" <joelagnelf@nvidia.com>,
"John Hubbard" <jhubbard@nvidia.com>,
rust-for-linux@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3] rust: alloc: implement `extend` for `Vec`
Date: Mon, 7 Apr 2025 13:01:44 +0200 [thread overview]
Message-ID: <Z_OwmEKHgsZlt2cs@pollux> (raw)
In-Reply-To: <20250406-vec_extend-v3-1-ec5c5c0acf2a@nvidia.com>
On Sun, Apr 06, 2025 at 10:01:55PM +0900, Alexandre Courbot wrote:
> KVec currently has `extend_with` and `extend_from_slice` methods, but no
> way extend a vector from a regular iterator as provided by the `Extend`
> trait.
>
> Due to the need to provide the GFP flags, `Extend` cannot be implemented
> directly, so simply define a homonymous method that takes an extra
> `flags` argument.
This is the same approach I took with Vec::collect(); I think this is fine for
now. One we attempt to implement more collections, we should implement our own
Extend and FromIterator traits.
> diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
> index ae9d072741cedbb34bed0be0c20cc75472aa53be..b3c4227e232cca3b5c17930abc63810240b9c4da 100644
> --- a/rust/kernel/alloc/kvec.rs
> +++ b/rust/kernel/alloc/kvec.rs
> @@ -454,30 +454,86 @@ pub fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocEr
> }
> }
>
> +impl<T, A: Allocator> Vec<T, A> {
Please re-use the existing impl block above, i.e.
diff --git a/rust/kernel/alloc/kvec.rs b/rust/kernel/alloc/kvec.rs
index b3c4227e232c..72659b017553 100644
--- a/rust/kernel/alloc/kvec.rs
+++ b/rust/kernel/alloc/kvec.rs
@@ -452,9 +452,7 @@ pub fn reserve(&mut self, additional: usize, flags: Flags) -> Result<(), AllocEr
Ok(())
}
-}
-impl<T, A: Allocator> Vec<T, A> {
/// Extends the vector by the elements of `iter`.
///
/// This uses [`Iterator::size_hint`] to optimize memory reallocations, but will work even with
> + /// Extends the vector by the elements of `iter`.
> + ///
> + /// This uses [`Iterator::size_hint`] to optimize memory reallocations, but will work even with
> + /// imprecise implementations - albeit in a non-optimal way.
> + ///
> + /// This method returns an error if a memory reallocation required to accommodate the new items
> + /// failed. In this case, callers must assume that some (but not all) elements of `iter` might
> + /// have been added to the vector.
> + ///
> + /// # Note on optimal behavior and correctness
> + ///
> + /// The efficiency of this method depends on how reliable the [`Iterator::size_hint`]
> + /// implementation of the `iter` is.
> + ///
> + /// It performs optimally with at most a single memory reallocation if the lower bound of
> + /// `size_hint` is the exact number of items actually yielded.
> + ///
> + /// If `size_hint` is more vague, there may be as many memory reallocations as necessary to
> + /// cover the whole iterator from the successive lower bounds returned by `size_hint`.
> + ///
> + /// If `size_hint` signals more items than actually yielded by the iterator, some unused memory
> + /// might be reserved.
> + ///
> + /// Finally, whenever `size_hint` returns `(0, Some(0))`, the method assumes that no more items
> + /// are yielded by the iterator and returns. This may result in some items not being added if
> + /// there were still some remaining.
> + ///
> + /// In the kernel most iterators are expected to have a precise and correct `size_hint`
> + /// implementation, so this should nicely optimize out for these cases.
I agree, hence I think we should enforce to be provided with a guaranteed
correct size hint and simplify the code. I think we should extend the signature.
pub fn extend<I>(&mut self, iter: I, flags: Flags) -> Result<(), AllocError>
where
I: IntoIterator<Item = T>,
I::IntoIter: ExactSizeIterator,
And implement ExactSizeIterator for IntoIter.
The only thing that bothers me a bit is that the documentation [1] of
ExactSizeIterator sounds a bit ambiguous.
It says: "When implementing an ExactSizeIterator, you must also implement
Iterator. When doing so, the implementation of Iterator::size_hint *must*
return the exact size of the iterator."
But it also says: "Note that this trait is a safe trait and as such does not and
cannot guarantee that the returned length is correct. This means that unsafe
code must not rely on the correctness of Iterator::size_hint. The unstable and
unsafe TrustedLen trait gives this additional guarantee."
Acknowledging the latter, I think we should implement our own trait for this
instead. Our own version of TrustedLen seems reasonable to me.
[1] https://doc.rust-lang.org/std/iter/trait.ExactSizeIterator.html
next prev parent reply other threads:[~2025-04-07 11:01 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-04-06 13:01 [PATCH v3] rust: alloc: implement `extend` for `Vec` Alexandre Courbot
2025-04-07 11:01 ` Danilo Krummrich [this message]
2025-04-08 13:34 ` Alexandre Courbot
2025-04-21 8:15 ` Alexandre Courbot
2025-04-22 17:03 ` Danilo Krummrich
2025-04-23 1:02 ` Alexandre Courbot
2025-04-23 8:51 ` Alice Ryhl
2025-04-23 9:40 ` Alexandre Courbot
2025-04-23 16:03 ` Boqun Feng
2025-04-24 11:50 ` Alice Ryhl
2025-04-24 13:36 ` Boqun Feng
2025-04-23 9:47 ` Danilo Krummrich
2025-04-23 13:15 ` Alexandre Courbot
-- strict thread matches above, loose matches on Subject: below --
2025-04-07 16:33 Benno Lossin
2025-04-08 14:00 ` Alexandre Courbot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=Z_OwmEKHgsZlt2cs@pollux \
--to=dakr@kernel.org \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=benno.lossin@proton.me \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=gary@garyguo.net \
--cc=jhubbard@nvidia.com \
--cc=joelagnelf@nvidia.com \
--cc=linux-kernel@vger.kernel.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox