diff --git a/clippy_lints/src/operators/integer_division_remainder_used.rs b/clippy_lints/src/operators/integer_division_remainder_used.rs index fa080cba926e..26826ce4c1f6 100644 --- a/clippy_lints/src/operators/integer_division_remainder_used.rs +++ b/clippy_lints/src/operators/integer_division_remainder_used.rs @@ -1,11 +1,11 @@ +use super::INTEGER_DIVISION_REMAINDER_USED; use clippy_utils::diagnostics::span_lint; +use clippy_utils::sym; use rustc_ast::BinOpKind; use rustc_hir::Expr; use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty; -use rustc_span::Span; - -use super::INTEGER_DIVISION_REMAINDER_USED; +use rustc_span::{Span, Symbol}; pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &Expr<'_>, span: Span) { if let BinOpKind::Div | BinOpKind::Rem = op @@ -23,3 +23,41 @@ pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &E ); } } +// check method call is present in specific list if yes also lint it +pub(super) fn check_method_call(cx: &LateContext<'_>, method_name: Symbol, receiver: &Expr<'_>, span: Span) { + if matches!( + method_name, + sym::checked_div + | sym::checked_div_euclid + | sym::checked_div_exact + | sym::checked_rem + | sym::checked_rem_euclid + | sym::div_ceil + | sym::div_euclid + | sym::div_exact + | sym::overflowing_div + | sym::overflowing_div_euclid + | sym::overflowing_rem + | sym::overflowing_rem_euclid + | sym::rem_euclid + | sym::strict_div + | sym::strict_div_euclid + | sym::saturating_div + | sym::strict_rem + | sym::strict_rem_euclid + | sym::wrapping_div + | sym::wrapping_div_euclid + | sym::wrapping_rem + | sym::wrapping_rem_euclid, + ) { + let instance_ty = cx.typeck_results().expr_ty(receiver); + if matches!(instance_ty.peel_refs().kind(), ty::Int(_) | ty::Uint(_)) { + span_lint( + cx, + INTEGER_DIVISION_REMAINDER_USED, + span.source_callsite(), + format!("use of `{method_name}` has been disallowed in this context"), + ); + } + } +} diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 8a7bbdf08e76..e8a66742979e 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -1087,6 +1087,9 @@ impl<'tcx> LateLintPass<'tcx> for Operators { ); manual_div_ceil::check(cx, e, op.node, lhs, rhs, self.msrv); }, + ExprKind::MethodCall(path, receiver, _args, span) => { + integer_division_remainder_used::check_method_call(cx, path.ident.name, receiver, span); + }, ExprKind::AssignOp(op, lhs, rhs) => { let bin_op = op.node.into(); if !e.span.from_expansion() { diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 8f03003eeb0a..72b60bdb1407 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -170,9 +170,13 @@ generate! { check_attributes, checked_abs, checked_add, + checked_div, + checked_div_euclid, + checked_div_exact, checked_isqrt, checked_mul, checked_pow, + checked_rem, checked_rem_euclid, checked_sub, child_id, @@ -213,6 +217,9 @@ generate! { deref_mut_method, diagnostics, disallowed_types, + div_ceil, + div_euclid, + div_exact, drain, dump, duration_constructors, @@ -461,6 +468,10 @@ generate! { os_str_to_os_string, os_string_as_os_str, outer_expn, + overflowing_div, + overflowing_div_euclid, + overflowing_rem, + overflowing_rem_euclid, panic_any, parse, partition, @@ -582,6 +593,10 @@ generate! { str_trim, str_trim_end, str_trim_start, + strict_div, + strict_div_euclid, + strict_rem, + strict_rem_euclid, string_as_mut_str, string_as_str, string_from_utf8, @@ -653,6 +668,7 @@ generate! { warnings, wildcard_imports, with_capacity, + wrapping_div_euclid, wrapping_neg, wrapping_offset, write, diff --git a/tests/ui/integer_division_remainder_used.rs b/tests/ui/integer_division_remainder_used.rs index 2d5e82dbeadb..796b5d5e32a9 100644 --- a/tests/ui/integer_division_remainder_used.rs +++ b/tests/ui/integer_division_remainder_used.rs @@ -20,6 +20,56 @@ impl std::ops::Rem for CustomOps { } } +fn issue17603() { + let x: u16 = 7; + + let _ = x.checked_div(3); + //~^ integer_division_remainder_used + let _ = x.checked_div_euclid(3); + //~^ integer_division_remainder_used + let _ = x.checked_rem(3); + //~^ integer_division_remainder_used + let _ = x.checked_rem_euclid(3); + //~^ integer_division_remainder_used + let _ = x.div_ceil(3); + //~^ integer_division_remainder_used + let _ = x.div_euclid(3); + //~^ integer_division_remainder_used + let _ = x.overflowing_div(3); + //~^ integer_division_remainder_used + let _ = x.overflowing_div_euclid(3); + //~^ integer_division_remainder_used + let _ = x.overflowing_rem(3); + //~^ integer_division_remainder_used + let _ = x.overflowing_rem_euclid(3); + //~^ integer_division_remainder_used + let _ = x.rem_euclid(3); + //~^ integer_division_remainder_used + let _ = x.strict_div(3); + //~^ integer_division_remainder_used + let _ = x.strict_div_euclid(3); + //~^ integer_division_remainder_used + let _ = x.saturating_div(3); + //~^ integer_division_remainder_used + let _ = x.strict_rem(3); + //~^ integer_division_remainder_used + let _ = x.strict_rem_euclid(3); + //~^ integer_division_remainder_used + let _ = x.wrapping_div(3); + //~^ integer_division_remainder_used + let _ = x.wrapping_div_euclid(3); + //~^ integer_division_remainder_used + let _ = x.wrapping_rem(3); + //~^ integer_division_remainder_used + let _ = x.wrapping_rem_euclid(3); + //~^ integer_division_remainder_used + + // methods that also exist on floats should not trigger there + let f: f64 = 7.0; + let _ = f.div_euclid(3.0); + let _ = f.rem_euclid(3.0); +} + fn main() { // should trigger let a = 10; diff --git a/tests/ui/integer_division_remainder_used.stderr b/tests/ui/integer_division_remainder_used.stderr index 632df3e960c1..42129a4cb281 100644 --- a/tests/ui/integer_division_remainder_used.stderr +++ b/tests/ui/integer_division_remainder_used.stderr @@ -13,62 +13,182 @@ error: use of `%` has been disallowed in this context LL | Self(self.0 % rhs.0) | ^^^^^^^^^^^^^^ +error: use of `checked_div` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:26:15 + | +LL | let _ = x.checked_div(3); + | ^^^^^^^^^^^^^^ + +error: use of `checked_div_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:28:15 + | +LL | let _ = x.checked_div_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of `checked_rem` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:30:15 + | +LL | let _ = x.checked_rem(3); + | ^^^^^^^^^^^^^^ + +error: use of `checked_rem_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:32:15 + | +LL | let _ = x.checked_rem_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^^ + +error: use of `div_ceil` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:34:15 + | +LL | let _ = x.div_ceil(3); + | ^^^^^^^^^^^ + +error: use of `div_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:36:15 + | +LL | let _ = x.div_euclid(3); + | ^^^^^^^^^^^^^ + +error: use of `overflowing_div` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:38:15 + | +LL | let _ = x.overflowing_div(3); + | ^^^^^^^^^^^^^^^^^^ + +error: use of `overflowing_div_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:40:15 + | +LL | let _ = x.overflowing_div_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `overflowing_rem` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:42:15 + | +LL | let _ = x.overflowing_rem(3); + | ^^^^^^^^^^^^^^^^^^ + +error: use of `overflowing_rem_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:44:15 + | +LL | let _ = x.overflowing_rem_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `rem_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:46:15 + | +LL | let _ = x.rem_euclid(3); + | ^^^^^^^^^^^^^ + +error: use of `strict_div` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:48:15 + | +LL | let _ = x.strict_div(3); + | ^^^^^^^^^^^^^ + +error: use of `strict_div_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:50:15 + | +LL | let _ = x.strict_div_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of `saturating_div` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:52:15 + | +LL | let _ = x.saturating_div(3); + | ^^^^^^^^^^^^^^^^^ + +error: use of `strict_rem` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:54:15 + | +LL | let _ = x.strict_rem(3); + | ^^^^^^^^^^^^^ + +error: use of `strict_rem_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:56:15 + | +LL | let _ = x.strict_rem_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^ + +error: use of `wrapping_div` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:58:15 + | +LL | let _ = x.wrapping_div(3); + | ^^^^^^^^^^^^^^^ + +error: use of `wrapping_div_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:60:15 + | +LL | let _ = x.wrapping_div_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: use of `wrapping_rem` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:62:15 + | +LL | let _ = x.wrapping_rem(3); + | ^^^^^^^^^^^^^^^ + +error: use of `wrapping_rem_euclid` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:64:15 + | +LL | let _ = x.wrapping_rem_euclid(3); + | ^^^^^^^^^^^^^^^^^^^^^^ + error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:27:13 + --> tests/ui/integer_division_remainder_used.rs:77:13 | LL | let c = a / b; | ^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:29:13 + --> tests/ui/integer_division_remainder_used.rs:79:13 | LL | let d = a % b; | ^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:31:13 + --> tests/ui/integer_division_remainder_used.rs:81:13 | LL | let e = &a / b; | ^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:33:13 + --> tests/ui/integer_division_remainder_used.rs:83:13 | LL | let f = a % &b; | ^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:35:13 + --> tests/ui/integer_division_remainder_used.rs:85:13 | LL | let g = &a / &b; | ^^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:37:13 + --> tests/ui/integer_division_remainder_used.rs:87:13 | LL | let h = &10 % b; | ^^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:39:13 + --> tests/ui/integer_division_remainder_used.rs:89:13 | LL | let i = a / &4; | ^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:44:5 + --> tests/ui/integer_division_remainder_used.rs:94:5 | LL | j /= 2; | ^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:46:5 + --> tests/ui/integer_division_remainder_used.rs:96:5 | LL | j %= 3; | ^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:60:13 + --> tests/ui/integer_division_remainder_used.rs:110:13 | LL | $a % $b | ^^^^^^^ @@ -78,5 +198,5 @@ LL | let issue17048 = mac!(a, b); | = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 12 previous errors +error: aborting due to 32 previous errors