From dd38e1881864852f81bd6bee212c6b21b2207a8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9E=97=E6=99=A8=20=28Leo=20Cheng=29?= Date: Thu, 9 Jul 2026 22:32:42 +0800 Subject: [PATCH] fix(non_zero_suggestions): don't lint signed div/rem as NonZero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Div> and Rem> are only implemented for unsigned integer types in std. Suggesting NonZeroI* as the RHS of / or % produces code that fails to compile because those trait impls do not exist for signed types. Guard the div/rem path to only fire when the RHS type is ty::Uint. Signed-off-by: 林晨 (Leo Cheng) --- clippy_lints/src/non_zero_suggestions.rs | 8 +++++++- tests/ui/non_zero_suggestions.fixed | 8 +++++++- tests/ui/non_zero_suggestions.rs | 8 +++++++- tests/ui/non_zero_suggestions.stderr | 4 ++-- 4 files changed, 23 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/non_zero_suggestions.rs b/clippy_lints/src/non_zero_suggestions.rs index 1b8ab1bdedf8..b8d1147baeb7 100644 --- a/clippy_lints/src/non_zero_suggestions.rs +++ b/clippy_lints/src/non_zero_suggestions.rs @@ -52,7 +52,13 @@ impl<'tcx> LateLintPass<'tcx> for NonZeroSuggestions { if let ExprKind::Binary(op, _, rhs) = expr.kind && matches!(op.node, BinOpKind::Div | BinOpKind::Rem) { - check_non_zero_conversion(cx, rhs, Applicability::MachineApplicable); + // `Div>` and `Rem>` are only implemented for unsigned + // integer types; signed integer types do not have these impls, so suggesting + // `NonZeroI*::from(x)` as the divisor produces code that won't compile. + let rhs_ty = cx.typeck_results().expr_ty(rhs); + if matches!(rhs_ty.kind(), ty::Uint(_)) { + check_non_zero_conversion(cx, rhs, Applicability::MachineApplicable); + } } else { // Check if the parent expression is a binary operation let parent_is_binary = cx.tcx.hir_parent_iter(expr.hir_id).any(|(_, node)| { diff --git a/tests/ui/non_zero_suggestions.fixed b/tests/ui/non_zero_suggestions.fixed index 4573896ecd67..b714a6cf6ede 100644 --- a/tests/ui/non_zero_suggestions.fixed +++ b/tests/ui/non_zero_suggestions.fixed @@ -1,5 +1,5 @@ #![warn(clippy::non_zero_suggestions)] -use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; +use std::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; fn main() { /// Positive test cases (lint should trigger) @@ -45,6 +45,12 @@ fn main() { let k: u64 = 300; let l = NonZeroU32::new(15).unwrap(); let r9 = k / NonZeroU64::from(l); + + // Signed integers in div/rem: must NOT trigger because i64 / NonZeroI64 is not in std + let s: i64 = 10; + let t = NonZeroI32::new(3).unwrap(); + let r10 = s / i64::from(t.get()); + let r11 = s % i64::from(t.get()); } // Additional function to test the lint in a different context diff --git a/tests/ui/non_zero_suggestions.rs b/tests/ui/non_zero_suggestions.rs index 3e7081e0c1c0..0e4cd3cc3652 100644 --- a/tests/ui/non_zero_suggestions.rs +++ b/tests/ui/non_zero_suggestions.rs @@ -1,5 +1,5 @@ #![warn(clippy::non_zero_suggestions)] -use std::num::{NonZeroI8, NonZeroI16, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; +use std::num::{NonZeroI8, NonZeroI16, NonZeroI32, NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroUsize}; fn main() { /// Positive test cases (lint should trigger) @@ -45,6 +45,12 @@ fn main() { let k: u64 = 300; let l = NonZeroU32::new(15).unwrap(); let r9 = k / NonZeroU64::from(l); + + // Signed integers in div/rem: must NOT trigger because i64 / NonZeroI64 is not in std + let s: i64 = 10; + let t = NonZeroI32::new(3).unwrap(); + let r10 = s / i64::from(t.get()); + let r11 = s % i64::from(t.get()); } // Additional function to test the lint in a different context diff --git a/tests/ui/non_zero_suggestions.stderr b/tests/ui/non_zero_suggestions.stderr index 7a57f7983be7..4b5a8a3fc6ff 100644 --- a/tests/ui/non_zero_suggestions.stderr +++ b/tests/ui/non_zero_suggestions.stderr @@ -26,13 +26,13 @@ LL | let x = u64::from(NonZeroU32::new(5).unwrap().get()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(NonZeroU32::new(5).unwrap())` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:52:9 + --> tests/ui/non_zero_suggestions.rs:58:9 | LL | x / u64::from(y.get()) | ^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(y)` error: consider using `NonZeroU64::from()` for more efficient and type-safe conversion - --> tests/ui/non_zero_suggestions.rs:62:22 + --> tests/ui/non_zero_suggestions.rs:68:22 | LL | self.value / u64::from(divisor.get()) | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace with: `NonZeroU64::from(divisor)`