diff mbox series

[v9,4/6] rust: enable `clippy::as_underscore` lint

Message ID 20250416-ptr-as-ptr-v9-4-18ec29b1b1f3@gmail.com (mailing list archive)
State New
Headers show
Series rust: reduce `as` casts, enable related lints | expand

Commit Message

Tamir Duberstein April 16, 2025, 5:36 p.m. UTC
In Rust 1.63.0, Clippy introduced the `as_underscore` lint [1]:

> The conversion might include lossy conversion or a dangerous cast that
> might go undetected due to the type being inferred.
>
> The lint is allowed by default as using `_` is less wordy than always
> specifying the type.

Always specifying the type is especially helpful in function call
contexts where the inferred type may change at a distance. Specifying
the type also allows Clippy to spot more cases of `useless_conversion`.

The primary downside is the need to specify the type in trivial getters.
There are 4 such functions: 3 have become slightly less ergonomic, 1 was
revealed to be a `useless_conversion`.

While this doesn't eliminate unchecked `as` conversions, it makes such
conversions easier to scrutinize.  It also has the slight benefit of
removing a degree of freedom on which to bikeshed. Thus apply the
changes and enable the lint -- no functional change intended.

Link: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore [1]
Reviewed-by: Benno Lossin <benno.lossin@proton.me>
Signed-off-by: Tamir Duberstein <tamird@gmail.com>
---
 Makefile                           |  1 +
 rust/kernel/block/mq/operations.rs |  2 +-
 rust/kernel/block/mq/request.rs    |  2 +-
 rust/kernel/device_id.rs           |  2 +-
 rust/kernel/devres.rs              | 15 ++++++++-------
 rust/kernel/dma.rs                 |  2 +-
 rust/kernel/error.rs               |  2 +-
 rust/kernel/io.rs                  | 18 +++++++++---------
 rust/kernel/miscdevice.rs          |  2 +-
 rust/kernel/of.rs                  |  6 +++---
 rust/kernel/pci.rs                 |  9 ++++++---
 rust/kernel/str.rs                 |  8 ++++----
 rust/kernel/workqueue.rs           |  2 +-
 13 files changed, 38 insertions(+), 33 deletions(-)

Comments

Boqun Feng April 17, 2025, 5:55 p.m. UTC | #1
On Wed, Apr 16, 2025 at 01:36:08PM -0400, Tamir Duberstein wrote:
> In Rust 1.63.0, Clippy introduced the `as_underscore` lint [1]:
> 
> > The conversion might include lossy conversion or a dangerous cast that
> > might go undetected due to the type being inferred.
> >
> > The lint is allowed by default as using `_` is less wordy than always
> > specifying the type.
> 
> Always specifying the type is especially helpful in function call
> contexts where the inferred type may change at a distance. Specifying
> the type also allows Clippy to spot more cases of `useless_conversion`.
> 
> The primary downside is the need to specify the type in trivial getters.
> There are 4 such functions: 3 have become slightly less ergonomic, 1 was
> revealed to be a `useless_conversion`.
> 
> While this doesn't eliminate unchecked `as` conversions, it makes such
> conversions easier to scrutinize.  It also has the slight benefit of
> removing a degree of freedom on which to bikeshed. Thus apply the
> changes and enable the lint -- no functional change intended.
> 
> Link: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore [1]
> Reviewed-by: Benno Lossin <benno.lossin@proton.me>
> Signed-off-by: Tamir Duberstein <tamird@gmail.com>
> ---
>  Makefile                           |  1 +
>  rust/kernel/block/mq/operations.rs |  2 +-
>  rust/kernel/block/mq/request.rs    |  2 +-
>  rust/kernel/device_id.rs           |  2 +-
>  rust/kernel/devres.rs              | 15 ++++++++-------
>  rust/kernel/dma.rs                 |  2 +-
>  rust/kernel/error.rs               |  2 +-
>  rust/kernel/io.rs                  | 18 +++++++++---------
>  rust/kernel/miscdevice.rs          |  2 +-
>  rust/kernel/of.rs                  |  6 +++---
>  rust/kernel/pci.rs                 |  9 ++++++---
>  rust/kernel/str.rs                 |  8 ++++----
>  rust/kernel/workqueue.rs           |  2 +-
>  13 files changed, 38 insertions(+), 33 deletions(-)
> 
> diff --git a/Makefile b/Makefile
> index 04a5246171f9..57080a64913f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -475,6 +475,7 @@ export rust_common_flags := --edition=2021 \
>  			    -Wunreachable_pub \
>  			    -Wclippy::all \
>  			    -Wclippy::as_ptr_cast_mut \
> +			    -Wclippy::as_underscore \
>  			    -Wclippy::ignored_unit_patterns \
>  			    -Wclippy::mut_mut \
>  			    -Wclippy::needless_bitwise_bool \
> diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
> index 864ff379dc91..d18ef55490da 100644
> --- a/rust/kernel/block/mq/operations.rs
> +++ b/rust/kernel/block/mq/operations.rs
> @@ -101,7 +101,7 @@ impl<T: Operations> OperationsVTable<T> {
>          if let Err(e) = ret {
>              e.to_blk_status()
>          } else {
> -            bindings::BLK_STS_OK as _
> +            bindings::BLK_STS_OK as u8
>          }
>      }
>  
> diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
> index af5c9ac94f36..22697104bf8c 100644
> --- a/rust/kernel/block/mq/request.rs
> +++ b/rust/kernel/block/mq/request.rs
> @@ -125,7 +125,7 @@ pub fn end_ok(this: ARef<Self>) -> Result<(), ARef<Self>> {
>          // success of the call to `try_set_end` guarantees that there are no
>          // `ARef`s pointing to this request. Therefore it is safe to hand it
>          // back to the block layer.
> -        unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as _) };
> +        unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as u8) };
>  

We could consider defining a const block::mq::BLK_STATUS_OK as:

	const BLK_STATUS_OK: u8 = bindings::BLK_STS_OK as u8;

, because repeating the as pattern is a bit err-prone. But maybe in a
later patch.

