Skip to content

Commit 00a5ef6

Browse files
committed
Added suggestion for conversion with is_ok.
1 parent 0a43dcf commit 00a5ef6

File tree

4 files changed

+156
-36
lines changed

4 files changed

+156
-36
lines changed

clippy_lints/src/checked_conversions.rs

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ use if_chain::if_chain;
44
use rustc::hir::*;
55
use rustc::lint::{in_external_macro, LateContext, LateLintPass, LintArray, LintContext, LintPass};
66
use rustc::{declare_lint_pass, declare_tool_lint};
7+
use rustc_errors::Applicability;
78
use syntax::ast::LitKind;
8-
9-
use crate::utils::{span_lint, SpanlessEq};
9+
use crate::utils::{span_lint_and_sugg, snippet_with_applicability, SpanlessEq};
1010

1111
declare_clippy_lint! {
1212
/// **What it does:** Checks for explicit bounds checking when casting.
@@ -54,16 +54,26 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for CheckedConversions {
5454
}
5555
};
5656

57-
if let Some(cv) = result {
58-
span_lint(
59-
cx,
60-
CHECKED_CONVERSIONS,
61-
item.span,
62-
&format!(
63-
"Checked cast can be simplified: `{}::try_from`",
64-
cv.to_type.unwrap_or_else(|| "IntegerType".to_string()),
65-
),
66-
);
57+
if_chain! {
58+
if let Some(cv) = result;
59+
if let Some(to_type) = cv.to_type;
60+
61+
then {
62+
let mut applicability = Applicability::MachineApplicable;
63+
let snippet = snippet_with_applicability(cx, cv.expr_to_cast.span, "_", &mut
64+
applicability);
65+
span_lint_and_sugg(
66+
cx,
67+
CHECKED_CONVERSIONS,
68+
item.span,
69+
"Checked cast can be simplified.",
70+
"try",
71+
format!("{}::try_from({}).is_ok()",
72+
to_type,
73+
snippet),
74+
applicability
75+
);
76+
}
6777
}
6878
}
6979
}

tests/ui/checked_conversions.fixed

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
// run-rustfix
2+
3+
#![warn(clippy::checked_conversions)]
4+
#![allow(clippy::cast_lossless)]
5+
#![allow(dead_code)]
6+
use std::convert::TryFrom;
7+
8+
// Positive tests
9+
10+
// Signed to unsigned
11+
12+
fn i64_to_u32(value: i64) -> Option<u32> {
13+
if u32::try_from(value).is_ok() {
14+
Some(value as u32)
15+
} else {
16+
None
17+
}
18+
}
19+
20+
fn i64_to_u16(value: i64) -> Option<u16> {
21+
if u16::try_from(value).is_ok() {
22+
Some(value as u16)
23+
} else {
24+
None
25+
}
26+
}
27+
28+
fn isize_to_u8(value: isize) -> Option<u8> {
29+
if u8::try_from(value).is_ok() {
30+
Some(value as u8)
31+
} else {
32+
None
33+
}
34+
}
35+
36+
// Signed to signed
37+
38+
fn i64_to_i32(value: i64) -> Option<i32> {
39+
if i32::try_from(value).is_ok() {
40+
Some(value as i32)
41+
} else {
42+
None
43+
}
44+
}
45+
46+
fn i64_to_i16(value: i64) -> Option<i16> {
47+
if i16::try_from(value).is_ok() {
48+
Some(value as i16)
49+
} else {
50+
None
51+
}
52+
}
53+
54+
// Unsigned to X
55+
56+
fn u32_to_i32(value: u32) -> Option<i32> {
57+
if i32::try_from(value).is_ok() {
58+
Some(value as i32)
59+
} else {
60+
None
61+
}
62+
}
63+
64+
fn usize_to_isize(value: usize) -> isize {
65+
if isize::try_from(value).is_ok() && value as i32 == 5 {
66+
5
67+
} else {
68+
1
69+
}
70+
}
71+
72+
fn u32_to_u16(value: u32) -> isize {
73+
if u16::try_from(value).is_ok() && value as i32 == 5 {
74+
5
75+
} else {
76+
1
77+
}
78+
}
79+
80+
// Negative tests
81+
82+
fn no_i64_to_i32(value: i64) -> Option<i32> {
83+
if value <= (i32::max_value() as i64) && value >= 0 {
84+
Some(value as i32)
85+
} else {
86+
None
87+
}
88+
}
89+
90+
fn no_isize_to_u8(value: isize) -> Option<u8> {
91+
if value <= (u8::max_value() as isize) && value >= (u8::min_value() as isize) {
92+
Some(value as u8)
93+
} else {
94+
None
95+
}
96+
}
97+
98+
fn i8_to_u8(value: i8) -> Option<u8> {
99+
if value >= 0 {
100+
Some(value as u8)
101+
} else {
102+
None
103+
}
104+
}
105+
106+
fn main() {}

