Skip to content

Commit 4f8909f

Browse files
committed
Extend useless_conversion lint with TryFrom
1 parent c41916d commit 4f8909f

File tree

5 files changed

+112
-20
lines changed

5 files changed

+112
-20
lines changed

clippy_lints/src/useless_conversion.rs

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
use crate::utils::{
2-
match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite, span_lint_and_sugg,
2+
is_type_diagnostic_item, match_def_path, match_trait_method, paths, same_tys, snippet, snippet_with_macro_callsite,
3+
span_lint_and_help, span_lint_and_sugg,
34
};
5+
use if_chain::if_chain;
46
use rustc_errors::Applicability;
57
use rustc_hir::{Expr, ExprKind, HirId, MatchSource};
68
use rustc_lint::{LateContext, LateLintPass};
9+
use rustc_middle::ty;
710
use rustc_session::{declare_tool_lint, impl_lint_pass};
811

912
declare_clippy_lint! {
10-
/// **What it does:** Checks for `Into`/`From`/`IntoIter` calls that useless converts
13+
/// **What it does:** Checks for `Into`, `From`, `TryFrom`,`IntoIter` calls that useless converts
1114
/// to the same type as caller.
1215
///
1316
/// **Why is this bad?** Redundant code.
@@ -26,7 +29,7 @@ declare_clippy_lint! {
2629
/// ```
2730
pub USELESS_CONVERSION,
2831
complexity,
29-
"calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type"
32+
"calls to `Into`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type"
3033
}
3134

3235
#[derive(Default)]
@@ -68,7 +71,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
6871
cx,
6972
USELESS_CONVERSION,
7073
e.span,
71-
"useless conversion",
74+
"Useless conversion to the same type",
7275
"consider removing `.into()`",
7376
sugg,
7477
Applicability::MachineApplicable, // snippet
@@ -84,7 +87,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
8487
cx,
8588
USELESS_CONVERSION,
8689
e.span,
87-
"useless conversion",
90+
"Useless conversion to the same type",
8891
"consider removing `.into_iter()`",
8992
sugg,
9093
Applicability::MachineApplicable, // snippet
@@ -94,11 +97,35 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
9497
},
9598

