diff --git a/clippy_lints/src/manual_rem_euclid.rs b/clippy_lints/src/manual_rem_euclid.rs index 7ef8f78a5f6..cba03389a9b 100644 --- a/clippy_lints/src/manual_rem_euclid.rs +++ b/clippy_lints/src/manual_rem_euclid.rs @@ -4,7 +4,7 @@ use clippy_utils::source::snippet_with_applicability; use clippy_utils::{meets_msrv, msrvs, path_to_local}; use if_chain::if_chain; use rustc_errors::Applicability; -use rustc_hir::{BinOpKind, Expr, ExprKind}; +use rustc_hir::{BinOpKind, Expr, ExprKind, Node, TyKind}; use rustc_lint::{LateContext, LateLintPass}; use rustc_semver::RustcVersion; use rustc_session::{declare_tool_lint, impl_lint_pass}; @@ -19,12 +19,12 @@ declare_clippy_lint! { /// /// ### Example /// ```rust - /// let x = 24; + /// let x: i32 = 24; /// let rem = ((x % 4) + 4) % 4; /// ``` /// Use instead: /// ```rust - /// let x = 24; + /// let x: i32 = 24; /// let rem = x.rem_euclid(4); /// ``` #[clippy::version = "1.63.0"] @@ -63,7 +63,14 @@ impl<'tcx> LateLintPass<'tcx> for ManualRemEuclid { if op3.node == BinOpKind::Rem; if let Some((const3, expr3)) = check_for_positive_int_constant(cx, expr2); if const1 == const2 && const2 == const3; - if path_to_local(expr3).is_some(); + // Only apply if we see an explicit type annotation on the local. + if let Some(hir_id) = path_to_local(expr3); + let hir = cx.tcx.hir(); + if let Some(Node::Binding(_)) = hir.find(hir_id); + let parent = hir.get_parent_node(hir_id); + if let Some(Node::Local(local)) = hir.find(parent); + if let Some(ty) = local.ty; + if !matches!(ty.kind, TyKind::Infer); then { let mut app = Applicability::MachineApplicable; let rem_of = snippet_with_applicability(cx, expr3.span, "_", &mut app); diff --git a/tests/ui/manual_rem_euclid.fixed b/tests/ui/manual_rem_euclid.fixed index f176fc9ad12..10a10e812f4 100644 --- a/tests/ui/manual_rem_euclid.fixed +++ b/tests/ui/manual_rem_euclid.fixed @@ -14,4 +14,11 @@ fn main() { let _: i32 = (3 + value % 4) % 4; let _: i32 = (-4 + value % -4) % -4; let _: i32 = ((5 % 4) + 4) % 4; + + // Make sure the lint does not trigger if it would cause an error, like with an ambiguous + // integer type + let not_annotated = 24; + let _ = ((not_annotated % 4) + 4) % 4; + let inferred: _ = 24; + let _ = ((inferred % 4) + 4) % 4; } diff --git a/tests/ui/manual_rem_euclid.rs b/tests/ui/manual_rem_euclid.rs index b243065de87..bf16f977ea9 100644 --- a/tests/ui/manual_rem_euclid.rs +++ b/tests/ui/manual_rem_euclid.rs @@ -14,4 +14,11 @@ fn main() { let _: i32 = (3 + value % 4) % 4; let _: i32 = (-4 + value % -4) % -4; let _: i32 = ((5 % 4) + 4) % 4; + + // Make sure the lint does not trigger if it would cause an error, like with an ambiguous + // integer type + let not_annotated = 24; + let _ = ((not_annotated % 4) + 4) % 4; + let inferred: _ = 24; + let _ = ((inferred % 4) + 4) % 4; }