]> git.lizzy.rs Git - rust.git/blob - clippy_lints/src/casts/cast_possible_truncation.rs
Auto merge of #7856 - Manishearth:impl-safety, r=xFrednet
[rust.git] / clippy_lints / src / casts / cast_possible_truncation.rs
1 use clippy_utils::diagnostics::span_lint;
2 use clippy_utils::expr_or_init;
3 use clippy_utils::ty::is_isize_or_usize;
4 use rustc_hir::{Expr, ExprKind};
5 use rustc_lint::LateContext;
6 use rustc_middle::ty::{self, FloatTy, Ty};
7
8 use super::{utils, CAST_POSSIBLE_TRUNCATION};
9
10 pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
11     // do not lint if cast comes from a `signum` function
12     if let ExprKind::MethodCall(path, ..) = expr_or_init(cx, cast_expr).kind {
13         if path.ident.name.as_str() == "signum" {
14             return;
15         }
16     }
17
18     let msg = match (cast_from.is_integral(), cast_to.is_integral()) {
19         (true, true) => {
20             let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
21             let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
22
23             let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
24                 (true, true) | (false, false) => (to_nbits < from_nbits, ""),
25                 (true, false) => (
26                     to_nbits <= 32,
27                     if to_nbits == 32 {
28                         " on targets with 64-bit wide pointers"
29                     } else {
30                         ""
31                     },
32                 ),
33                 (false, true) => (from_nbits == 64, " on targets with 32-bit wide pointers"),
34             };
35
36             if !should_lint {
37                 return;
38             }
39
40             format!(
41                 "casting `{}` to `{}` may truncate the value{}",
42                 cast_from, cast_to, suffix,
43             )
44         },
45
46         (false, true) => {
47             format!("casting `{}` to `{}` may truncate the value", cast_from, cast_to)
48         },
49
50         (_, _) => {
51             if matches!(cast_from.kind(), &ty::Float(FloatTy::F64))
52                 && matches!(cast_to.kind(), &ty::Float(FloatTy::F32))
53             {
54                 "casting `f64` to `f32` may truncate the value".to_string()
55             } else {
56                 return;
57             }
58         },
59     };
60
61     span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg);
62 }