1
1
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,
3
4
} ;
5
+ use if_chain:: if_chain;
4
6
use rustc_errors:: Applicability ;
5
7
use rustc_hir:: { Expr , ExprKind , HirId , MatchSource } ;
6
8
use rustc_lint:: { LateContext , LateLintPass } ;
9
+ use rustc_middle:: ty;
7
10
use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
8
11
9
12
declare_clippy_lint ! {
10
- /// **What it does:** Checks for `Into`/` From`/` IntoIter` calls that useless converts
11
- /// 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.
12
15
///
13
16
/// **Why is this bad?** Redundant code.
14
17
///
@@ -26,7 +29,7 @@ declare_clippy_lint! {
26
29
/// ```
27
30
pub USELESS_CONVERSION ,
28
31
complexity,
29
- "calls to `Into`/` From`/ `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"
30
33
}
31
34
32
35
#[ derive( Default ) ]
@@ -36,6 +39,7 @@ pub struct UselessConversion {
36
39
37
40
impl_lint_pass ! ( UselessConversion => [ USELESS_CONVERSION ] ) ;
38
41
42
+ #[ allow( clippy:: too_many_lines) ]
39
43
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for UselessConversion {
40
44
fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , e : & ' tcx Expr < ' _ > ) {
41
45
if e. span . from_expansion ( ) {
@@ -63,12 +67,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
63
67
let b = cx. tables . expr_ty ( & args[ 0 ] ) ;
64
68
if same_tys ( cx, a, b) {
65
69
let sugg = snippet_with_macro_callsite ( cx, args[ 0 ] . span , "<expr>" ) . to_string ( ) ;
66
-
67
70
span_lint_and_sugg (
68
71
cx,
69
72
USELESS_CONVERSION ,
70
73
e. span ,
71
- "useless conversion" ,
74
+ "useless conversion to the same type " ,
72
75
"consider removing `.into()`" ,
73
76
sugg,
74
77
Applicability :: MachineApplicable , // snippet
@@ -84,30 +87,78 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
84
87
cx,
85
88
USELESS_CONVERSION ,
86
89
e. span ,
87
- "useless conversion" ,
90
+ "useless conversion to the same type " ,
88
91
"consider removing `.into_iter()`" ,
89
92
sugg,
90
93
Applicability :: MachineApplicable , // snippet
91
94
) ;
92
95
}
93
96
}
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
+ }
94
118
} ,
95
119
96
120
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 ( ) {
99
- 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 ] ) ;
102
- if same_tys ( cx, a, b) {
121
+ if_chain ! {
122
+ if args. len( ) == 1 ;
123
+ if let ExprKind :: Path ( ref qpath) = path. kind;
124
+ if let Some ( def_id) = cx. tables. qpath_res( qpath, path. hir_id) . opt_def_id( ) ;
125
+ let a = cx. tables. expr_ty( e) ;
126
+ let b = cx. tables. expr_ty( & args[ 0 ] ) ;
127
+
128
+ then {
129
+ if_chain! {
130
+ if match_def_path( cx, def_id, & paths:: TRY_FROM ) ;
131
+ if is_type_diagnostic_item( cx, a, sym!( result_type) ) ;
132
+ if let ty:: Adt ( _, substs) = a. kind;
133
+ if let Some ( a_type) = substs. types( ) . next( ) ;
134
+ if same_tys( cx, a_type, b) ;
135
+
136
+ then {
137
+ let hint = format!( "consider removing `{}()`" , snippet( cx, path. span, "TryFrom::try_from" ) ) ;
138
+ span_lint_and_help(
139
+ cx,
140
+ USELESS_CONVERSION ,
141
+ e. span,
142
+ "useless conversion to the same type" ,
143
+ None ,
144
+ & hint,
145
+ ) ;
146
+ }
147
+ }
148
+
149
+ if_chain! {
150
+ if match_def_path( cx, def_id, & paths:: FROM_FROM ) ;
151
+ if same_tys( cx, a, b) ;
152
+
153
+ then {
103
154
let sugg = snippet( cx, args[ 0 ] . span. source_callsite( ) , "<expr>" ) . into_owned( ) ;
104
155
let sugg_msg =
105
156
format!( "consider removing `{}()`" , snippet( cx, path. span, "From::from" ) ) ;
106
157
span_lint_and_sugg(
107
158
cx,
108
159
USELESS_CONVERSION ,
109
160
e. span,
110
- "useless conversion" ,
161
+ "useless conversion to the same type " ,
111
162
& sugg_msg,
112
163
sugg,
113
164
Applicability :: MachineApplicable , // snippet
0 commit comments