`build_assert` relies on the compiler to optimize out its error path.
Functions using it with its arguments must thus always be inlined,
otherwise the error path of `build_assert` might not be optimized out,
triggering a build error.
Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
---
rust/kernel/io.rs | 9 ++++++---
rust/kernel/io/resource.rs | 2 ++
2 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index ee182b0b5452..ccdd394099cb 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -120,7 +120,8 @@ macro_rules! define_read {
/// Bound checks are performed on compile time, hence if the offset is not known at compile
/// time, the build will fail.
$(#[$attr])*
- #[inline]
+ // Always inline to optimize out error path of `io_addr_assert`.
+ #[inline(always)]
pub fn $name(&self, offset: usize) -> $type_name {
let addr = self.io_addr_assert::<$type_name>(offset);
@@ -149,7 +150,8 @@ macro_rules! define_write {
/// Bound checks are performed on compile time, hence if the offset is not known at compile
/// time, the build will fail.
$(#[$attr])*
- #[inline]
+ // Always inline to optimize out error path of `io_addr_assert`.
+ #[inline(always)]
pub fn $name(&self, value: $type_name, offset: usize) {
let addr = self.io_addr_assert::<$type_name>(offset);
@@ -217,7 +219,8 @@ fn io_addr<U>(&self, offset: usize) -> Result<usize> {
self.addr().checked_add(offset).ok_or(EINVAL)
}
- #[inline]
+ // Always inline to optimize out error path of `build_assert`.
+ #[inline(always)]
fn io_addr_assert<U>(&self, offset: usize) -> usize {
build_assert!(Self::offset_valid::<U>(offset, SIZE));
diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
index bea3ee0ed87b..d9851923562c 100644
--- a/rust/kernel/io/resource.rs
+++ b/rust/kernel/io/resource.rs
@@ -223,6 +223,8 @@ impl Flags {
/// Resource represents a memory region that must be ioremaped using `ioremap_np`.
pub const IORESOURCE_MEM_NONPOSTED: Flags = Flags::new(bindings::IORESOURCE_MEM_NONPOSTED);
+ // Always inline to optimize out error path of `build_assert`.
+ #[inline(always)]
const fn new(value: u32) -> Self {
crate::build_assert!(value as u64 <= c_ulong::MAX as u64);
Flags(value as c_ulong)
--
2.52.0
On 11/27/25 18:11, Alexandre Courbot wrote:
> `build_assert` relies on the compiler to optimize out its error path.
> Functions using it with its arguments must thus always be inlined,
> otherwise the error path of `build_assert` might not be optimized out,
> triggering a build error.
>
> Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
> ---
> rust/kernel/io.rs | 9 ++++++---
> rust/kernel/io/resource.rs | 2 ++
> 2 files changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
> index ee182b0b5452..ccdd394099cb 100644
> --- a/rust/kernel/io.rs
> +++ b/rust/kernel/io.rs
> @@ -120,7 +120,8 @@ macro_rules! define_read {
> /// Bound checks are performed on compile time, hence if the offset is not known at compile
> /// time, the build will fail.
> $(#[$attr])*
> - #[inline]
> + // Always inline to optimize out error path of `io_addr_assert`.
> + #[inline(always)]
> pub fn $name(&self, offset: usize) -> $type_name {
> let addr = self.io_addr_assert::<$type_name>(offset);
>
> @@ -149,7 +150,8 @@ macro_rules! define_write {
> /// Bound checks are performed on compile time, hence if the offset is not known at compile
> /// time, the build will fail.
> $(#[$attr])*
> - #[inline]
> + // Always inline to optimize out error path of `io_addr_assert`.
> + #[inline(always)]
> pub fn $name(&self, value: $type_name, offset: usize) {
> let addr = self.io_addr_assert::<$type_name>(offset);
>
> @@ -217,7 +219,8 @@ fn io_addr<U>(&self, offset: usize) -> Result<usize> {
> self.addr().checked_add(offset).ok_or(EINVAL)
> }
>
> - #[inline]
> + // Always inline to optimize out error path of `build_assert`.
> + #[inline(always)]
> fn io_addr_assert<U>(&self, offset: usize) -> usize {
> build_assert!(Self::offset_valid::<U>(offset, SIZE));
>
> diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
> index bea3ee0ed87b..d9851923562c 100644
> --- a/rust/kernel/io/resource.rs
> +++ b/rust/kernel/io/resource.rs
> @@ -223,6 +223,8 @@ impl Flags {
> /// Resource represents a memory region that must be ioremaped using `ioremap_np`.
> pub const IORESOURCE_MEM_NONPOSTED: Flags = Flags::new(bindings::IORESOURCE_MEM_NONPOSTED);
>
> + // Always inline to optimize out error path of `build_assert`.
> + #[inline(always)]
> const fn new(value: u32) -> Self {
Does the build_assert problem actually manifest for const functions?
Regards,
Edwin Peer
> crate::build_assert!(value as u64 <= c_ulong::MAX as u64);
> Flags(value as c_ulong)
>
On Mon, Dec 1, 2025 at 9:07 PM Edwin Peer <epeer@nvidia.com> wrote:
>
>
> On 11/27/25 18:11, Alexandre Courbot wrote:
> > diff --git a/rust/kernel/io/resource.rs b/rust/kernel/io/resource.rs
> > index bea3ee0ed87b..d9851923562c 100644
> > --- a/rust/kernel/io/resource.rs
> > +++ b/rust/kernel/io/resource.rs
> > @@ -223,6 +223,8 @@ impl Flags {
> > /// Resource represents a memory region that must be ioremaped using `ioremap_np`.
> > pub const IORESOURCE_MEM_NONPOSTED: Flags = Flags::new(bindings::IORESOURCE_MEM_NONPOSTED);
> >
> > + // Always inline to optimize out error path of `build_assert`.
> > + #[inline(always)]
> > const fn new(value: u32) -> Self {
>
> Does the build_assert problem actually manifest for const functions?
Yes, the const marker only allows you to call it from const context.
It does not change behavior when it is called from non-const context.
Alice
© 2016 - 2026 Red Hat, Inc.