summaryrefslogtreecommitdiffstats
path: root/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs')
-rw-r--r--src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs44
1 files changed, 44 insertions, 0 deletions
diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
new file mode 100644
index 000000000..64ea326b7
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/casts/cast_abs_to_unsigned.rs
@@ -0,0 +1,44 @@
+use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::sugg::Sugg;
+use clippy_utils::{meets_msrv, msrvs};
+use rustc_errors::Applicability;
+use rustc_hir::{Expr, ExprKind};
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, Ty};
+use rustc_semver::RustcVersion;
+
+use super::CAST_ABS_TO_UNSIGNED;
+
+pub(super) fn check(
+ cx: &LateContext<'_>,
+ expr: &Expr<'_>,
+ cast_expr: &Expr<'_>,
+ cast_from: Ty<'_>,
+ cast_to: Ty<'_>,
+ msrv: Option<RustcVersion>,
+) {
+ if meets_msrv(msrv, msrvs::UNSIGNED_ABS)
+ && let ty::Int(from) = cast_from.kind()
+ && let ty::Uint(to) = cast_to.kind()
+ && let ExprKind::MethodCall(method_path, args, _) = cast_expr.kind
+ && method_path.ident.name.as_str() == "abs"
+ {
+ let span = if from.bit_width() == to.bit_width() {
+ expr.span
+ } else {
+ // if the result of `.unsigned_abs` would be a different type, keep the cast
+ // e.g. `i64 -> usize`, `i16 -> u8`
+ cast_expr.span
+ };
+
+ span_lint_and_sugg(
+ cx,
+ CAST_ABS_TO_UNSIGNED,
+ span,
+ &format!("casting the result of `{cast_from}::abs()` to {cast_to}"),
+ "replace with",
+ format!("{}.unsigned_abs()", Sugg::hir(cx, &args[0], "..")),
+ Applicability::MachineApplicable,
+ );
+ }
+}