about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYoshitomo Nakanishi <yurayura.rounin.3@gmail.com>2021-03-09 11:22:17 +0900
committerYoshitomo Nakanishi <yurayura.rounin.3@gmail.com>2021-03-09 11:22:17 +0900
commitc2cbcd32299270487388442e3dc684619279ae6b (patch)
treedf70311ecbd92cc0e9d5f395da80a2774f5956e8
parent360f0654047ef45212440e0cc9dcfe77c970b1eb (diff)
downloadrust-c2cbcd32299270487388442e3dc684619279ae6b.tar.gz
rust-c2cbcd32299270487388442e3dc684619279ae6b.zip
Move cast_precision_loss to its own module
-rw-r--r--clippy_lints/src/casts/cast_precision_loss.rs51
-rw-r--r--clippy_lints/src/casts/mod.rs62
-rw-r--r--clippy_lints/src/casts/utils.rs25
3 files changed, 83 insertions, 55 deletions
diff --git a/clippy_lints/src/casts/cast_precision_loss.rs b/clippy_lints/src/casts/cast_precision_loss.rs
new file mode 100644
index 00000000000..a1c3900ce1f
--- /dev/null
+++ b/clippy_lints/src/casts/cast_precision_loss.rs
@@ -0,0 +1,51 @@
+use rustc_hir::Expr;
+use rustc_lint::LateContext;
+use rustc_middle::ty::{self, FloatTy, Ty};
+
+use crate::utils::{is_isize_or_usize, span_lint};
+
+use super::{utils, CAST_PRECISION_LOSS};
+
+pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
+    if !cast_from.is_integral() || cast_to.is_integral() {
+        return;
+    }
+
+    let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
+    let to_nbits = if let ty::Float(FloatTy::F32) = cast_to.kind() {
+        32
+    } else {
+        64
+    };
+
+    if !(is_isize_or_usize(cast_from) || from_nbits >= to_nbits) {
+        return;
+    }
+
+    let cast_to_f64 = to_nbits == 64;
+    let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
+    let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
+    let arch_dependent_str = "on targets with 64-bit wide pointers ";
+    let from_nbits_str = if arch_dependent {
+        "64".to_owned()
+    } else if is_isize_or_usize(cast_from) {
+        "32 or 64".to_owned()
+    } else {
+        utils::int_ty_to_nbits(cast_from, cx.tcx).to_string()
+    };
+
+    span_lint(
+        cx,
+        CAST_PRECISION_LOSS,
+        expr.span,
+        &format!(
+            "casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
+             but `{1}`'s mantissa is only {4} bits wide)",
+            cast_from,
+            if cast_to_f64 { "f64" } else { "f32" },
+            if arch_dependent { arch_dependent_str } else { "" },
+            from_nbits_str,
+            mantissa_nbits
+        ),
+    );
+}
diff --git a/clippy_lints/src/casts/mod.rs b/clippy_lints/src/casts/mod.rs
index 95e563fc3ba..7eb35aa8290 100644
--- a/clippy_lints/src/casts/mod.rs
+++ b/clippy_lints/src/casts/mod.rs
@@ -1,3 +1,6 @@
+mod cast_precision_loss;
+mod utils;
+
 use std::borrow::Cow;
 
 use if_chain::if_chain;
@@ -6,7 +9,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Expr, ExprKind, GenericArg, Lit, MutTy, Mutability, TyKind, UnOp};
 use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
-use rustc_middle::ty::{self, FloatTy, InferTy, IntTy, Ty, TyCtxt, TypeAndMut, UintTy};
+use rustc_middle::ty::{self, FloatTy, InferTy, Ty, TypeAndMut, UintTy};
 use rustc_semver::RustcVersion;
 use rustc_session::{declare_lint_pass, declare_tool_lint, impl_lint_pass};
 use rustc_span::symbol::sym;
@@ -20,6 +23,8 @@ use crate::utils::{
     span_lint_and_then,
 };
 
