diff options
| author | Samuel Tardieu <sam@rfc1149.net> | 2025-07-03 20:22:18 +0200 |
|---|---|---|
| committer | Samuel Tardieu <sam@rfc1149.net> | 2025-07-03 22:14:00 +0200 |
| commit | a8ab02c4641de4e3ec634b3479fddb60e4ad7763 (patch) | |
| tree | a6ec346ca3f015191e64a460af4c3c2f8e921f0c /clippy_lints/src | |
| parent | 83148cb28343bf15ed469f946915c73deeaa9a28 (diff) | |
Fix several issues with `manual_is_multiple_of`
- `&a % &b == 0` compiles, but requires dereferencing `b` when replacing with `a.is_multiple_of(b)`. - In `a % b == 0`, if type of `a` is not certain, `a.is_multiple_of(b)` might not be typable. - In `a % b == 0`, `a` and `b` must be unsigned integers, not any arbitrary types implementing `Rem` and outputing an integer.
Diffstat (limited to 'clippy_lints/src')
| -rw-r--r-- | clippy_lints/src/operators/manual_is_multiple_of.rs | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/clippy_lints/src/operators/manual_is_multiple_of.rs b/clippy_lints/src/operators/manual_is_multiple_of.rs index 821178a4315..55bb78cfce5 100644 --- a/clippy_lints/src/operators/manual_is_multiple_of.rs +++ b/clippy_lints/src/operators/manual_is_multiple_of.rs @@ -2,11 +2,12 @@ use clippy_utils::consts::is_zero_integer_const; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; +use clippy_utils::ty::expr_type_is_certain; use rustc_ast::BinOpKind; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; -use rustc_middle::ty; +use rustc_middle::ty::{self, Ty}; use super::MANUAL_IS_MULTIPLE_OF; @@ -22,9 +23,21 @@ pub(super) fn check<'tcx>( && let Some(operand) = uint_compare_to_zero(cx, op, lhs, rhs) && let ExprKind::Binary(operand_op, operand_left, operand_right) = operand.kind && operand_op.node == BinOpKind::Rem + && matches!( + cx.typeck_results().expr_ty_adjusted(operand_left).peel_refs().kind(), + ty::Uint(_) + ) + && matches!( + cx.typeck_results().expr_ty_adjusted(operand_right).peel_refs().kind(), + ty::Uint(_) + ) + && expr_type_is_certain(cx, operand_left) { let mut app = Applicability::MachineApplicable; - let divisor = Sugg::hir_with_applicability(cx, operand_right, "_", &mut app); + let divisor = deref_sugg( + Sugg::hir_with_applicability(cx, operand_right, "_", &mut app), + cx.typeck_results().expr_ty_adjusted(operand_right), + ); span_lint_and_sugg( cx, MANUAL_IS_MULTIPLE_OF, @@ -64,3 +77,11 @@ fn uint_compare_to_zero<'tcx>( matches!(cx.typeck_results().expr_ty_adjusted(operand).kind(), ty::Uint(_)).then_some(operand) } + +fn deref_sugg<'a>(sugg: Sugg<'a>, ty: Ty<'_>) -> Sugg<'a> { + if let ty::Ref(_, target_ty, _) = ty.kind() { + deref_sugg(sugg.deref(), *target_ty) + } else { + sugg + } +} |
