Skip to content

Commit 3382201

Browse files
committed
Lint for bool to integer casts in cast_lossless
1 parent c94d62b commit 3382201

File tree

6 files changed

+177
-7
lines changed

6 files changed

+177
-7
lines changed

clippy_lints/src/bool_assert_comparison.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ impl<'tcx> LateLintPass<'tcx> for BoolAssertComparison {
7272
if let Some(span) = is_direct_expn_of(expr.span, mac) {
7373
if let Some(args) = higher::extract_assert_macro_args(expr) {
7474
if let [a, b, ..] = args[..] {
75-
let nb_bool_args = is_bool_lit(a) as usize + is_bool_lit(b) as usize;
75+
let nb_bool_args = usize::from(is_bool_lit(a)) + usize::from(is_bool_lit(b));
7676

7777
if nb_bool_args != 1 {
7878
// If there are two boolean arguments, we definitely don't understand

clippy_lints/src/casts/cast_lossless.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ fn should_lint(cx: &LateContext<'_>, expr: &Expr<'_>, cast_from: Ty<'_>, cast_to
7272
};
7373
from_nbits < to_nbits
7474
},
75-
75+
(false, true) if matches!(cast_from.kind(), ty::Bool) => true,
7676
(_, _) => {
7777
matches!(cast_from.kind(), ty::Float(FloatTy::F32)) && matches!(cast_to.kind(), ty::Float(FloatTy::F64))
7878
},

clippy_lints/src/casts/mod.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,12 +426,16 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
426426
fn_to_numeric_cast_any::check(cx, expr, cast_expr, cast_from, cast_to);
427427
fn_to_numeric_cast::check(cx, expr, cast_expr, cast_from, cast_to);
428428
fn_to_numeric_cast_with_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
429-
if cast_from.is_numeric() && cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
430-
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
431-
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
432-
cast_precision_loss::check(cx, expr, cast_from, cast_to);
429+
430+
if cast_to.is_numeric() && !in_external_macro(cx.sess(), expr.span) {
431+
if cast_from.is_numeric() {
432+
cast_possible_truncation::check(cx, expr, cast_expr, cast_from, cast_to);
433+
cast_possible_wrap::check(cx, expr, cast_from, cast_to);
434+
cast_precision_loss::check(cx, expr, cast_from, cast_to);
435+
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
436+
}
437+
433438
cast_lossless::check(cx, expr, cast_expr, cast_from, cast_to);
434-
cast_sign_loss::check(cx, expr, cast_expr, cast_from, cast_to);
435439
}
436440
}
437441

tests/ui/cast_lossless_bool.fixed

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
#![warn(clippy::cast_lossless)]
5+
6+
fn main() {
7+
// Test clippy::cast_lossless with casts to integer types
8+
let _ = u8::from(true);
9+
let _ = u16::from(true);
10+
let _ = u32::from(true);
11+
let _ = u64::from(true);
12+
let _ = u128::from(true);
13+
let _ = usize::from(true);
14+
15+
let _ = i8::from(true);
16+
let _ = i16::from(true);
17+
let _ = i32::from(true);
18+
let _ = i64::from(true);
19+
let _ = i128::from(true);
20+
let _ = isize::from(true);
21+
22+
// Test with an expression wrapped in parens
23+
let _ = u16::from(true | false);
24+
}
25+
26+
// The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,
27+
// so we skip the lint if the expression is in a const fn.
28+
// See #3656
29+
const fn abc(input: bool) -> u32 {
30+
input as u32
31+
}
32+
33+
// Same as the above issue. We can't suggest `::from` in const fns in impls
34+
mod cast_lossless_in_impl {
35+
struct A;
36+
37+
impl A {
38+
pub const fn convert(x: bool) -> u64 {
39+
x as u64
40+
}
41+
}
42+
}

tests/ui/cast_lossless_bool.rs

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// run-rustfix
2+
3+
#![allow(dead_code)]
4+
#![warn(clippy::cast_lossless)]
5+
6+
fn main() {
7+
// Test clippy::cast_lossless with casts to integer types
8+
let _ = true as u8;
9+
let _ = true as u16;
10+
let _ = true as u32;
11+
let _ = true as u64;
12+
let _ = true as u128;
13+
let _ = true as usize;
14+
15+
let _ = true as i8;
16+
let _ = true as i16;
17+
let _ = true as i32;
18+
let _ = true as i64;
19+
let _ = true as i128;
20+
let _ = true as isize;
21+
22+
// Test with an expression wrapped in parens
23+
let _ = (true | false) as u16;
24+
}
25+
26+
// The lint would suggest using `u32::from(input)` here but the `XX::from` function is not const,
27+
// so we skip the lint if the expression is in a const fn.
28+
// See #3656
29+
const fn abc(input: bool) -> u32 {
30+
input as u32
31+
}
32+
33+
// Same as the above issue. We can't suggest `::from` in const fns in impls
34+
mod cast_lossless_in_impl {
35+
struct A;
36+
37+
impl A {
38+
pub const fn convert(x: bool) -> u64 {
39+
x as u64
40+
}
41+
}
42+
}

tests/ui/cast_lossless_bool.stderr

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
error: casting `bool` to `u8` may become silently lossy if you later change the type
2+
--> $DIR/cast_lossless_bool.rs:8:13
3+
|
4+
LL | let _ = true as u8;
5+
| ^^^^^^^^^^ help: try: `u8::from(true)`
6+
|
7+
= note: `-D clippy::cast-lossless` implied by `-D warnings`
8+
9+
error: casting `bool` to `u16` may become silently lossy if you later change the type
10+
--> $DIR/cast_lossless_bool.rs:9:13
11+
|
12+
LL | let _ = true as u16;
13+
| ^^^^^^^^^^^ help: try: `u16::from(true)`
14+
15+
error: casting `bool` to `u32` may become silently lossy if you later change the type
16+
--> $DIR/cast_lossless_bool.rs:10:13
17+
|
18+
LL | let _ = true as u32;
19+
| ^^^^^^^^^^^ help: try: `u32::from(true)`
20+
21+
error: casting `bool` to `u64` may become silently lossy if you later change the type
22+
--> $DIR/cast_lossless_bool.rs:11:13
23+
|
24+
LL | let _ = true as u64;
25+
| ^^^^^^^^^^^ help: try: `u64::from(true)`
26+
27+
error: casting `bool` to `u128` may become silently lossy if you later change the type
28+
--> $DIR/cast_lossless_bool.rs:12:13
29+
|
30+
LL | let _ = true as u128;
31+
| ^^^^^^^^^^^^ help: try: `u128::from(true)`
32+
33+
error: casting `bool` to `usize` may become silently lossy if you later change the type
34+
--> $DIR/cast_lossless_bool.rs:13:13
35+
|
36+
LL | let _ = true as usize;
37+
| ^^^^^^^^^^^^^ help: try: `usize::from(true)`
38+
39+
error: casting `bool` to `i8` may become silently lossy if you later change the type
40+
--> $DIR/cast_lossless_bool.rs:15:13
41+
|
42+
LL | let _ = true as i8;
43+
| ^^^^^^^^^^ help: try: `i8::from(true)`
44+
45+
error: casting `bool` to `i16` may become silently lossy if you later change the type
46+
--> $DIR/cast_lossless_bool.rs:16:13
47+
|
48+
LL | let _ = true as i16;
49+
| ^^^^^^^^^^^ help: try: `i16::from(true)`
50+
51+
error: casting `bool` to `i32` may become silently lossy if you later change the type
52+
--> $DIR/cast_lossless_bool.rs:17:13
53+
|
54+
LL | let _ = true as i32;
55+
| ^^^^^^^^^^^ help: try: `i32::from(true)`
56+
57+
error: casting `bool` to `i64` may become silently lossy if you later change the type
58+
--> $DIR/cast_lossless_bool.rs:18:13
59+
|
60+
LL | let _ = true as i64;
61+
| ^^^^^^^^^^^ help: try: `i64::from(true)`
62+
63+
error: casting `bool` to `i128` may become silently lossy if you later change the type
64+
--> $DIR/cast_lossless_bool.rs:19:13
65+
|
66+
LL | let _ = true as i128;
67+
| ^^^^^^^^^^^^ help: try: `i128::from(true)`
68+
69+
error: casting `bool` to `isize` may become silently lossy if you later change the type
70+
--> $DIR/cast_lossless_bool.rs:20:13
71+
|
72+
LL | let _ = true as isize;
73+
| ^^^^^^^^^^^^^ help: try: `isize::from(true)`
74+
75+
error: casting `bool` to `u16` may become silently lossy if you later change the type
76+
--> $DIR/cast_lossless_bool.rs:23:13
77+
|
78+
LL | let _ = (true | false) as u16;
79+
| ^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::from(true | false)`
80+
81+
error: aborting due to 13 previous errors
82+

0 commit comments

Comments
 (0)