[PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants

John Hubbard posted 3 patches 3 weeks, 5 days ago
There is a newer version of this series
[PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
Posted by John Hubbard 3 weeks, 5 days ago
Alignment::new() takes a const usize, which means callers that work
with DeviceSize constants still need to import the usize SZ_*
variants. Add from_u64() so callers can write
Alignment::from_u64(u64::SZ_128K) and stay entirely in the
DeviceSize world.

Both asserts evaluate at compile time in const context, so there is
no runtime cost.

Signed-off-by: John Hubbard <jhubbard@nvidia.com>
---
 rust/kernel/ptr.rs | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
index 5b6a382637fe..b06f6b404a46 100644
--- a/rust/kernel/ptr.rs
+++ b/rust/kernel/ptr.rs
@@ -76,6 +76,41 @@ pub const fn new_checked(align: usize) -> Option<Self> {
         }
     }
 
+    /// Creates an [`Alignment`] from a [`u64`] value.
+    ///
+    /// This is useful when the alignment comes from a [`DeviceSize`] constant
+    /// rather than a [`usize`] literal.
+    ///
+    /// A build error is triggered if `align` is not a power of two, or if it
+    /// exceeds [`usize::MAX`].
+    ///
+    /// [`DeviceSize`]: crate::sizes::DeviceSize
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use kernel::ptr::Alignment;
+    /// use kernel::sizes::DeviceSize;
+    ///
+    /// let v = Alignment::from_u64(u64::SZ_128K);
+    /// assert_eq!(v.as_usize(), 0x0002_0000);
+    /// ```
+    #[inline(always)]
+    pub const fn from_u64(align: u64) -> Self {
+        assert!(
+            align.is_power_of_two(),
+            "Provided alignment is not a power of two."
+        );
+        assert!(
+            align <= usize::MAX as u64,
+            "Provided alignment exceeds usize::MAX."
+        );
+
+        // INVARIANT: `align` is a power of two.
+        // SAFETY: `align` is a power of two, fits in usize, and thus non-zero.
+        Self(unsafe { NonZero::new_unchecked(align as usize) })
+    }
+
     /// Returns the alignment of `T`.
     ///
     /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
-- 
2.53.0
Re: [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
Posted by Gary Guo 2 weeks ago
On Thu Mar 12, 2026 at 3:15 AM GMT, John Hubbard wrote:
> Alignment::new() takes a const usize, which means callers that work
> with DeviceSize constants still need to import the usize SZ_*
> variants. Add from_u64() so callers can write
> Alignment::from_u64(u64::SZ_128K) and stay entirely in the
> DeviceSize world.
>
> Both asserts evaluate at compile time in const context, so there is
> no runtime cost.
>
> Signed-off-by: John Hubbard <jhubbard@nvidia.com>
> ---
>  rust/kernel/ptr.rs | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
>
> diff --git a/rust/kernel/ptr.rs b/rust/kernel/ptr.rs
> index 5b6a382637fe..b06f6b404a46 100644
> --- a/rust/kernel/ptr.rs
> +++ b/rust/kernel/ptr.rs
> @@ -76,6 +76,41 @@ pub const fn new_checked(align: usize) -> Option<Self> {
>          }
>      }
>  
> +    /// Creates an [`Alignment`] from a [`u64`] value.
> +    ///
> +    /// This is useful when the alignment comes from a [`DeviceSize`] constant
> +    /// rather than a [`usize`] literal.
> +    ///
> +    /// A build error is triggered if `align` is not a power of two, or if it
> +    /// exceeds [`usize::MAX`].
> +    ///
> +    /// [`DeviceSize`]: crate::sizes::DeviceSize
> +    ///
> +    /// # Examples
> +    ///
> +    /// ```
> +    /// use kernel::ptr::Alignment;
> +    /// use kernel::sizes::DeviceSize;
> +    ///
> +    /// let v = Alignment::from_u64(u64::SZ_128K);
> +    /// assert_eq!(v.as_usize(), 0x0002_0000);
> +    /// ```
> +    #[inline(always)]
> +    pub const fn from_u64(align: u64) -> Self {
> +        assert!(
> +            align.is_power_of_two(),
> +            "Provided alignment is not a power of two."
> +        );

This should be build_assert! to match the doc.

Best,
Gary

> +        assert!(
> +            align <= usize::MAX as u64,
> +            "Provided alignment exceeds usize::MAX."
> +        );
> +
> +        // INVARIANT: `align` is a power of two.
> +        // SAFETY: `align` is a power of two, fits in usize, and thus non-zero.
> +        Self(unsafe { NonZero::new_unchecked(align as usize) })
> +    }
> +
>      /// Returns the alignment of `T`.
>      ///
>      /// This is equivalent to [`align_of`], but with the return value provided as an [`Alignment`].
Re: [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
Posted by Miguel Ojeda 3 weeks, 5 days ago
On Thu, Mar 12, 2026 at 4:15 AM John Hubbard <jhubbard@nvidia.com> wrote:
>
> +    /// A build error is triggered if `align` is not a power of two, or if it
> +    /// exceeds [`usize::MAX`].

I think this wording comes from the `new` constructor, but there we
use a const assert, not a runtime one.

So as you mention in the commit message,  it is true that if you call
it in a const context you will get it at compile-time error, but the
wording here in the docs seems to imply otherwise.

Cheers,
Miguel
Re: [PATCH v2 2/3] rust: ptr: add Alignment::from_u64() for DeviceSize constants
Posted by John Hubbard 3 weeks, 5 days ago
On 3/11/26 11:16 PM, Miguel Ojeda wrote:
> On Thu, Mar 12, 2026 at 4:15 AM John Hubbard <jhubbard@nvidia.com> wrote:
>>
>> +    /// A build error is triggered if `align` is not a power of two, or if it
>> +    /// exceeds [`usize::MAX`].
> 
> I think this wording comes from the `new` constructor, but there we

Yes it does--guilty as charged, haha. :)

> use a const assert, not a runtime one.
> 
> So as you mention in the commit message,  it is true that if you call
> it in a const context you will get it at compile-time error, but the
> wording here in the docs seems to imply otherwise.
> 

Good catch, thanks.


thanks,
-- 
John Hubbard