Re: [PATCH v12 5/6] rust: enable `clippy::cast_lossless` lint
From: Tamir Duberstein <hidden>
Date: 2025-06-18 13:52:11
Also in:
dri-devel, linux-block, linux-devicetree, linux-kbuild, linux-kselftest, linux-mm, linux-pci, linux-pm, lkml, nouveau, rust-for-linux
On Sun, Jun 15, 2025 at 4:55 PM Tamir Duberstein [off-list ref] wrote:
Before Rust 1.29.0, Clippy introduced the `cast_lossless` lint [1]:quoted
Rust’s `as` keyword will perform many kinds of conversions, including silently lossy conversions. Conversion functions such as `i32::from` will only perform lossless conversions. Using the conversion functions prevents conversions from becoming silently lossy if the input types ever change, and makes it clear for people reading the code that the conversion is lossless.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#cast_lossless [1] Suggested-by: Benno Lossin <redacted> Link: https://lore.kernel.org/all/D8ORTXSUTKGL.1KOJAGBM8F8TN@proton.me/ (local) Reviewed-by: Benno Lossin <redacted> Reviewed-by: Boqun Feng <redacted> Signed-off-by: Tamir Duberstein <redacted>
@Danilo Krummrich could you please have a look for drm and nova?
quoted hunk ↗ jump to hunk
--- Makefile | 1 + drivers/gpu/drm/drm_panic_qr.rs | 4 ++-- drivers/gpu/nova-core/regs.rs | 2 +- drivers/gpu/nova-core/regs/macros.rs | 2 +- rust/bindings/lib.rs | 1 + rust/kernel/net/phy.rs | 4 ++-- rust/uapi/lib.rs | 1 + 7 files changed, 9 insertions(+), 6 deletions(-)diff --git a/Makefile b/Makefile index 0ba22c361de8..29cf39be14de 100644 --- a/Makefile +++ b/Makefile@@ -481,6 +481,7 @@ export rust_common_flags := --edition=2021 \ -Wclippy::all \ -Wclippy::as_ptr_cast_mut \ -Wclippy::as_underscore \ + -Wclippy::cast_lossless \ -Wclippy::ignored_unit_patterns \ -Wclippy::mut_mut \ -Wclippy::needless_bitwise_bool \diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs index dd55b1cb764d..6b59d19ab631 100644 --- a/drivers/gpu/drm/drm_panic_qr.rs +++ b/drivers/gpu/drm/drm_panic_qr.rs@@ -404,7 +404,7 @@ fn pop3(&mut self) -> Option<(u16, usize)> { let mut out = 0; let mut exp = 1; for i in 0..poplen { - out += self.decimals[self.len + i] as u16 * exp; + out += u16::from(self.decimals[self.len + i]) * exp; exp *= 10; } Some((out, NUM_CHARS_BITS[poplen]))@@ -425,7 +425,7 @@ fn next(&mut self) -> Option<Self::Item> { match self.segment { Segment::Binary(data) => { if self.offset < data.len() { - let byte = data[self.offset] as u16; + let byte = u16::from(data[self.offset]); self.offset += 1; Some((byte, 8)) } else {diff --git a/drivers/gpu/nova-core/regs.rs b/drivers/gpu/nova-core/regs.rs index 5a1273230306..c1cb6d4c49ee 100644 --- a/drivers/gpu/nova-core/regs.rs +++ b/drivers/gpu/nova-core/regs.rs@@ -32,7 +32,7 @@ pub(crate) fn architecture(self) -> Result<Architecture> { pub(crate) fn chipset(self) -> Result<Chipset> { self.architecture() .map(|arch| { - ((arch as u32) << Self::IMPLEMENTATION.len()) | self.implementation() as u32 + ((arch as u32) << Self::IMPLEMENTATION.len()) | u32::from(self.implementation()) }) .and_then(Chipset::try_from) }diff --git a/drivers/gpu/nova-core/regs/macros.rs b/drivers/gpu/nova-core/regs/macros.rs index 7ecc70efb3cd..6851af8b5885 100644 --- a/drivers/gpu/nova-core/regs/macros.rs +++ b/drivers/gpu/nova-core/regs/macros.rs@@ -264,7 +264,7 @@ pub(crate) fn $field(self) -> $res_type { pub(crate) fn [<set_ $field>](mut self, value: $to_type) -> Self { const MASK: u32 = $name::[<$field:upper _MASK>]; const SHIFT: u32 = $name::[<$field:upper _SHIFT>]; - let value = ((value as u32) << SHIFT) & MASK; + let value = (u32::from(value) << SHIFT) & MASK; self.0 = (self.0 & !MASK) | value; selfdiff --git a/rust/bindings/lib.rs b/rust/bindings/lib.rs index 81b6c7aa4916..7631c9f6708d 100644 --- a/rust/bindings/lib.rs +++ b/rust/bindings/lib.rs@@ -25,6 +25,7 @@ )] #[allow(dead_code)] +#[allow(clippy::cast_lossless)] #[allow(clippy::ptr_as_ptr)] #[allow(clippy::undocumented_unsafe_blocks)] #[cfg_attr(CONFIG_RUSTC_HAS_UNNECESSARY_TRANSMUTES, allow(unnecessary_transmutes))]diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs index 32ea43ece646..65ac4d59ad77 100644 --- a/rust/kernel/net/phy.rs +++ b/rust/kernel/net/phy.rs@@ -142,7 +142,7 @@ pub fn is_autoneg_enabled(&self) -> bool { // SAFETY: The struct invariant ensures that we may access // this field without additional synchronization. let bit_field = unsafe { &(*self.0.get())._bitfield_1 }; - bit_field.get(13, 1) == bindings::AUTONEG_ENABLE as u64 + bit_field.get(13, 1) == u64::from(bindings::AUTONEG_ENABLE) } /// Gets the current auto-negotiation state.@@ -427,7 +427,7 @@ impl<T: Driver> Adapter<T> { // where we hold `phy_device->lock`, so the accessors on // `Device` are okay to call. let dev = unsafe { Device::from_raw(phydev) }; - T::match_phy_device(dev) as i32 + T::match_phy_device(dev).into() } /// # Safetydiff --git a/rust/uapi/lib.rs b/rust/uapi/lib.rs index e79a1f49f055..08e68ebef606 100644 --- a/rust/uapi/lib.rs +++ b/rust/uapi/lib.rs@@ -14,6 +14,7 @@ #![cfg_attr(test, allow(unsafe_op_in_unsafe_fn))] #![allow( clippy::all, + clippy::cast_lossless, clippy::ptr_as_ptr, clippy::undocumented_unsafe_blocks, dead_code, --2.49.0