Re: [PATCH v7 03/10] rust: num: add nz! macro for compile time NonZero values

"Eliot Courtney" <[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 Thu Aug 20, 2026 at 5:07 AM JST, Gary Guo wrote:
> On Mon Aug 17, 2026 at 8:04 AM BST, Eliot Courtney wrote:
>> Currently, using NonZero constants is quite verbose. It's unfortunate
>> because it disincentivizes using it in interface boundaries. Introduce a
>> macro to make it nicer to use.
>>
>> Link: https://lore.kernel.org/[email protected]
>> Signed-off-by: Eliot Courtney <[email protected]>
>> ---
>>  rust/kernel/num.rs | 23 +++++++++++++++++++++++
>>  1 file changed, 23 insertions(+)
>>
>> diff --git a/rust/kernel/num.rs b/rust/kernel/num.rs
>> index 8532b511384c..055d23ca7fd1 100644
>> --- a/rust/kernel/num.rs
>> +++ b/rust/kernel/num.rs
>> @@ -7,6 +7,29 @@
>>  pub mod bounded;
>>  pub use bounded::*;
>>  
>> +/// Infallibly creates a [`NonZero`] value from a constant expression.
>> +///
>> +/// [`NonZero`]: core::num::NonZero
>> +///
>> +/// # Examples
>> +///
>> +/// ```
>> +/// use core::num::NonZero;
>> +/// use kernel::nz;
>> +///
>> +/// let v: NonZero<usize> = nz!(8);
>> +/// assert_eq!(v.get(), 8);
>> +///
>> +/// const N: NonZero<u32> = nz!(0x10);
>> +/// assert_eq!(N.get(), 0x10);
>> +/// ```
>> +#[macro_export]
>> +macro_rules! nz {
>> +    ($v:expr) => {
>> +        const { ::core::num::NonZero::new($v).unwrap() }
>> +    };
>> +}
>
> I wonder if if we can have a generic macro for creating types from literals,
> given that this is needed for bounded too. Something like
>
>     trait FromLiteral {
>         fn from_literal<const N: i64>() -> Self;
>     }
>
>     impl FromLiteral for NonZero<u32> {
>         #[inline]
>         fn from_literal<const N: i64>() -> Self {
>             const_assert!(N > 0 && N < u32::MAX as i64);
>             const { NonZero::new(N as u32).unwrap() }
>         }
>     }
>
>     macro_rules! lit {
>         ($x:expr) => {
>             FromLiteral::from_literal::<{$x}>()
>         }
>     }
>
>     let nz: NonZero<u32> = lit!(1);
>     let bounded: Bounded<..> = lit!(1);
>
> I think the only downside is that this expression isn't const expr anymore. We
> can change this to be
>
>     const trait FromLiteral {
>         fn from_literal(v: i64) -> Self;
>     }
>
> when const trait impl is stable upstream and we have MSRV bumped high enough to
> have an impl of it.
>
> Best,
> Gary

I think this is a great idea. I would further generalise it to work on
any integer const expression (Maybe FromConst::from_const, and cv!
instead of lit! if we want to make the distinction of literals vs const
expression values). One example where only literals are not enough is in
the Bitmap tests we have nz!(usize::MAX).

We still have some usages in const contexts for Alignment so I still
think it's valuable to keep the SizeConstants on Alignment. And I think
Alignment::SZ_* is more informative than cv!(...) (or lit!(...)). But of
course we can completely replace nz! with this.
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.