]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/casts/cast_precision_loss.rs
Rollup merge of #102854 - semarie:openbsd-immutablestack, r=m-ou-se
[rust.git] / src / tools / clippy / clippy_lints / src / casts / cast_precision_loss.rs
1 use clippy_utils::diagnostics::span_lint;
2 use clippy_utils::ty::is_isize_or_usize;
3 use rustc_hir::Expr;
4 use rustc_lint::LateContext;
5 use rustc_middle::ty::{self, FloatTy, Ty};
6
7 use super::{utils, CAST_PRECISION_LOSS};
8
9 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
10     if !cast_from.is_integral() || cast_to.is_integral() {
11         return;
12     }
13
14     let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
15     let to_nbits = if cast_to.kind() == &ty::Float(FloatTy::F32) {
16         32
17     } else {
18         64
19     };
20
21     if !(is_isize_or_usize(cast_from) || from_nbits >= to_nbits) {
22         return;
23     }
24
25     let cast_to_f64 = to_nbits == 64;
26     let mantissa_nbits = if cast_to_f64 { 52 } else { 23 };
27     let arch_dependent = is_isize_or_usize(cast_from) && cast_to_f64;
28     let arch_dependent_str = "on targets with 64-bit wide pointers ";
29     let from_nbits_str = if arch_dependent {
30         "64".to_owned()
31     } else if is_isize_or_usize(cast_from) {
32         "32 or 64".to_owned()
33     } else {
34         utils::int_ty_to_nbits(cast_from, cx.tcx).to_string()
35     };
36
37     span_lint(
38         cx,
39         CAST_PRECISION_LOSS,
40         expr.span,
41         &format!(
42             "casting `{0}` to `{1}` causes a loss of precision {2}(`{0}` is {3} bits wide, \
43              but `{1}`'s mantissa is only {4} bits wide)",
44             cast_from,
45             if cast_to_f64 { "f64" } else { "f32" },
46             if arch_dependent { arch_dependent_str } else { "" },
47             from_nbits_str,
48             mantissa_nbits
49         ),
50     );
51 }