Skip to content

Commit 705bfdc

Browse files
committed
Extend useless_conversion lint with TryInto
1 parent 4f8909f commit 705bfdc

File tree

5 files changed

+77
-19
lines changed

5 files changed

+77
-19
lines changed

clippy_lints/src/useless_conversion.rs

+31-7
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_middle::ty;
1010
use rustc_session::{declare_tool_lint, impl_lint_pass};
1111

1212
declare_clippy_lint! {
13-
/// **What it does:** Checks for `Into`, `From`, `TryFrom`,`IntoIter` calls that useless converts
14-
/// to the same type as caller.
13+
/// **What it does:** Checks for `Into`, `TryInto`, `From`, `TryFrom`,`IntoIter` calls
14+
/// that useless converts to the same type as caller.
1515
///
1616
/// **Why is this bad?** Redundant code.
1717
///
@@ -29,7 +29,7 @@ declare_clippy_lint! {
2929
/// ```
3030
pub USELESS_CONVERSION,
3131
complexity,
32-
"calls to `Into`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type"
32+
"calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type"
3333
}
3434

3535
#[derive(Default)]
@@ -39,6 +39,7 @@ pub struct UselessConversion {
3939

4040
impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]);
4141

42+
#[allow(clippy::too_many_lines)]
4243
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
4344
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx Expr<'_>) {
4445
if e.span.from_expansion() {
@@ -66,7 +67,6 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
6667
let b = cx.tables.expr_ty(&args[0]);
6768
if same_tys(cx, a, b) {
6869
let sugg = snippet_with_macro_callsite(cx, args[0].span, "<expr>").to_string();
69-
7070
span_lint_and_sugg(
7171
cx,
7272
USELESS_CONVERSION,
@@ -94,6 +94,27 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
9494
);
9595
}
9696
}
97+
if match_trait_method(cx, e, &paths::TRY_INTO_TRAIT) && &*name.ident.as_str() == "try_into" {
98+
if_chain! {
99+
let a = cx.tables.expr_ty(e);
100+
let b = cx.tables.expr_ty(&args[0]);
101+
if is_type_diagnostic_item(cx, a, sym!(result_type));
102+
if let ty::Adt(_, substs) = a.kind;
103+
if let Some(a_type) = substs.types().next();
104+
if same_tys(cx, a_type, b);
105+
106+
then {
107+
span_lint_and_help(
108+
cx,
109+
USELESS_CONVERSION,
110+
e.span,
111+
"Useless conversion to the same type",
112+
None,
113+
"consider removing `.try_into()`",
114+
);
115+
}
116+
}
117+
}
97118
},
98119

99120
ExprKind::Call(ref path, ref args) => {
@@ -109,7 +130,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
109130
if match_def_path(cx, def_id, &paths::TRY_FROM);
110131
if is_type_diagnostic_item(cx, a, sym!(result_type));
111132
if let ty::Adt(_, substs) = a.kind;
112-
if let Some(a_type) = substs.types().nth(0);
133+
if let Some(a_type) = substs.types().next();
113134
if same_tys(cx, a_type, b);
114135

115136
then {
@@ -125,8 +146,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
125146
}
126147
}
127148

