Lint for bool to integer casts in cast_lossless

This commit is contained in:
5225225 2021-11-08 20:44:50 +00:00
parent c94d62b153
commit 33822012ec
6 changed files with 177 additions and 7 deletions

View File

@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
if let Some(span) = is_direct_expn_of(expr.span, mac) {
if let Some(args) = higher::extract_assert_macro_args(expr) {
if let [a, b, ..] = args[..] {
let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize;
let nb_bool_args = usize::from(is_bool_lit(a)) + usize::from(is_bool_lit(b));
if nb_bool_args != 1 {
// If there are two boolean arguments, we definitely don't understand

View File

@ -72,7 +72,7 @@ fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to
};
from_nbits < to_nbits
},
(false, true) if matches!(cast_from.kind(), ty::Bool) => true,
(_, _) => {
matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64))
},

View File

@ -426,12 +426,16 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
cast_precision_loss::check(cx, expr, cast_from, cast_to);
if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
if cast_from.is_numeric() {
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
cast_precision_loss::check(cx, expr, cast_from, cast_to);
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
}
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to);
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
}
}

View File

@ -0,0 +1,42 @@
// run-rustfix
#![allow(dead_code)]
#![warn(clippy::cast_lossless)]
fn main() {
// Test clippy::cast_lossless with casts to integer types
let _ = u8::from(true);
let _ = u16::from(true);
let _ = u32::from(true);
let _ = u64::from(true);
let _ = u128::from(true);
let _ = usize::from(true);
let _ = i8::from(true);
let _ = i16::from(true);
let _ = i32::from(true);
let _ = i64::from(true);
let _ = i128::from(true);
let _ = isize::from(true);
// Test with an expression wrapped in parens
let _ = u16::from(true | false);
}
// The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,
// so we skip the lint if the expression is in a const fn.
// See #3656
const fn abc(input: bool) -> u32 {
input as u32
}
// Same as the above issue. We can't suggest `::from` in const fns in impls
mod cast_lossless_in_impl {
struct A;
impl A {
pub const fn convert(x: bool) -> u64 {
x as u64
}
}
}

View File

@ -0,0 +1,42 @@
// run-rustfix
#![allow(dead_code)]
#![warn(clippy::cast_lossless)]
fn main() {
// Test clippy::cast_lossless with casts to integer types
let _ = true as u8;
let _ = true as u16;
let _ = true as u32;
let _ = true as u64;
let _ = true as u128;
let _ = true as usize;
let _ = true as i8;
let _ = true as i16;
let _ = true as i32;
let _ = true as i64;
let _ = true as i128;
let _ = true as isize;
// Test with an expression wrapped in parens
let _ = (true | false) as u16;
}
// The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,
// so we skip the lint if the expression is in a const fn.
// See #3656
const fn abc(input: bool) -> u32 {
input as u32
}
// Same as the above issue. We can't suggest `::from` in const fns in impls
mod cast_lossless_in_impl {
struct A;
impl A {
pub const fn convert(x: bool) -> u64 {
x as u64
}
}
}

View File

@ -0,0 +1,82 @@
error: casting `bool` to `u8` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:8:13
|
LL | let _ = true as u8;
| ^^^^^^^^^^ help: try: `u8::from(true)`
|
= note: `-D clippy::cast-lossless` implied by `-D warnings`
error: casting `bool` to `u16` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:9:13
|
LL | let _ = true as u16;
| ^^^^^^^^^^^ help: try: `u16::from(true)`
error: casting `bool` to `u32` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:10:13
|
LL | let _ = true as u32;
| ^^^^^^^^^^^ help: try: `u32::from(true)`
error: casting `bool` to `u64` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:11:13
|
LL | let _ = true as u64;
| ^^^^^^^^^^^ help: try: `u64::from(true)`
error: casting `bool` to `u128` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:12:13
|
LL | let _ = true as u128;
| ^^^^^^^^^^^^ help: try: `u128::from(true)`
error: casting `bool` to `usize` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:13:13
|
LL | let _ = true as usize;
| ^^^^^^^^^^^^^ help: try: `usize::from(true)`
error: casting `bool` to `i8` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:15:13
|
LL | let _ = true as i8;
| ^^^^^^^^^^ help: try: `i8::from(true)`
error: casting `bool` to `i16` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:16:13
|
LL | let _ = true as i16;
| ^^^^^^^^^^^ help: try: `i16::from(true)`
error: casting `bool` to `i32` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:17:13
|
LL | let _ = true as i32;
| ^^^^^^^^^^^ help: try: `i32::from(true)`
error: casting `bool` to `i64` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:18:13
|
LL | let _ = true as i64;
| ^^^^^^^^^^^ help: try: `i64::from(true)`
error: casting `bool` to `i128` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:19:13
|
LL | let _ = true as i128;
| ^^^^^^^^^^^^ help: try: `i128::from(true)`
error: casting `bool` to `isize` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:20:13
|
LL | let _ = true as isize;
| ^^^^^^^^^^^^^ help: try: `isize::from(true)`
error: casting `bool` to `u16` may become silently lossy if you later change the type
--> $DIR/cast_lossless_bool.rs:23:13
|
LL | let _ = (true | false) as u16;
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
error: aborting due to 13 previous errors