9699
ExprKind::Call(ref path, ref args) => {
97-
if let ExprKind::Path(ref qpath) = path.kind {
98-
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id() {
100+
if_chain! {
101+
if args.len() == 1;
102+
if let ExprKind::Path(ref qpath) = path.kind;
103+
if let Some(def_id) = cx.tables.qpath_res(qpath, path.hir_id).opt_def_id();
104+
let a = cx.tables.expr_ty(e);
105+
let b = cx.tables.expr_ty(&args[0]);
106+
107+
then {
108+
if_chain! {
109+
if match_def_path(cx, def_id, &paths::TRY_FROM);
110+
if is_type_diagnostic_item(cx, a, sym!(result_type));
111+
if let ty::Adt(_, substs) = a.kind;
112+
if let Some(a_type) = substs.types().nth(0);
113+
if same_tys(cx, a_type, b);
114+
115+
then {
116+
let hint = format!("consider removing `{}()`", snippet(cx, path.span, "TryFrom::try_from"));
117+
span_lint_and_help(
118+
cx,
119+
USELESS_CONVERSION,
120+
e.span,
121+
"Useless conversion to the same type",
122+
None,
123+
&hint,
124+
);
125+
}
126+
}
127+
99128
if match_def_path(cx, def_id, &paths::FROM_FROM) {
100-
let a = cx.tables.expr_ty(e);
101-
let b = cx.tables.expr_ty(&args[0]);
102129
if same_tys(cx, a, b) {
103130
let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned();
104131
let sugg_msg =
@@ -107,7 +134,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
107134
cx,
108135
USELESS_CONVERSION,
109136
e.span,
110-
"useless conversion",
137+
"Useless conversion to the same type",
111138
&sugg_msg,
112139
sugg,
113140
Applicability::MachineApplicable, // snippet

clippy_lints/src/utils/paths.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ pub const TO_OWNED_METHOD: [&str; 4] = ["alloc", "borrow", "ToOwned", "to_owned"
128128
pub const TO_STRING: [&str; 3] = ["alloc", "string", "ToString"];
129129
pub const TO_STRING_METHOD: [&str; 4] = ["alloc", "string", "ToString", "to_string"];
130130
pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
131+
pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
131132
pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"];
132133
pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
133134
pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];

tests/ui/useless_conversion.stderr

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
error: useless conversion
1+
error: Useless conversion to the same type
22
--> $DIR/useless_conversion.rs:6:13
33
|
44
LL | let _ = T::from(val);
@@ -10,55 +10,55 @@ note: the lint level is defined here
1010
LL | #![deny(clippy::useless_conversion)]
1111
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1212

13-
error: useless conversion
13+
error: Useless conversion to the same type
1414
--> $DIR/useless_conversion.rs:7:5
1515
|
1616
LL | val.into()
1717
| ^^^^^^^^^^ help: consider removing `.into()`: `val`
1818

19-
error: useless conversion
19+
error: Useless conversion to the same type
2020
--> $DIR/useless_conversion.rs:19:22
2121
|
2222
LL | let _: i32 = 0i32.into();
2323
| ^^^^^^^^^^^ help: consider removing `.into()`: `0i32`
2424

25-
error: useless conversion
25+
error: Useless conversion to the same type
2626
--> $DIR/useless_conversion.rs:51:21
2727
|
2828
LL | let _: String = "foo".to_string().into();
2929
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into()`: `"foo".to_string()`
3030

31-
error: useless conversion
31+
error: Useless conversion to the same type
3232
--> $DIR/useless_conversion.rs:52:21
3333
|
3434
LL | let _: String = From::from("foo".to_string());
3535
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `From::from()`: `"foo".to_string()`
3636

37-
error: useless conversion
37+
error: Useless conversion to the same type
3838
--> $DIR/useless_conversion.rs:53:13
3939
|
4040
LL | let _ = String::from("foo".to_string());
4141
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `"foo".to_string()`
4242

43-
error: useless conversion
43+
error: Useless conversion to the same type
4444
--> $DIR/useless_conversion.rs:54:13
4545
|
4646
LL | let _ = String::from(format!("A: {:04}", 123));
4747
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `String::from()`: `format!("A: {:04}", 123)`
4848

49-
error: useless conversion
49+
error: Useless conversion to the same type
5050
--> $DIR/useless_conversion.rs:55:13
5151
|
5252
LL | let _ = "".lines().into_iter();
5353
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `"".lines()`
5454

55-
error: useless conversion
55+
error: Useless conversion to the same type
5656
--> $DIR/useless_conversion.rs:56:13
5757
|
5858
LL | let _ = vec![1, 2, 3].into_iter().into_iter();
5959
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![1, 2, 3].into_iter()`
6060

61-
error: useless conversion
61+
error: Useless conversion to the same type
6262
--> $DIR/useless_conversion.rs:57:21
6363
|
6464
LL | let _: String = format!("Hello {}", "world").into();

tests/ui/useless_conversion_try.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![deny(clippy::useless_conversion)]
2+
3+
use std::convert::TryFrom;
4+
5+
fn test_generic<T: Copy>(val: T) -> T {
6+
T::try_from(val).unwrap()
7+
}
8+
9+
fn test_generic2<T: Copy + Into<i32> + Into<U>, U: From<T>>(val: T) {
10+
let _ = U::try_from(val).unwrap();
11+
}
12+
13+
fn main() {
14+
test_generic(10i32);
15+
test_generic2::<i32, i32>(10i32);
16+
17+
let _: String = TryFrom::try_from("foo").unwrap();
18+
let _ = String::try_from("foo").unwrap();
19+
#[allow(clippy::useless_conversion)]
20+
let _ = String::try_from("foo").unwrap();
21+
22+
let _: String = TryFrom::try_from("foo".to_string()).unwrap();
23+
let _ = String::try_from("foo".to_string()).unwrap();
24+
let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
25+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error: Useless conversion to the same type
2+
--> $DIR/useless_conversion_try.rs:6:5
3+
|
4+
LL | T::try_from(val).unwrap()
5+
| ^^^^^^^^^^^^^^^^
6+
|
7+
note: the lint level is defined here
8+
--> $DIR/useless_conversion_try.rs:1:9
9+
|
10+
LL | #![deny(clippy::useless_conversion)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
= help: consider removing `T::try_from()`
13+
14+
error: Useless conversion to the same type
15+
--> $DIR/useless_conversion_try.rs:22:21
16+
|
17+
LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap();
18+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
19+
|
20+
= help: consider removing `TryFrom::try_from()`
21+
22+
error: Useless conversion to the same type
23+
--> $DIR/useless_conversion_try.rs:23:13
24+
|
25+
LL | let _ = String::try_from("foo".to_string()).unwrap();
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
|
28+
= help: consider removing `String::try_from()`
29+
30+
error: Useless conversion to the same type
31+
--> $DIR/useless_conversion_try.rs:24:13
32+
|
33+
LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
34+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35+
|
36+
= help: consider removing `String::try_from()`
37+
38+
error: aborting due to 4 previous errors
39+

0 commit comments

Comments
 (0)