128-
if match_def_path(cx, def_id, &paths::FROM_FROM) {
129-
if same_tys(cx, a, b) {
149+
if_chain! {
150+
if match_def_path(cx, def_id, &paths::FROM_FROM);
151+
if same_tys(cx, a, b);
152+
153+
then {
130154
let sugg = snippet(cx, args[0].span.source_callsite(), "<expr>").into_owned();
131155
let sugg_msg =
132156
format!("consider removing `{}()`", snippet(cx, path.span, "From::from"));

clippy_lints/src/utils/paths.rs

+1
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ pub const TRANSMUTE: [&str; 4] = ["core", "intrinsics", "", "transmute"];
131131
pub const TRY_FROM: [&str; 4] = ["core", "convert", "TryFrom", "try_from"];
132132
pub const TRY_FROM_ERROR: [&str; 4] = ["std", "ops", "Try", "from_error"];
133133
pub const TRY_INTO_RESULT: [&str; 4] = ["std", "ops", "Try", "into_result"];
134+
pub const TRY_INTO_TRAIT: [&str; 3] = ["core", "convert", "TryInto"];
134135
pub const VEC: [&str; 3] = ["alloc", "vec", "Vec"];
135136
pub const VEC_AS_MUT_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_mut_slice"];
136137
pub const VEC_AS_SLICE: [&str; 4] = ["alloc", "vec", "Vec", "as_slice"];

src/lintlist/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2421,7 +2421,7 @@ pub static ref ALL_LINTS: Vec<Lint> = vec![
24212421
Lint {
24222422
name: "useless_conversion",
24232423
group: "complexity",
2424-
desc: "calls to `Into`/`From`/`IntoIter` that performs useless conversions to the same type",
2424+
desc: "calls to `Into`, `TryInto`, `From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type",
24252425
deprecation: None,
24262426
module: "useless_conversion",
24272427
},

tests/ui/useless_conversion_try.rs

+13-4
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,34 @@
11
#![deny(clippy::useless_conversion)]
22

3-
use std::convert::TryFrom;
3+
use std::convert::{TryFrom, TryInto};
44

55
fn test_generic<T: Copy>(val: T) -> T {
6-
T::try_from(val).unwrap()
6+
let _ = T::try_from(val).unwrap();
7+
val.try_into().unwrap()
78
}
89

910
fn test_generic2<T: Copy + Into<i32> + Into<U>, U: From<T>>(val: T) {
11+
// ok
12+
let _: i32 = val.try_into().unwrap();
13+
let _: U = val.try_into().unwrap();
1014
let _ = U::try_from(val).unwrap();
1115
}
1216

1317
fn main() {
1418
test_generic(10i32);
1519
test_generic2::<i32, i32>(10i32);
1620

21+
let _: String = "foo".try_into().unwrap();
1722
let _: String = TryFrom::try_from("foo").unwrap();
1823
let _ = String::try_from("foo").unwrap();
1924
#[allow(clippy::useless_conversion)]
20-
let _ = String::try_from("foo").unwrap();
21-
25+
{
26+
let _ = String::try_from("foo").unwrap();
27+
let _: String = "foo".try_into().unwrap();
28+
}
29+
let _: String = "foo".to_string().try_into().unwrap();
2230
let _: String = TryFrom::try_from("foo".to_string()).unwrap();
2331
let _ = String::try_from("foo".to_string()).unwrap();
2432
let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
33+
let _: String = format!("Hello {}", "world").try_into().unwrap();
2534
}
+31-7
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
error: Useless conversion to the same type
2-
--> $DIR/useless_conversion_try.rs:6:5
2+
--> $DIR/useless_conversion_try.rs:6:13
33
|
4-
LL | T::try_from(val).unwrap()
5-
| ^^^^^^^^^^^^^^^^
4+
LL | let _ = T::try_from(val).unwrap();
5+
| ^^^^^^^^^^^^^^^^
66
|
77
note: the lint level is defined here
88
--> $DIR/useless_conversion_try.rs:1:9
@@ -12,28 +12,52 @@ LL | #![deny(clippy::useless_conversion)]
1212
= help: consider removing `T::try_from()`
1313

1414
error: Useless conversion to the same type
15-
--> $DIR/useless_conversion_try.rs:22:21
15+
--> $DIR/useless_conversion_try.rs:7:5
16+
|
17+
LL | val.try_into().unwrap()
18+
| ^^^^^^^^^^^^^^
19+
|
20+
= help: consider removing `.try_into()`
21+
22+
error: Useless conversion to the same type
23+
--> $DIR/useless_conversion_try.rs:29:21
24+
|
25+
LL | let _: String = "foo".to_string().try_into().unwrap();
26+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
27+
|
28+
= help: consider removing `.try_into()`
29+
30+
error: Useless conversion to the same type
31+
--> $DIR/useless_conversion_try.rs:30:21
1632
|
1733
LL | let _: String = TryFrom::try_from("foo".to_string()).unwrap();
1834
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1935
|
2036
= help: consider removing `TryFrom::try_from()`
2137

2238
error: Useless conversion to the same type
23-
--> $DIR/useless_conversion_try.rs:23:13
39+
--> $DIR/useless_conversion_try.rs:31:13
2440
|
2541
LL | let _ = String::try_from("foo".to_string()).unwrap();
2642
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2743
|
2844
= help: consider removing `String::try_from()`
2945

3046
error: Useless conversion to the same type
31-
--> $DIR/useless_conversion_try.rs:24:13
47+
--> $DIR/useless_conversion_try.rs:32:13
3248
|
3349
LL | let _ = String::try_from(format!("A: {:04}", 123)).unwrap();
3450
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3551
|
3652
= help: consider removing `String::try_from()`
3753

38-
error: aborting due to 4 previous errors
54+
error: Useless conversion to the same type
55+
--> $DIR/useless_conversion_try.rs:33:21
56+
|
57+
LL | let _: String = format!("Hello {}", "world").try_into().unwrap();
58+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
59+
|
60+
= help: consider removing `.try_into()`
61+
62+
error: aborting due to 7 previous errors
3963

0 commit comments

Comments
 (0)