+use utils::int_ty_to_nbits;
+
 declare_clippy_lint! {
     /// **What it does:** Checks for casts from any numerical to a float type where
     /// the receiving type cannot store all values from the original type without
@@ -249,57 +254,6 @@ declare_clippy_lint! {
     "casting a function pointer to a numeric type not wide enough to store the address"
 }
 
-/// Returns the size in bits of an integral type.
-/// Will return 0 if the type is not an int or uint variant
-fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 {
-    match typ.kind() {
-        ty::Int(i) => match i {
-            IntTy::Isize => tcx.data_layout.pointer_size.bits(),
-            IntTy::I8 => 8,
-            IntTy::I16 => 16,
-            IntTy::I32 => 32,
-            IntTy::I64 => 64,
-            IntTy::I128 => 128,
-        },
-        ty::Uint(i) => match i {
-            UintTy::Usize => tcx.data_layout.pointer_size.bits(),
-            UintTy::U8 => 8,
-            UintTy::U16 => 16,
-            UintTy::U32 => 32,
-            UintTy::U64 => 64,
-            UintTy::U128 => 128,
-        },
-        _ => 0,
-    }
-}
-
-fn span_precision_loss_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to_f64: bool) {
-    let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
-    let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
-    let arch_dependent_str = "on targets with 64-bit wide pointers ";
-    let from_nbits_str = if arch_dependent {
-        "64".to_owned()
-    } else if is_isize_or_usize(cast_from) {
-        "32 or 64".to_owned()
-    } else {
-        int_ty_to_nbits(cast_from, cx.tcx).to_string()
-    };
-    span_lint(
-        cx,
-        CAST_PRECISION_LOSS,
-        expr.span,
-        &format!(
-            "casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
-             but `{1}`'s mantissa is only {4} bits wide)",
-            cast_from,
-            if cast_to_f64 { "f64" } else { "f32" },
-            if arch_dependent { arch_dependent_str } else { "" },
-            from_nbits_str,
-            mantissa_nbits
-        ),
-    );
-}
-
 fn should_strip_parens(op: &Expr<'_>, snip: &str) -> bool {
     if let ExprKind::Binary(_, _, _) = op.kind {
         if snip.starts_with('(') && snip.ends_with(')') {
@@ -629,6 +583,7 @@ fn lint_numeric_casts<'tcx>(
     cast_from: Ty<'tcx>,
     cast_to: Ty<'tcx>,
 ) {
+    cast_precision_loss::check(cx, expr, cast_from, cast_to);
     match (cast_from.is_integral(), cast_to.is_integral()) {
         (true, false) => {
             let from_nbits = int_ty_to_nbits(cast_from, cx.tcx);
@@ -637,9 +592,6 @@ fn lint_numeric_casts<'tcx>(
             } else {
                 64
             };
-            if is_isize_or_usize(cast_from) || from_nbits >= to_nbits {
-                span_precision_loss_lint(cx, expr, cast_from, to_nbits == 64);
-            }
             if from_nbits < to_nbits {
                 span_lossless_lint(cx, expr, cast_expr, cast_from, cast_to);
             }
diff --git a/clippy_lints/src/casts/utils.rs b/clippy_lints/src/casts/utils.rs
new file mode 100644
index 00000000000..00fd0b3473b
--- /dev/null
+++ b/clippy_lints/src/casts/utils.rs
@@ -0,0 +1,25 @@
+use rustc_middle::ty::{self, IntTy, Ty, TyCtxt, UintTy};
+
+/// Returns the size in bits of an integral type.
+/// Will return 0 if the type is not an int or uint variant
+pub(super) fn int_ty_to_nbits(typ: Ty<'_>, tcx: TyCtxt<'_>) -> u64 {
+    match typ.kind() {
+        ty::Int(i) => match i {
+            IntTy::Isize => tcx.data_layout.pointer_size.bits(),
+            IntTy::I8 => 8,
+            IntTy::I16 => 16,
+            IntTy::I32 => 32,
+            IntTy::I64 => 64,
+            IntTy::I128 => 128,
+        },
+        ty::Uint(i) => match i {
+            UintTy::Usize => tcx.data_layout.pointer_size.bits(),
+            UintTy::U8 => 8,
+            UintTy::U16 => 16,
+            UintTy::U32 => 32,
+            UintTy::U64 => 64,
+            UintTy::U128 => 128,
+        },
+        _ => 0,
+    }
+}