From: Joel Fernandes <joelagnelf@nvidia.com>
To: Alexandre Courbot <acourbot@nvidia.com>
Cc: "Danilo Krummrich" <dakr@kernel.org>,
"Yury Norov" <yury.norov@gmail.com>,
"Jesung Yang" <y.j3ms.n@gmail.com>,
"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" <lossin@kernel.org>,
"Andreas Hindborg" <a.hindborg@kernel.org>,
"Alice Ryhl" <aliceryhl@google.com>,
"Trevor Gross" <tmgross@umich.edu>,
nouveau@lists.freedesktop.org, linux-kernel@vger.kernel.org,
rust-for-linux@vger.kernel.org,
Nouveau <nouveau-bounces@lists.freedesktop.org>
Subject: Re: [PATCH RFC v2 2/3] rust: kernel: add bounded integer types
Date: Fri, 10 Oct 2025 11:23:02 -0400 [thread overview]
Message-ID: <b53e554c-252d-4b21-a337-578c97c80dde@nvidia.com> (raw)
In-Reply-To: <DDEIH181JDA9.2DG2C3DBOB2V@nvidia.com>
On 10/10/2025 4:49 AM, Alexandre Courbot wrote:
> On Fri Oct 10, 2025 at 6:33 AM JST, Joel Fernandes wrote:
>> Hi Alex,
>>
>> Great effort, thanks. I replied with few comments below. Since the patch is
>> large, it would be great if could be possibly split. Maybe the From
>> primitives deserve a separate patch.
>
> I'm all for smaller patches when it makes reviewing easier, but in this
> case all it would achieve is making the second patch append code right
> after the next. :) Is there a benefit in doing so?
I think there is a benefit, because reviewers don't have to scroll through huge
emails :). Plus separate commit messages would be added in too, to reason about
new code. There's other possible logical splits too, was just giving example but
I am Ok with it if you still want to keep it singular. :)
>>> +impl<const NUM_BITS: u32> Boundable<NUM_BITS> for u16 {
>>> + const MASK: u16 = crate::bits::genmask_u16(0..=(NUM_BITS - 1));
>>> +}
>>> +
>>> +impl<const NUM_BITS: u32> Boundable<NUM_BITS> for u32 {
>>> + const MASK: u32 = crate::bits::genmask_u32(0..=(NUM_BITS - 1));
>>> +}
>>> +
>>> +impl<const NUM_BITS: u32> Boundable<NUM_BITS> for u64 {
>>> + const MASK: u64 = crate::bits::genmask_u64(0..=(NUM_BITS - 1));
>>> +}
>>> +
>>> +impl<T, const NUM_BITS: u32> BoundedInt<T, NUM_BITS>
>>> +where
>>> + T: Boundable<NUM_BITS>,
>>> +{
>>> + /// Checks that `value` is valid for this type at compile-time and build a new value.
>>> + ///
>>> + /// This relies on [`build_assert!`] to perform validation at compile-time. If `value` cannot
>>> + /// be inferred to be in bounds at compile-time, use the fallible [`Self::try_new`] instead.
>>> + ///
>>> + /// When possible, use one of the `new_const` methods instead of this method as it statically
>>> + /// validates `value` instead of relying on the compiler's optimizations.
>>
>> This sounds like, users might use the less-optimal API first with the same
>> build_assert issues we had with the IO accessors, since new() sounds very obvious.
>> How about the following naming?
>>
>> new::<VALUE>() // Primary constructor for constants using const generics.
>> try_new(value) // Keep as-is for fallible runtime
>> new_from_expr(value) // For compile-time validated runtime values
>>
>> If new::<VALUE>() does not work for the user, the compiler will fail.
>>
>> Or, new_from_expr() could be from_value(), Ok with either naming or a better name.
>
> Agreed, the preferred method should appear first. IIRC Alice also made a
> similar suggestion about v1 during the DRM sync, sorry for not picking
> it up.
Cool, sounds good.
[..]>>> + /// Returns the contained value as a primitive type.
>>> + ///
>>> + /// # Examples
>>> + ///
>>> + /// ```
>>> + /// use kernel::num::BoundedInt;
>>> + ///
>>> + /// let v = BoundedInt::<u32, 4>::new_const::<7>();
>>> + /// assert_eq!(v.get(), 7u32);
>>> + /// ```
>>> + pub fn get(self) -> T {
>>> + if !T::is_in_bounds(self.0) {
>>> + // SAFETY: Per the invariants, `self.0` cannot have bits set outside of `MASK`, so
>>> + // this block will
>>> + // never be reached.
>>> + unsafe { core::hint::unreachable_unchecked() }
>>> + }
>>
>> Does this if block help the compiler generate better code? I wonder if code
>> gen could be checked to confirm the rationale.
>
> Benno suggested that it would on a different patch:
>
> https://lore.kernel.org/rust-for-linux/DBL1ZGZCSJF3.29HNS9BSN89C6@kernel.org/
>
> OTOH as shown in patch 3/3, this doesn't exempt us from handling
> impossible values when using this in a match expression...
Interesting, TIL.
>>> + self.0
>>> + }
>>> +
>>> + /// Increase the number of bits usable for `self`.
>>> + ///
>>> + /// This operation cannot fail.
>>> + ///
>>> + /// # Examples
>>> + ///
>>> + /// ```
>>> + /// use kernel::num::BoundedInt;
>>> + ///
>>> + /// let v = BoundedInt::<u32, 4>::new_const::<7>();
>>> + /// let larger_v = v.enlarge::<12>();
>>> + /// // The contained values are equal even though `larger_v` has a bigger capacity.
>>> + /// assert_eq!(larger_v, v);
>>> + /// ```
>>> + pub const fn enlarge<const NEW_NUM_BITS: u32>(self) -> BoundedInt<T, NEW_NUM_BITS>
>>> + where
>>> + T: Boundable<NEW_NUM_BITS>,
>>> + T: Copy,
>>
>> Boundable already implies copy so T: Copy is redundant.
>
> Thanks. I need to do a thorough review of all the contraints as I've
> changed them quite a bit as the implementation matured.
Cool. :)
>> [...]
>>> +impl_const_new!(u8 u16 u32 u64);
>>> +
>>> +/// Declares a new `$trait` and implements it for all bounded types represented using `$num_bits`.
>>> +///
>>> +/// This is used to declare properties as traits that we can use for later implementations.
>>> +macro_rules! impl_size_rule {
>>> + ($trait:ident, $($num_bits:literal)*) => {
>>> + trait $trait {}
>>> +
>>> + $(
>>> + impl<T> $trait for BoundedInt<T, $num_bits> where T: Boundable<$num_bits> {}
>>> + )*
>>> + };
>>> +}
>>> +
>>> +// Bounds that are larger than a `u64`.
>>> +impl_size_rule!(LargerThanU64, 64);
>>> +
>>> +// Bounds that are larger than a `u32`.
>>> +impl_size_rule!(LargerThanU32,
>>> + 32 33 34 35 36 37 38 39
>>
>> If num_bits == 32 (number of bits), how could BoundedInt<T, 32> a
>> LargerThanU32? It should be AtleastU32 or something.
>>
>> Or the above list should start from 33. Only a >= 33-bit wide integer can be
>> LargerThanU32.
>
> The name is a bit ambiguous indeed. An accurate one would be
> `LargerOrEqualThanU32`, but `AtLeastU32` should also work.
Sure, I prefer AtLeastU32 since it is shorter :)
thanks,
- Joel
next prev parent reply other threads:[~2025-10-10 15:23 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-09 12:37 [RFC PATCH v2 0/3] rust: bounded integer types and use in register macro Alexandre Courbot
2025-10-09 12:37 ` [PATCH RFC v2 1/3] gpu: nova-core: register: use field type for Into implementation Alexandre Courbot
2025-10-09 15:17 ` Joel Fernandes
2025-10-09 15:41 ` Joel Fernandes
2025-10-10 8:24 ` Alexandre Courbot
2025-10-10 8:26 ` Alexandre Courbot
2025-10-10 14:59 ` Joel Fernandes
2025-10-09 20:10 ` Edwin Peer
2025-10-16 14:51 ` Joel Fernandes
2025-10-09 12:37 ` [PATCH RFC v2 2/3] rust: kernel: add bounded integer types Alexandre Courbot
2025-10-09 21:33 ` Joel Fernandes
2025-10-10 8:49 ` Alexandre Courbot
2025-10-10 15:23 ` Joel Fernandes [this message]
2025-10-11 10:33 ` Alice Ryhl
2025-10-09 12:37 ` [PATCH RFC v2 3/3] gpu: nova-core: use BoundedInt Alexandre Courbot
2025-10-09 16:40 ` Yury Norov
2025-10-09 17:18 ` Danilo Krummrich
2025-10-09 18:28 ` Yury Norov
2025-10-09 18:37 ` Joel Fernandes
2025-10-09 19:19 ` Miguel Ojeda
2025-10-09 19:34 ` Danilo Krummrich
2025-10-09 18:29 ` Joel Fernandes
2025-10-10 9:19 ` Alexandre Courbot
2025-10-10 17:20 ` Yury Norov
2025-10-10 17:58 ` Danilo Krummrich
2025-10-13 13:58 ` Joel Fernandes
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=b53e554c-252d-4b21-a337-578c97c80dde@nvidia.com \
--to=joelagnelf@nvidia.com \
--cc=a.hindborg@kernel.org \
--cc=acourbot@nvidia.com \
--cc=alex.gaynor@gmail.com \
--cc=aliceryhl@google.com \
--cc=bjorn3_gh@protonmail.com \
--cc=boqun.feng@gmail.com \
--cc=dakr@kernel.org \
--cc=gary@garyguo.net \
--cc=linux-kernel@vger.kernel.org \
--cc=lossin@kernel.org \
--cc=nouveau-bounces@lists.freedesktop.org \
--cc=nouveau@lists.freedesktop.org \
--cc=ojeda@kernel.org \
--cc=rust-for-linux@vger.kernel.org \
--cc=tmgross@umich.edu \
--cc=y.j3ms.n@gmail.com \
--cc=yury.norov@gmail.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.