11use 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;
46use rustc_errors:: Applicability ;
57use rustc_hir:: { Expr , ExprKind , HirId , MatchSource } ;
68use rustc_lint:: { LateContext , LateLintPass } ;
9+ use rustc_middle:: ty;
710use rustc_session:: { declare_tool_lint, impl_lint_pass} ;
811
912declare_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.
1215 ///
1316 /// **Why is this bad?** Redundant code.
1417 ///
@@ -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`, `TryInto`, ` From`, `TryFrom`, `IntoIter` that performs useless conversions to the same type"
3033}
3134
3235#[ derive( Default ) ]
@@ -36,6 +39,7 @@ pub struct UselessConversion {
3639
3740impl_lint_pass ! ( UselessConversion => [ USELESS_CONVERSION ] ) ;
3841
42+ #[ allow( clippy:: too_many_lines) ]
3943impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for UselessConversion {
4044 fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , e : & ' tcx Expr < ' _ > ) {
4145 if e. span . from_expansion ( ) {
@@ -63,12 +67,11 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UselessConversion {
6367 let b = cx. tables . expr_ty ( & args[ 0 ] ) ;
6468 if same_tys ( cx, a, b) {
6569 let sugg = snippet_with_macro_callsite ( cx, args[ 0 ] . span , "<expr>" ) . to_string ( ) ;
66-
6770 span_lint_and_sugg (
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,30 +87,78 @@ 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
9194 ) ;
9295 }
9396 }
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+ }
94118 } ,
95119
96120 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 {
103154 let sugg = snippet( cx, args[ 0 ] . span. source_callsite( ) , "<expr>" ) . into_owned( ) ;
104155 let sugg_msg =
105156 format!( "consider removing `{}()`" , snippet( cx, path. span, "From::from" ) ) ;
106157 span_lint_and_sugg(
107158 cx,
108159 USELESS_CONVERSION ,
109160 e. span,
110- "useless conversion" ,
161+ "useless conversion to the same type " ,
111162 & sugg_msg,
112163 sugg,
113164 Applicability :: MachineApplicable , // snippet
0 commit comments