>          Ok(())
>      }
> diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
> index e5859217a579..4063f09d76d9 100644
> --- a/rust/kernel/device_id.rs
> +++ b/rust/kernel/device_id.rs
> @@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
>              unsafe {
>                  raw_ids[i]
>                      .as_mut_ptr()
> -                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
> +                    .byte_add(T::DRIVER_DATA_OFFSET)
>                      .cast::<usize>()
>                      .write(i);
>              }
> diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
> index f7e8f5f53622..70d12014e476 100644
> --- a/rust/kernel/devres.rs
> +++ b/rust/kernel/devres.rs
> @@ -45,7 +45,7 @@ struct DevresInner<T> {
>  /// # Example
>  ///
>  /// ```no_run
> -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
> +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
>  /// # use core::ops::Deref;
>  ///
>  /// // See also [`pci::Bar`] for a real example.
> @@ -59,19 +59,19 @@ struct DevresInner<T> {
>  ///     unsafe fn new(paddr: usize) -> Result<Self>{
>  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
>  ///         // valid for `ioremap`.
> -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };


///         let addr = unsafe { bindings::ioremap(bindings::phys_addr_t::from(paddr), SIZE) };

better? Or even with .into()

///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };

>  ///         if addr.is_null() {
>  ///             return Err(ENOMEM);
>  ///         }
>  ///
> -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
>  ///     }
>  /// }
>  ///
>  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
>  ///     fn drop(&mut self) {
>  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
>  ///     }
>  /// }
>  ///
[...]
> diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> index 43ecf3c2e860..851a6339aa90 100644
> --- a/rust/kernel/dma.rs
> +++ b/rust/kernel/dma.rs
> @@ -38,7 +38,7 @@
>  impl Attrs {
>      /// Get the raw representation of this attribute.
>      pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> -        self.0 as _
> +        self.0 as crate::ffi::c_ulong

        crate::ffi::c_ulong::from(self.0)

maybe, a C unsigned long should always be able to hold the whole `Attr`
and a lossly casting is what this function does.

>      }
>  
>      /// Check whether `flags` is contained in `self`.
[...]
> @@ -70,19 +70,19 @@ pub fn maxsize(&self) -> usize {
>  ///     unsafe fn new(paddr: usize) -> Result<Self>{
>  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
>  ///         // valid for `ioremap`.
> -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };

Similarly:

///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };

or `from()`.

>  ///         if addr.is_null() {
>  ///             return Err(ENOMEM);
>  ///         }
>  ///
> -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
>  ///     }
>  /// }
>  ///
>  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
>  ///     fn drop(&mut self) {
>  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
>  ///     }
>  /// }
>  ///
[...]

The rest looks good to me. Thanks!

Regards,
Boqun
Tamir Duberstein April 17, 2025, 7:26 p.m. UTC | #2
On Thu, Apr 17, 2025 at 1:55 PM Boqun Feng <boqun.feng@gmail.com> wrote:
>
> On Wed, Apr 16, 2025 at 01:36:08PM -0400, Tamir Duberstein wrote:
> > In Rust 1.63.0, Clippy introduced the `as_underscore` lint [1]:
> >
> > > The conversion might include lossy conversion or a dangerous cast that
> > > might go undetected due to the type being inferred.
> > >
> > > The lint is allowed by default as using `_` is less wordy than always
> > > specifying the type.
> >
> > Always specifying the type is especially helpful in function call
> > contexts where the inferred type may change at a distance. Specifying
> > the type also allows Clippy to spot more cases of `useless_conversion`.
> >
> > The primary downside is the need to specify the type in trivial getters.
> > There are 4 such functions: 3 have become slightly less ergonomic, 1 was
> > revealed to be a `useless_conversion`.
> >
> > While this doesn't eliminate unchecked `as` conversions, it makes such
> > conversions easier to scrutinize.  It also has the slight benefit of
> > removing a degree of freedom on which to bikeshed. Thus apply the
> > changes and enable the lint -- no functional change intended.
> >
> > Link: https://rust-lang.github.io/rust-clippy/master/index.html#as_underscore [1]
> > Reviewed-by: Benno Lossin <benno.lossin@proton.me>
> > Signed-off-by: Tamir Duberstein <tamird@gmail.com>
> > ---
> >  Makefile                           |  1 +
> >  rust/kernel/block/mq/operations.rs |  2 +-
> >  rust/kernel/block/mq/request.rs    |  2 +-
> >  rust/kernel/device_id.rs           |  2 +-
> >  rust/kernel/devres.rs              | 15 ++++++++-------
> >  rust/kernel/dma.rs                 |  2 +-
> >  rust/kernel/error.rs               |  2 +-
> >  rust/kernel/io.rs                  | 18 +++++++++---------
> >  rust/kernel/miscdevice.rs          |  2 +-
> >  rust/kernel/of.rs                  |  6 +++---
> >  rust/kernel/pci.rs                 |  9 ++++++---
> >  rust/kernel/str.rs                 |  8 ++++----
> >  rust/kernel/workqueue.rs           |  2 +-
> >  13 files changed, 38 insertions(+), 33 deletions(-)
> >
> > diff --git a/Makefile b/Makefile
> > index 04a5246171f9..57080a64913f 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -475,6 +475,7 @@ export rust_common_flags := --edition=2021 \
> >                           -Wunreachable_pub \
> >                           -Wclippy::all \
> >                           -Wclippy::as_ptr_cast_mut \
> > +                         -Wclippy::as_underscore \
> >                           -Wclippy::ignored_unit_patterns \
> >                           -Wclippy::mut_mut \
> >                           -Wclippy::needless_bitwise_bool \
> > diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
> > index 864ff379dc91..d18ef55490da 100644
> > --- a/rust/kernel/block/mq/operations.rs
> > +++ b/rust/kernel/block/mq/operations.rs
> > @@ -101,7 +101,7 @@ impl<T: Operations> OperationsVTable<T> {
> >          if let Err(e) = ret {
> >              e.to_blk_status()
> >          } else {
> > -            bindings::BLK_STS_OK as _
> > +            bindings::BLK_STS_OK as u8
> >          }
> >      }
> >
> > diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
> > index af5c9ac94f36..22697104bf8c 100644
> > --- a/rust/kernel/block/mq/request.rs
> > +++ b/rust/kernel/block/mq/request.rs
> > @@ -125,7 +125,7 @@ pub fn end_ok(this: ARef<Self>) -> Result<(), ARef<Self>> {
> >          // success of the call to `try_set_end` guarantees that there are no
> >          // `ARef`s pointing to this request. Therefore it is safe to hand it
> >          // back to the block layer.
> > -        unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as _) };
> > +        unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as u8) };
> >
>
> We could consider defining a const block::mq::BLK_STATUS_OK as:
>
>         const BLK_STATUS_OK: u8 = bindings::BLK_STS_OK as u8;
>
> , because repeating the as pattern is a bit err-prone. But maybe in a
> later patch.

