]>
Commit | Line | Data |
---|---|---|
f20569fa XL |
1 | use rustc_hir::Expr; |
2 | use rustc_lint::LateContext; | |
3 | use rustc_middle::ty::{self, FloatTy, Ty}; | |
4 | ||
5 | use crate::utils::{is_isize_or_usize, span_lint}; | |
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 let ty::Float(FloatTy::F32) = cast_to.kind() { | |
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 | } |