2021-03-13 23:01:03 +00:00
|
|
|
use clippy_utils::ty::is_isize_or_usize;
|
2021-03-09 03:10:59 +00:00
|
|
|
use rustc_hir::Expr;
|
|
|
|
use rustc_lint::LateContext;
|
|
|
|
use rustc_middle::ty::{self, FloatTy, Ty};
|
|
|
|
|
2021-03-16 00:55:45 +00:00
|
|
|
use clippy_utils::diagnostics::span_lint;
|
2021-03-09 03:10:59 +00:00
|
|
|
|
|
|
|
use super::{utils, CAST_POSSIBLE_TRUNCATION};
|
|
|
|
|
|
|
|
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to: Ty<'_>) {
|
|
|
|
let msg = match (cast_from.is_integral(), cast_to.is_integral()) {
|
|
|
|
(true, true) => {
|
|
|
|
let from_nbits = utils::int_ty_to_nbits(cast_from, cx.tcx);
|
|
|
|
let to_nbits = utils::int_ty_to_nbits(cast_to, cx.tcx);
|
|
|
|
|
|
|
|
let (should_lint, suffix) = match (is_isize_or_usize(cast_from), is_isize_or_usize(cast_to)) {
|
|
|
|
(true, true) | (false, false) => (to_nbits < from_nbits, ""),
|
|
|
|
(true, false) => (
|
|
|
|
to_nbits <= 32,
|
|
|
|
if to_nbits == 32 {
|
|
|
|
" on targets with 64-bit wide pointers"
|
|
|
|
} else {
|
|
|
|
""
|
|
|
|
},
|
|
|
|
),
|
|
|
|
(false, true) => (from_nbits == 64, " on targets with 32-bit wide pointers"),
|
|
|
|
};
|
|
|
|
|
|
|
|
if !should_lint {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
format!(
|
|
|
|
"casting `{}` to `{}` may truncate the value{}",
|
|
|
|
cast_from, cast_to, suffix,
|
|
|
|
)
|
|
|
|
},
|
|
|
|
|
|
|
|
(false, true) => {
|
|
|
|
format!("casting `{}` to `{}` may truncate the value", cast_from, cast_to)
|
|
|
|
},
|
|
|
|
|
|
|
|
(_, _) => {
|
|
|
|
if matches!(cast_from.kind(), &ty::Float(FloatTy::F64))
|
|
|
|
&& matches!(cast_to.kind(), &ty::Float(FloatTy::F32))
|
|
|
|
{
|
|
|
|
"casting `f64` to `f32` may truncate the value".to_string()
|
|
|
|
} else {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
},
|
|
|
|
};
|
|
|
|
|
|
|
|
span_lint(cx, CAST_POSSIBLE_TRUNCATION, expr.span, &msg);
|
|
|
|
}
|