tests/ui/checked_conversions.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
// run-rustfix
2+
13
#![warn(clippy::checked_conversions)]
24
#![allow(clippy::cast_lossless)]
5+
#![allow(dead_code)]
6+
use std::convert::TryFrom;
37

48
// Positive tests
59

tests/ui/checked_conversions.stderr

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,52 @@
1-
error: Checked cast can be simplified: `u32::try_from`
2-
--> $DIR/checked_conversions.rs:9:8
1+
error: Checked cast can be simplified.
2+
--> $DIR/checked_conversions.rs:13:8
33
|
44
LL | if value <= (u32::max_value() as i64) && value >= 0 {
5-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u32::try_from(value).is_ok()`
66
|
77
= note: `-D clippy::checked-conversions` implied by `-D warnings`
88

9-
error: Checked cast can be simplified: `u16::try_from`
10-
--> $DIR/checked_conversions.rs:17:8
9+
error: Checked cast can be simplified.
10+
--> $DIR/checked_conversions.rs:21:8
1111
|
1212
LL | if value <= i64::from(u16::max_value()) && value >= 0 {
13-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
1414

15-
error: Checked cast can be simplified: `u8::try_from`
16-
--> $DIR/checked_conversions.rs:25:8
15+
error: Checked cast can be simplified.
16+
--> $DIR/checked_conversions.rs:29:8
1717
|
1818
LL | if value <= (u8::max_value() as isize) && value >= 0 {
19-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u8::try_from(value).is_ok()`
2020

21-
error: Checked cast can be simplified: `i32::try_from`
22-
--> $DIR/checked_conversions.rs:35:8
21+
error: Checked cast can be simplified.
22+
--> $DIR/checked_conversions.rs:39:8
2323
|
2424
LL | if value <= (i32::max_value() as i64) && value >= (i32::min_value() as i64) {
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
25+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
2626

27-
error: Checked cast can be simplified: `i16::try_from`
28-
--> $DIR/checked_conversions.rs:43:8
27+
error: Checked cast can be simplified.
28+
--> $DIR/checked_conversions.rs:47:8
2929
|
3030
LL | if value <= i64::from(i16::max_value()) && value >= i64::from(i16::min_value()) {
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i16::try_from(value).is_ok()`
3232

33-
error: Checked cast can be simplified: `i32::try_from`
34-
--> $DIR/checked_conversions.rs:53:8
33+
error: Checked cast can be simplified.
34+
--> $DIR/checked_conversions.rs:57:8
3535
|
3636
LL | if value <= i32::max_value() as u32 {
37-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
37+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `i32::try_from(value).is_ok()`
3838

39-
error: Checked cast can be simplified: `isize::try_from`
40-
--> $DIR/checked_conversions.rs:61:8
39+
error: Checked cast can be simplified.
40+
--> $DIR/checked_conversions.rs:65:8
4141
|
4242
LL | if value <= isize::max_value() as usize && value as i32 == 5 {
43-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
43+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `isize::try_from(value).is_ok()`
4444

45-
error: Checked cast can be simplified: `u16::try_from`
46-
--> $DIR/checked_conversions.rs:69:8
45+
error: Checked cast can be simplified.
46+
--> $DIR/checked_conversions.rs:73:8
4747
|
4848
LL | if value <= u16::max_value() as u32 && value as i32 == 5 {
49-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `u16::try_from(value).is_ok()`
5050

5151
error: aborting due to 8 previous errors
5252

0 commit comments

Comments
 (0)