Sure. I think there's only this instance at the moment.

>
> >          Ok(())
> >      }
> > diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
> > index e5859217a579..4063f09d76d9 100644
> > --- a/rust/kernel/device_id.rs
> > +++ b/rust/kernel/device_id.rs
> > @@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
> >              unsafe {
> >                  raw_ids[i]
> >                      .as_mut_ptr()
> > -                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
> > +                    .byte_add(T::DRIVER_DATA_OFFSET)
> >                      .cast::<usize>()
> >                      .write(i);
> >              }
> > diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
> > index f7e8f5f53622..70d12014e476 100644
> > --- a/rust/kernel/devres.rs
> > +++ b/rust/kernel/devres.rs
> > @@ -45,7 +45,7 @@ struct DevresInner<T> {
> >  /// # Example
> >  ///
> >  /// ```no_run
> > -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
> > +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
> >  /// # use core::ops::Deref;
> >  ///
> >  /// // See also [`pci::Bar`] for a real example.
> > @@ -59,19 +59,19 @@ struct DevresInner<T> {
> >  ///     unsafe fn new(paddr: usize) -> Result<Self>{
> >  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
> >  ///         // valid for `ioremap`.
> > -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> > +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
>
>
> ///         let addr = unsafe { bindings::ioremap(bindings::phys_addr_t::from(paddr), SIZE) };
>
> better? Or even with .into()
>
> ///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };

This doesn't compile because `paddr` is usize, and
`bindings::phys_addr_t` is u64 (on my machine, which is aarch64).

> >  ///         if addr.is_null() {
> >  ///             return Err(ENOMEM);
> >  ///         }
> >  ///
> > -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> > +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
> >  ///     }
> >  /// }
> >  ///
> >  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
> >  ///     fn drop(&mut self) {
> >  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> > -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> > +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
> >  ///     }
> >  /// }
> >  ///
> [...]
> > diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> > index 43ecf3c2e860..851a6339aa90 100644
> > --- a/rust/kernel/dma.rs
> > +++ b/rust/kernel/dma.rs
> > @@ -38,7 +38,7 @@
> >  impl Attrs {
> >      /// Get the raw representation of this attribute.
> >      pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> > -        self.0 as _
> > +        self.0 as crate::ffi::c_ulong
>
>         crate::ffi::c_ulong::from(self.0)
>
> maybe, a C unsigned long should always be able to hold the whole `Attr`
> and a lossly casting is what this function does.

This also doesn't compile: "the trait `core::convert::From<u32>` is
not implemented for `usize`". Upstream has ambitions of running on
16-bit, I guess :)

>
> >      }
> >
> >      /// Check whether `flags` is contained in `self`.
> [...]
> > @@ -70,19 +70,19 @@ pub fn maxsize(&self) -> usize {
> >  ///     unsafe fn new(paddr: usize) -> Result<Self>{
> >  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
> >  ///         // valid for `ioremap`.
> > -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> > +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
>
> Similarly:
>
> ///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };
>
> or `from()`.

As above, doesn't compile.

> >  ///         if addr.is_null() {
> >  ///             return Err(ENOMEM);
> >  ///         }
> >  ///
> > -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> > +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
> >  ///     }
> >  /// }
> >  ///
> >  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
> >  ///     fn drop(&mut self) {
> >  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> > -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> > +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
> >  ///     }
> >  /// }
> >  ///
> [...]
>
> The rest looks good to me. Thanks!
>
> Regards,
> Boqun

Thanks!
Boqun Feng April 17, 2025, 8:12 p.m. UTC | #3
On Thu, Apr 17, 2025 at 03:26:14PM -0400, Tamir Duberstein wrote:
[...]
> >
> > >          Ok(())
> > >      }
> > > diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
> > > index e5859217a579..4063f09d76d9 100644
> > > --- a/rust/kernel/device_id.rs
> > > +++ b/rust/kernel/device_id.rs
> > > @@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
> > >              unsafe {
> > >                  raw_ids[i]
> > >                      .as_mut_ptr()
> > > -                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
> > > +                    .byte_add(T::DRIVER_DATA_OFFSET)
> > >                      .cast::<usize>()
> > >                      .write(i);
> > >              }
> > > diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
> > > index f7e8f5f53622..70d12014e476 100644
> > > --- a/rust/kernel/devres.rs
> > > +++ b/rust/kernel/devres.rs
> > > @@ -45,7 +45,7 @@ struct DevresInner<T> {
> > >  /// # Example
> > >  ///
> > >  /// ```no_run
> > > -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
> > > +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
> > >  /// # use core::ops::Deref;
> > >  ///
> > >  /// // See also [`pci::Bar`] for a real example.
> > > @@ -59,19 +59,19 @@ struct DevresInner<T> {
> > >  ///     unsafe fn new(paddr: usize) -> Result<Self>{
> > >  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
> > >  ///         // valid for `ioremap`.
> > > -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> > > +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
> >
> >
> > ///         let addr = unsafe { bindings::ioremap(bindings::phys_addr_t::from(paddr), SIZE) };
> >
> > better? Or even with .into()
> >
> > ///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };
> 
> This doesn't compile because `paddr` is usize, and
> `bindings::phys_addr_t` is u64 (on my machine, which is aarch64).
> 

Ok, looks like Rust yet doesn't provide From/Into between usize and u64
even if the pointer size is fixed. Latest discussion can be found at:

	https://github.com/rust-lang/rust/issues/41619#issuecomment-2056902943

Lemme see if we can get an issue tracking this. Thanks for taking a
look.

> > >  ///         if addr.is_null() {
> > >  ///             return Err(ENOMEM);
> > >  ///         }
> > >  ///
> > > -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> > > +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
> > >  ///     }
> > >  /// }
> > >  ///
> > >  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
> > >  ///     fn drop(&mut self) {
> > >  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> > > -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> > > +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
> > >  ///     }
> > >  /// }
> > >  ///
> > [...]
> > > diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> > > index 43ecf3c2e860..851a6339aa90 100644
> > > --- a/rust/kernel/dma.rs
> > > +++ b/rust/kernel/dma.rs
> > > @@ -38,7 +38,7 @@
> > >  impl Attrs {
> > >      /// Get the raw representation of this attribute.
> > >      pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> > > -        self.0 as _
> > > +        self.0 as crate::ffi::c_ulong
> >
> >         crate::ffi::c_ulong::from(self.0)
> >
> > maybe, a C unsigned long should always be able to hold the whole `Attr`
> > and a lossly casting is what this function does.
> 
> This also doesn't compile: "the trait `core::convert::From<u32>` is
> not implemented for `usize`". Upstream has ambitions of running on
> 16-bit, I guess :)
> 

They do but they also have the target_pointer_width cfg, so they can
totally provide these functions. It's just they want to find a better
way (like the link I post above).

Regards,
Boqun
Tamir Duberstein April 18, 2025, 12:08 p.m. UTC | #4
On Thu, Apr 17, 2025 at 4:12 PM Boqun Feng <boqun.feng@gmail.com> wrote:
>
> On Thu, Apr 17, 2025 at 03:26:14PM -0400, Tamir Duberstein wrote:
> [...]
> > >
> > > >          Ok(())
> > > >      }
> > > > diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
> > > > index e5859217a579..4063f09d76d9 100644
> > > > --- a/rust/kernel/device_id.rs
> > > > +++ b/rust/kernel/device_id.rs
> > > > @@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
> > > >              unsafe {
> > > >                  raw_ids[i]
> > > >                      .as_mut_ptr()
> > > > -                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
> > > > +                    .byte_add(T::DRIVER_DATA_OFFSET)
> > > >                      .cast::<usize>()
> > > >                      .write(i);
> > > >              }
> > > > diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
> > > > index f7e8f5f53622..70d12014e476 100644
> > > > --- a/rust/kernel/devres.rs
> > > > +++ b/rust/kernel/devres.rs
> > > > @@ -45,7 +45,7 @@ struct DevresInner<T> {
> > > >  /// # Example
> > > >  ///
> > > >  /// ```no_run
> > > > -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
> > > > +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
> > > >  /// # use core::ops::Deref;
> > > >  ///
> > > >  /// // See also [`pci::Bar`] for a real example.
> > > > @@ -59,19 +59,19 @@ struct DevresInner<T> {
> > > >  ///     unsafe fn new(paddr: usize) -> Result<Self>{
> > > >  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
> > > >  ///         // valid for `ioremap`.
> > > > -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> > > > +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
> > >
> > >
> > > ///         let addr = unsafe { bindings::ioremap(bindings::phys_addr_t::from(paddr), SIZE) };
> > >
> > > better? Or even with .into()
> > >
> > > ///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };
> >
> > This doesn't compile because `paddr` is usize, and
> > `bindings::phys_addr_t` is u64 (on my machine, which is aarch64).
> >
>
> Ok, looks like Rust yet doesn't provide From/Into between usize and u64
> even if the pointer size is fixed. Latest discussion can be found at:
>
>         https://github.com/rust-lang/rust/issues/41619#issuecomment-2056902943
>
> Lemme see if we can get an issue tracking this. Thanks for taking a
> look.
>
> > > >  ///         if addr.is_null() {
> > > >  ///             return Err(ENOMEM);
> > > >  ///         }
> > > >  ///
> > > > -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> > > > +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
> > > >  ///     }
> > > >  /// }
> > > >  ///
> > > >  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
> > > >  ///     fn drop(&mut self) {
> > > >  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> > > > -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> > > > +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
> > > >  ///     }
> > > >  /// }
> > > >  ///
> > > [...]
> > > > diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> > > > index 43ecf3c2e860..851a6339aa90 100644
> > > > --- a/rust/kernel/dma.rs
> > > > +++ b/rust/kernel/dma.rs
> > > > @@ -38,7 +38,7 @@
> > > >  impl Attrs {
> > > >      /// Get the raw representation of this attribute.
> > > >      pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> > > > -        self.0 as _
> > > > +        self.0 as crate::ffi::c_ulong
> > >
> > >         crate::ffi::c_ulong::from(self.0)
> > >
> > > maybe, a C unsigned long should always be able to hold the whole `Attr`
> > > and a lossly casting is what this function does.
> >
> > This also doesn't compile: "the trait `core::convert::From<u32>` is
> > not implemented for `usize`". Upstream has ambitions of running on
> > 16-bit, I guess :)
> >
>
> They do but they also have the target_pointer_width cfg, so they can
> totally provide these functions. It's just they want to find a better
> way (like the link I post above).

Did you want me to hold off on the respin on this point, or shall I go ahead?
Boqun Feng April 18, 2025, 3:09 p.m. UTC | #5
On Fri, Apr 18, 2025 at 08:08:02AM -0400, Tamir Duberstein wrote:
> On Thu, Apr 17, 2025 at 4:12 PM Boqun Feng <boqun.feng@gmail.com> wrote:
> >
> > On Thu, Apr 17, 2025 at 03:26:14PM -0400, Tamir Duberstein wrote:
> > [...]
> > > >
> > > > >          Ok(())
> > > > >      }
> > > > > diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
> > > > > index e5859217a579..4063f09d76d9 100644
> > > > > --- a/rust/kernel/device_id.rs
> > > > > +++ b/rust/kernel/device_id.rs
> > > > > @@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
> > > > >              unsafe {
> > > > >                  raw_ids[i]
> > > > >                      .as_mut_ptr()
> > > > > -                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
> > > > > +                    .byte_add(T::DRIVER_DATA_OFFSET)
> > > > >                      .cast::<usize>()
> > > > >                      .write(i);
> > > > >              }
> > > > > diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
> > > > > index f7e8f5f53622..70d12014e476 100644
> > > > > --- a/rust/kernel/devres.rs
> > > > > +++ b/rust/kernel/devres.rs
> > > > > @@ -45,7 +45,7 @@ struct DevresInner<T> {
> > > > >  /// # Example
> > > > >  ///
> > > > >  /// ```no_run
> > > > > -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
> > > > > +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
> > > > >  /// # use core::ops::Deref;
> > > > >  ///
> > > > >  /// // See also [`pci::Bar`] for a real example.
> > > > > @@ -59,19 +59,19 @@ struct DevresInner<T> {
> > > > >  ///     unsafe fn new(paddr: usize) -> Result<Self>{
> > > > >  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
> > > > >  ///         // valid for `ioremap`.
> > > > > -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> > > > > +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
> > > >
> > > >
> > > > ///         let addr = unsafe { bindings::ioremap(bindings::phys_addr_t::from(paddr), SIZE) };
> > > >
> > > > better? Or even with .into()
> > > >
> > > > ///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };
> > >
> > > This doesn't compile because `paddr` is usize, and
> > > `bindings::phys_addr_t` is u64 (on my machine, which is aarch64).
> > >
> >
> > Ok, looks like Rust yet doesn't provide From/Into between usize and u64
> > even if the pointer size is fixed. Latest discussion can be found at:
> >
> >         https://github.com/rust-lang/rust/issues/41619#issuecomment-2056902943
> >
> > Lemme see if we can get an issue tracking this. Thanks for taking a
> > look.
> >
> > > > >  ///         if addr.is_null() {
> > > > >  ///             return Err(ENOMEM);
> > > > >  ///         }
> > > > >  ///
> > > > > -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> > > > > +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
> > > > >  ///     }
> > > > >  /// }
> > > > >  ///
> > > > >  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
> > > > >  ///     fn drop(&mut self) {
> > > > >  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> > > > > -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> > > > > +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
> > > > >  ///     }
> > > > >  /// }
> > > > >  ///
> > > > [...]
> > > > > diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> > > > > index 43ecf3c2e860..851a6339aa90 100644
> > > > > --- a/rust/kernel/dma.rs
> > > > > +++ b/rust/kernel/dma.rs
> > > > > @@ -38,7 +38,7 @@
> > > > >  impl Attrs {
> > > > >      /// Get the raw representation of this attribute.
> > > > >      pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> > > > > -        self.0 as _
> > > > > +        self.0 as crate::ffi::c_ulong
> > > >
> > > >         crate::ffi::c_ulong::from(self.0)
> > > >
> > > > maybe, a C unsigned long should always be able to hold the whole `Attr`
> > > > and a lossly casting is what this function does.
> > >
> > > This also doesn't compile: "the trait `core::convert::From<u32>` is
> > > not implemented for `usize`". Upstream has ambitions of running on
> > > 16-bit, I guess :)
> > >
> >
> > They do but they also have the target_pointer_width cfg, so they can
> > totally provide these functions. It's just they want to find a better
> > way (like the link I post above).
> 
> Did you want me to hold off on the respin on this point, or shall I go ahead?

No need to wait. This doesn't affect your current patch. But we do need
to start making some decisions about how we handle the conversions *32
=> *size, *size => *64 and c*long <=> *size, they should all be lossless
in the context of kernel. We have 3 options:

1.	Using `as`.
2.	Having our own to_*size(*32), to_*64(*size), to_*size(*64),
	to_c*long(*size) and to_*size(c*long) helper functions.
3.	Waiting and using what Rust upstream comes up.

I'm leaning towards to 2 and then 3, because using `as` can sometimes
surprise you when you change the type. Thoughts?

Regards,
Boqun
Tamir Duberstein April 18, 2025, 3:15 p.m. UTC | #6
On Fri, Apr 18, 2025 at 11:09 AM Boqun Feng <boqun.feng@gmail.com> wrote:
>
> On Fri, Apr 18, 2025 at 08:08:02AM -0400, Tamir Duberstein wrote:
> > On Thu, Apr 17, 2025 at 4:12 PM Boqun Feng <boqun.feng@gmail.com> wrote:
> > >
> > > On Thu, Apr 17, 2025 at 03:26:14PM -0400, Tamir Duberstein wrote:
> > > [...]
> > > > >
> > > > > >          Ok(())
> > > > > >      }
> > > > > > diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
> > > > > > index e5859217a579..4063f09d76d9 100644
> > > > > > --- a/rust/kernel/device_id.rs
> > > > > > +++ b/rust/kernel/device_id.rs
> > > > > > @@ -82,7 +82,7 @@ impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
> > > > > >              unsafe {
> > > > > >                  raw_ids[i]
> > > > > >                      .as_mut_ptr()
> > > > > > -                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
> > > > > > +                    .byte_add(T::DRIVER_DATA_OFFSET)
> > > > > >                      .cast::<usize>()
> > > > > >                      .write(i);
> > > > > >              }
> > > > > > diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
> > > > > > index f7e8f5f53622..70d12014e476 100644
> > > > > > --- a/rust/kernel/devres.rs
> > > > > > +++ b/rust/kernel/devres.rs
> > > > > > @@ -45,7 +45,7 @@ struct DevresInner<T> {
> > > > > >  /// # Example
> > > > > >  ///
> > > > > >  /// ```no_run
> > > > > > -/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
> > > > > > +/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
> > > > > >  /// # use core::ops::Deref;
> > > > > >  ///
> > > > > >  /// // See also [`pci::Bar`] for a real example.
> > > > > > @@ -59,19 +59,19 @@ struct DevresInner<T> {
> > > > > >  ///     unsafe fn new(paddr: usize) -> Result<Self>{
> > > > > >  ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
> > > > > >  ///         // valid for `ioremap`.
> > > > > > -///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
> > > > > > +///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
> > > > >
> > > > >
> > > > > ///         let addr = unsafe { bindings::ioremap(bindings::phys_addr_t::from(paddr), SIZE) };
> > > > >
> > > > > better? Or even with .into()
> > > > >
> > > > > ///         let addr = unsafe { bindings::ioremap(paddr.into(), SIZE) };
> > > >
> > > > This doesn't compile because `paddr` is usize, and
> > > > `bindings::phys_addr_t` is u64 (on my machine, which is aarch64).
> > > >
> > >
> > > Ok, looks like Rust yet doesn't provide From/Into between usize and u64
> > > even if the pointer size is fixed. Latest discussion can be found at:
> > >
> > >         https://github.com/rust-lang/rust/issues/41619#issuecomment-2056902943
> > >
> > > Lemme see if we can get an issue tracking this. Thanks for taking a
> > > look.
> > >
> > > > > >  ///         if addr.is_null() {
> > > > > >  ///             return Err(ENOMEM);
> > > > > >  ///         }
> > > > > >  ///
> > > > > > -///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
> > > > > > +///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
> > > > > >  ///     }
> > > > > >  /// }
> > > > > >  ///
> > > > > >  /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
> > > > > >  ///     fn drop(&mut self) {
> > > > > >  ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
> > > > > > -///         unsafe { bindings::iounmap(self.0.addr() as _); };
> > > > > > +///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
> > > > > >  ///     }
> > > > > >  /// }
> > > > > >  ///
> > > > > [...]
> > > > > > diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
> > > > > > index 43ecf3c2e860..851a6339aa90 100644
> > > > > > --- a/rust/kernel/dma.rs
> > > > > > +++ b/rust/kernel/dma.rs
> > > > > > @@ -38,7 +38,7 @@
> > > > > >  impl Attrs {
> > > > > >      /// Get the raw representation of this attribute.
> > > > > >      pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
> > > > > > -        self.0 as _
> > > > > > +        self.0 as crate::ffi::c_ulong
> > > > >
> > > > >         crate::ffi::c_ulong::from(self.0)
> > > > >
> > > > > maybe, a C unsigned long should always be able to hold the whole `Attr`
> > > > > and a lossly casting is what this function does.
> > > >
> > > > This also doesn't compile: "the trait `core::convert::From<u32>` is
> > > > not implemented for `usize`". Upstream has ambitions of running on
> > > > 16-bit, I guess :)
> > > >
> > >
> > > They do but they also have the target_pointer_width cfg, so they can
> > > totally provide these functions. It's just they want to find a better
> > > way (like the link I post above).
> >
> > Did you want me to hold off on the respin on this point, or shall I go ahead?
>
> No need to wait. This doesn't affect your current patch. But we do need
> to start making some decisions about how we handle the conversions *32
> => *size, *size => *64 and c*long <=> *size, they should all be lossless
> in the context of kernel. We have 3 options:
>
> 1.      Using `as`.
> 2.      Having our own to_*size(*32), to_*64(*size), to_*size(*64),
>         to_c*long(*size) and to_*size(c*long) helper functions.
> 3.      Waiting and using what Rust upstream comes up.
>
> I'm leaning towards to 2 and then 3, because using `as` can sometimes
> surprise you when you change the type. Thoughts?

Yes, I think that's the right thing to do. That, along with the
provenance functions, might even allow us to turn on
https://rust-lang.github.io/rust-clippy/master/index.html#as_conversions.
diff mbox series

Patch

diff --git a/Makefile b/Makefile
index 04a5246171f9..57080a64913f 100644
--- a/Makefile
+++ b/Makefile
@@ -475,6 +475,7 @@  export rust_common_flags := --edition=2021 \
 			    -Wunreachable_pub \
 			    -Wclippy::all \
 			    -Wclippy::as_ptr_cast_mut \
+			    -Wclippy::as_underscore \
 			    -Wclippy::ignored_unit_patterns \
 			    -Wclippy::mut_mut \
 			    -Wclippy::needless_bitwise_bool \
diff --git a/rust/kernel/block/mq/operations.rs b/rust/kernel/block/mq/operations.rs
index 864ff379dc91..d18ef55490da 100644
--- a/rust/kernel/block/mq/operations.rs
+++ b/rust/kernel/block/mq/operations.rs
@@ -101,7 +101,7 @@  impl<T: Operations> OperationsVTable<T> {
         if let Err(e) = ret {
             e.to_blk_status()
         } else {
-            bindings::BLK_STS_OK as _
+            bindings::BLK_STS_OK as u8
         }
     }
 
diff --git a/rust/kernel/block/mq/request.rs b/rust/kernel/block/mq/request.rs
index af5c9ac94f36..22697104bf8c 100644
--- a/rust/kernel/block/mq/request.rs
+++ b/rust/kernel/block/mq/request.rs
@@ -125,7 +125,7 @@  pub fn end_ok(this: ARef<Self>) -> Result<(), ARef<Self>> {
         // success of the call to `try_set_end` guarantees that there are no
         // `ARef`s pointing to this request. Therefore it is safe to hand it
         // back to the block layer.
-        unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as _) };
+        unsafe { bindings::blk_mq_end_request(request_ptr, bindings::BLK_STS_OK as u8) };
 
         Ok(())
     }
diff --git a/rust/kernel/device_id.rs b/rust/kernel/device_id.rs
index e5859217a579..4063f09d76d9 100644
--- a/rust/kernel/device_id.rs
+++ b/rust/kernel/device_id.rs
@@ -82,7 +82,7 @@  impl<T: RawDeviceId, U, const N: usize> IdArray<T, U, N> {
             unsafe {
                 raw_ids[i]
                     .as_mut_ptr()
-                    .byte_offset(T::DRIVER_DATA_OFFSET as _)
+                    .byte_add(T::DRIVER_DATA_OFFSET)
                     .cast::<usize>()
                     .write(i);
             }
diff --git a/rust/kernel/devres.rs b/rust/kernel/devres.rs
index f7e8f5f53622..70d12014e476 100644
--- a/rust/kernel/devres.rs
+++ b/rust/kernel/devres.rs
@@ -45,7 +45,7 @@  struct DevresInner<T> {
 /// # Example
 ///
 /// ```no_run
-/// # use kernel::{bindings, c_str, device::Device, devres::Devres, io::{Io, IoRaw}};
+/// # use kernel::{bindings, c_str, device::Device, devres::Devres, ffi::c_void, io::{Io, IoRaw}};
 /// # use core::ops::Deref;
 ///
 /// // See also [`pci::Bar`] for a real example.
@@ -59,19 +59,19 @@  struct DevresInner<T> {
 ///     unsafe fn new(paddr: usize) -> Result<Self>{
 ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
 ///         // valid for `ioremap`.
-///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
+///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
 ///         if addr.is_null() {
 ///             return Err(ENOMEM);
 ///         }
 ///
-///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
+///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
 ///     }
 /// }
 ///
 /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
 ///     fn drop(&mut self) {
 ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
-///         unsafe { bindings::iounmap(self.0.addr() as _); };
+///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
 ///     }
 /// }
 ///
@@ -115,8 +115,9 @@  fn new(dev: &Device, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> {
 
         // SAFETY: `devm_add_action` guarantees to call `Self::devres_callback` once `dev` is
         // detached.
-        let ret =
-            unsafe { bindings::devm_add_action(dev.as_raw(), Some(inner.callback), data as _) };
+        let ret = unsafe {
+            bindings::devm_add_action(dev.as_raw(), Some(inner.callback), data.cast_mut().cast())
+        };
 
         if ret != 0 {
             // SAFETY: We just created another reference to `inner` in order to pass it to
@@ -130,7 +131,7 @@  fn new(dev: &Device, data: T, flags: Flags) -> Result<Arc<DevresInner<T>>> {
     }
 
     fn as_ptr(&self) -> *const Self {
-        self as _
+        self
     }
 
     fn remove_action(this: &Arc<Self>) {
diff --git a/rust/kernel/dma.rs b/rust/kernel/dma.rs
index 43ecf3c2e860..851a6339aa90 100644
--- a/rust/kernel/dma.rs
+++ b/rust/kernel/dma.rs
@@ -38,7 +38,7 @@ 
 impl Attrs {
     /// Get the raw representation of this attribute.
     pub(crate) fn as_raw(self) -> crate::ffi::c_ulong {
-        self.0 as _
+        self.0 as crate::ffi::c_ulong
     }
 
     /// Check whether `flags` is contained in `self`.
diff --git a/rust/kernel/error.rs b/rust/kernel/error.rs
index afcb00cb6a75..fd7a8b759437 100644
--- a/rust/kernel/error.rs
+++ b/rust/kernel/error.rs
@@ -153,7 +153,7 @@  pub(crate) fn to_blk_status(self) -> bindings::blk_status_t {
     /// Returns the error encoded as a pointer.
     pub fn to_ptr<T>(self) -> *mut T {
         // SAFETY: `self.0` is a valid error due to its invariant.
-        unsafe { bindings::ERR_PTR(self.0.get() as _).cast() }
+        unsafe { bindings::ERR_PTR(self.0.get() as isize).cast() }
     }
 
     /// Returns a string representing the error, if one exists.
diff --git a/rust/kernel/io.rs b/rust/kernel/io.rs
index 72d80a6f131e..c08de4121637 100644
--- a/rust/kernel/io.rs
+++ b/rust/kernel/io.rs
@@ -5,7 +5,7 @@ 
 //! C header: [`include/asm-generic/io.h`](srctree/include/asm-generic/io.h)
 
 use crate::error::{code::EINVAL, Result};
-use crate::{bindings, build_assert};
+use crate::{bindings, build_assert, ffi::c_void};
 
 /// Raw representation of an MMIO region.
 ///
@@ -56,7 +56,7 @@  pub fn maxsize(&self) -> usize {
 /// # Examples
 ///
 /// ```no_run
-/// # use kernel::{bindings, io::{Io, IoRaw}};
+/// # use kernel::{bindings, ffi::c_void, io::{Io, IoRaw}};
 /// # use core::ops::Deref;
 ///
 /// // See also [`pci::Bar`] for a real example.
@@ -70,19 +70,19 @@  pub fn maxsize(&self) -> usize {
 ///     unsafe fn new(paddr: usize) -> Result<Self>{
 ///         // SAFETY: By the safety requirements of this function [`paddr`, `paddr` + `SIZE`) is
 ///         // valid for `ioremap`.
-///         let addr = unsafe { bindings::ioremap(paddr as _, SIZE as _) };
+///         let addr = unsafe { bindings::ioremap(paddr as bindings::phys_addr_t, SIZE) };
 ///         if addr.is_null() {
 ///             return Err(ENOMEM);
 ///         }
 ///
-///         Ok(IoMem(IoRaw::new(addr as _, SIZE)?))
+///         Ok(IoMem(IoRaw::new(addr as usize, SIZE)?))
 ///     }
 /// }
 ///
 /// impl<const SIZE: usize> Drop for IoMem<SIZE> {
 ///     fn drop(&mut self) {
 ///         // SAFETY: `self.0.addr()` is guaranteed to be properly mapped by `Self::new`.
-///         unsafe { bindings::iounmap(self.0.addr() as _); };
+///         unsafe { bindings::iounmap(self.0.addr() as *mut c_void); };
 ///     }
 /// }
 ///
@@ -119,7 +119,7 @@  pub fn $name(&self, offset: usize) -> $type_name {
             let addr = self.io_addr_assert::<$type_name>(offset);
 
             // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
-            unsafe { bindings::$c_fn(addr as _) }
+            unsafe { bindings::$c_fn(addr as *const c_void) }
         }
 
         /// Read IO data from a given offset.
@@ -131,7 +131,7 @@  pub fn $try_name(&self, offset: usize) -> Result<$type_name> {
             let addr = self.io_addr::<$type_name>(offset)?;
 
             // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
-            Ok(unsafe { bindings::$c_fn(addr as _) })
+            Ok(unsafe { bindings::$c_fn(addr as *const c_void) })
         }
     };
 }
@@ -148,7 +148,7 @@  pub fn $name(&self, value: $type_name, offset: usize) {
             let addr = self.io_addr_assert::<$type_name>(offset);
 
             // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
-            unsafe { bindings::$c_fn(value, addr as _, ) }
+            unsafe { bindings::$c_fn(value, addr as *mut c_void) }
         }
 
         /// Write IO data from a given offset.
@@ -160,7 +160,7 @@  pub fn $try_name(&self, value: $type_name, offset: usize) -> Result {
             let addr = self.io_addr::<$type_name>(offset)?;
 
             // SAFETY: By the type invariant `addr` is a valid address for MMIO operations.
-            unsafe { bindings::$c_fn(value, addr as _) }
+            unsafe { bindings::$c_fn(value, addr as *mut c_void) }
             Ok(())
         }
     };
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
index fa9ecc42602a..6f9a7f97b7e5 100644
--- a/rust/kernel/miscdevice.rs
+++ b/rust/kernel/miscdevice.rs
@@ -33,7 +33,7 @@  impl MiscDeviceOptions {
     pub const fn into_raw<T: MiscDevice>(self) -> bindings::miscdevice {
         // SAFETY: All zeros is valid for this C type.
         let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };
-        result.minor = bindings::MISC_DYNAMIC_MINOR as _;
+        result.minor = bindings::MISC_DYNAMIC_MINOR as i32;
         result.name = self.name.as_char_ptr();
         result.fops = MiscdeviceVTable::<T>::build();
         result
diff --git a/rust/kernel/of.rs b/rust/kernel/of.rs
index 04f2d8ef29cb..40d1bd13682c 100644
--- a/rust/kernel/of.rs
+++ b/rust/kernel/of.rs
@@ -22,7 +22,7 @@  unsafe impl RawDeviceId for DeviceId {
     const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::of_device_id, data);
 
     fn index(&self) -> usize {
-        self.0.data as _
+        self.0.data as usize
     }
 }
 
@@ -34,10 +34,10 @@  pub const fn new(compatible: &'static CStr) -> Self {
         // SAFETY: FFI type is valid to be zero-initialized.
         let mut of: bindings::of_device_id = unsafe { core::mem::zeroed() };
 
-        // TODO: Use `clone_from_slice` once the corresponding types do match.
+        // TODO: Use `copy_from_slice` once stabilized for `const`.
         let mut i = 0;
         while i < src.len() {
-            of.compatible[i] = src[i] as _;
+            of.compatible[i] = src[i];
             i += 1;
         }
 
diff --git a/rust/kernel/pci.rs b/rust/kernel/pci.rs
index 391b4f070b1c..7efbbe5f8f59 100644
--- a/rust/kernel/pci.rs
+++ b/rust/kernel/pci.rs
@@ -169,7 +169,7 @@  unsafe impl RawDeviceId for DeviceId {
     const DRIVER_DATA_OFFSET: usize = core::mem::offset_of!(bindings::pci_device_id, driver_data);
 
     fn index(&self) -> usize {
-        self.0.driver_data as _
+        self.0.driver_data
     }
 }
 
@@ -204,7 +204,10 @@  macro_rules! pci_device_table {
 ///     MODULE_PCI_TABLE,
 ///     <MyDriver as pci::Driver>::IdInfo,
 ///     [
-///         (pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as _), ())
+///         (
+///             pci::DeviceId::from_id(bindings::PCI_VENDOR_ID_REDHAT, bindings::PCI_ANY_ID as u32),
+///             (),
+///         )
 ///     ]
 /// );
 ///
@@ -327,7 +330,7 @@  unsafe fn do_release(pdev: &Device, ioptr: usize, num: i32) {
         // `ioptr` is valid by the safety requirements.
         // `num` is valid by the safety requirements.
         unsafe {
-            bindings::pci_iounmap(pdev.as_raw(), ioptr as _);
+            bindings::pci_iounmap(pdev.as_raw(), ioptr as *mut kernel::ffi::c_void);
             bindings::pci_release_region(pdev.as_raw(), num);
         }
     }
diff --git a/rust/kernel/str.rs b/rust/kernel/str.rs
index 02863c40c21b..40034f77fc2f 100644
--- a/rust/kernel/str.rs
+++ b/rust/kernel/str.rs
@@ -738,9 +738,9 @@  fn new() -> Self {
     pub(crate) unsafe fn from_ptrs(pos: *mut u8, end: *mut u8) -> Self {
         // INVARIANT: The safety requirements guarantee the type invariants.
         Self {
-            beg: pos as _,
-            pos: pos as _,
-            end: end as _,
+            beg: pos as usize,
+            pos: pos as usize,
+            end: end as usize,
         }
     }
 
@@ -765,7 +765,7 @@  pub(crate) unsafe fn from_buffer(buf: *mut u8, len: usize) -> Self {
     ///
     /// N.B. It may point to invalid memory.
     pub(crate) fn pos(&self) -> *mut u8 {
-        self.pos as _
+        self.pos as *mut u8
     }
 
     /// Returns the number of bytes written to the formatter.
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 223fe5e8ed82..7d3a6e586a1d 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -198,7 +198,7 @@  pub fn enqueue<W, const ID: u64>(&self, w: W) -> W::EnqueueOutput
         unsafe {
             w.__enqueue(move |work_ptr| {
                 bindings::queue_work_on(
-                    bindings::wq_misc_consts_WORK_CPU_UNBOUND as _,
+                    bindings::wq_misc_consts_WORK_CPU_UNBOUND as i32,
                     queue_ptr,
                     work_ptr,
                 )