11//! lint on manually implemented checked conversions that could be transformed into `try_from`
22
33use if_chain:: if_chain;
4- use lazy_static:: lazy_static;
54use rustc:: hir:: * ;
65use rustc:: lint:: { in_external_macro, LateContext , LateLintPass , LintArray , LintContext , LintPass } ;
76use rustc:: { declare_lint_pass, declare_tool_lint} ;
87use rustc_errors:: Applicability ;
98use syntax:: ast:: LitKind ;
10- use syntax:: symbol:: Symbol ;
119
12- use crate :: utils:: { snippet_with_applicability, span_lint_and_sugg, sym , SpanlessEq } ;
10+ use crate :: utils:: { snippet_with_applicability, span_lint_and_sugg, SpanlessEq } ;
1311
1412declare_clippy_lint ! {
1513 /// **What it does:** Checks for explicit bounds checking when casting.
@@ -104,7 +102,7 @@ fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr, right: &'a Expr) -
104102struct Conversion < ' a > {
105103 cvt : ConversionType ,
106104 expr_to_cast : & ' a Expr ,
107- to_type : Option < Symbol > ,
105+ to_type : Option < & ' a str > ,
108106}
109107
110108/// The kind of conversion that is checked
@@ -140,7 +138,7 @@ impl<'a> Conversion<'a> {
140138 }
141139
142140 /// Try to construct a new conversion if the conversion type is valid
143- fn try_new ( expr_to_cast : & ' a Expr , from_type : Symbol , to_type : Symbol ) -> Option < Conversion < ' a > > {
141+ fn try_new ( expr_to_cast : & ' a Expr , from_type : & str , to_type : & ' a str ) -> Option < Conversion < ' a > > {
144142 ConversionType :: try_new ( from_type, to_type) . map ( |cvt| Conversion {
145143 cvt,
146144 expr_to_cast,
@@ -160,7 +158,7 @@ impl<'a> Conversion<'a> {
160158
161159impl ConversionType {
162160 /// Creates a conversion type if the type is allowed & conversion is valid
163- fn try_new ( from : Symbol , to : Symbol ) -> Option < Self > {
161+ fn try_new ( from : & str , to : & str ) -> Option < Self > {
164162 if UINTS . contains ( & from) {
165163 Some ( ConversionType :: FromUnsigned )
166164 } else if SINTS . contains ( & from) {
@@ -182,7 +180,7 @@ fn check_upper_bound(expr: &Expr) -> Option<Conversion<'_>> {
182180 if_chain ! {
183181 if let ExprKind :: Binary ( ref op, ref left, ref right) = & expr. node;
184182 if let Some ( ( candidate, check) ) = normalize_le_ge( op, left, right) ;
185- if let Some ( ( from, to) ) = get_types_from_cast( check, * sym :: max_value , & * INTS ) ;
183+ if let Some ( ( from, to) ) = get_types_from_cast( check, MAX_VALUE , INTS ) ;
186184
187185 then {
188186 Conversion :: try_new( candidate, from, to)
@@ -222,17 +220,17 @@ fn check_lower_bound_zero<'a>(candidate: &'a Expr, check: &'a Expr) -> Option<Co
222220
223221/// Check for `expr >= (to_type::min_value() as from_type)`
224222fn check_lower_bound_min < ' a > ( candidate : & ' a Expr , check : & ' a Expr ) -> Option < Conversion < ' a > > {
225- if let Some ( ( from, to) ) = get_types_from_cast ( check, * sym :: min_value , & * SINTS ) {
223+ if let Some ( ( from, to) ) = get_types_from_cast ( check, MIN_VALUE , SINTS ) {
226224 Conversion :: try_new ( candidate, from, to)
227225 } else {
228226 None
229227 }
230228}
231229
232230/// Tries to extract the from- and to-type from a cast expression
233- fn get_types_from_cast ( expr : & Expr , func : Symbol , types : & [ Symbol ] ) -> Option < ( Symbol , Symbol ) > {
231+ fn get_types_from_cast < ' a > ( expr : & ' a Expr , func : & ' a str , types : & ' a [ & str ] ) -> Option < ( & ' a str , & ' a str ) > {
234232 // `to_type::maxmin_value() as from_type`
235- let call_from_cast: Option < ( & Expr , Symbol ) > = if_chain ! {
233+ let call_from_cast: Option < ( & Expr , & str ) > = if_chain ! {
236234 // to_type::maxmin_value(), from_type
237235 if let ExprKind :: Cast ( ref limit, ref from_type) = & expr. node;
238236 if let TyKind :: Path ( ref from_type_path) = & from_type. node;
@@ -246,7 +244,7 @@ fn get_types_from_cast(expr: &Expr, func: Symbol, types: &[Symbol]) -> Option<(S
246244 } ;
247245
248246 // `from_type::from(to_type::maxmin_value())`
249- let limit_from: Option < ( & Expr , Symbol ) > = call_from_cast. or_else ( || {
247+ let limit_from: Option < ( & Expr , & str ) > = call_from_cast. or_else ( || {
250248 if_chain ! {
251249 // `from_type::from, to_type::maxmin_value()`
252250 if let ExprKind :: Call ( ref from_func, ref args) = & expr. node;
@@ -255,7 +253,7 @@ fn get_types_from_cast(expr: &Expr, func: Symbol, types: &[Symbol]) -> Option<(S
255253 if let limit = & args[ 0 ] ;
256254 // `from_type::from`
257255 if let ExprKind :: Path ( ref path) = & from_func. node;
258- if let Some ( from_sym) = get_implementing_type( path, & * INTS , * sym :: from ) ;
256+ if let Some ( from_sym) = get_implementing_type( path, INTS , FROM ) ;
259257
260258 then {
261259 Some ( ( limit, from_sym) )
@@ -285,34 +283,31 @@ fn get_types_from_cast(expr: &Expr, func: Symbol, types: &[Symbol]) -> Option<(S
285283}
286284
287285/// Gets the type which implements the called function
288- fn get_implementing_type ( path : & QPath , candidates : & [ Symbol ] , function : Symbol ) -> Option < Symbol > {
286+ fn get_implementing_type < ' a > ( path : & QPath , candidates : & ' a [ & str ] , function : & str ) -> Option < & ' a str > {
289287 if_chain ! {
290288 if let QPath :: TypeRelative ( ref ty, ref path) = & path;
291- if path. ident. name == function;
289+ if path. ident. name. as_str ( ) == function;
292290 if let TyKind :: Path ( QPath :: Resolved ( None , ref tp) ) = & ty. node;
293291 if let [ int] = & * tp. segments;
294- let name = int. ident. name;
295- if candidates. contains( & name) ;
292+ let name = & int. ident. name. as_str( ) ;
296293
297294 then {
298- Some ( name)
295+ candidates . iter ( ) . find ( |c| name == * c ) . cloned ( )
299296 } else {
300297 None
301298 }
302299 }
303300}
304301
305302/// Gets the type as a string, if it is a supported integer
306- fn int_ty_to_sym ( path : & QPath ) -> Option < Symbol > {
303+ fn int_ty_to_sym ( path : & QPath ) -> Option < & str > {
307304 if_chain ! {
308305 if let QPath :: Resolved ( _, ref path) = * path;
309306 if let [ ty] = & * path. segments;
307+ let name = & ty. ident. name. as_str( ) ;
310308
311309 then {
312- INTS
313- . iter( )
314- . find( |c| ty. ident. name == * * c)
315- . cloned( )
310+ INTS . iter( ) . find( |c| name == * c) . cloned( )
316311 } else {
317312 None
318313 }
@@ -328,27 +323,19 @@ fn transpose<T, U>(lhs: Option<T>, rhs: Option<U>) -> Option<(T, U)> {
328323}
329324
330325/// Will return the expressions as if they were expr1 <= expr2
331- fn normalize_le_ge < ' a > ( op : & ' a BinOp , left : & ' a Expr , right : & ' a Expr ) -> Option < ( & ' a Expr , & ' a Expr ) > {
326+ fn normalize_le_ge < ' a > ( op : & BinOp , left : & ' a Expr , right : & ' a Expr ) -> Option < ( & ' a Expr , & ' a Expr ) > {
332327 match op. node {
333328 BinOpKind :: Le => Some ( ( left, right) ) ,
334329 BinOpKind :: Ge => Some ( ( right, left) ) ,
335330 _ => None ,
336331 }
337332}
338333
339- lazy_static ! {
340- static ref UINTS : [ Symbol ; 5 ] = [ * sym:: u8 , * sym:: u16 , * sym:: u32 , * sym:: u64 , * sym:: usize ] ;
341- static ref SINTS : [ Symbol ; 5 ] = [ * sym:: i8 , * sym:: i16 , * sym:: i32 , * sym:: i64 , * sym:: isize ] ;
342- static ref INTS : [ Symbol ; 10 ] = [
343- * sym:: u8 ,
344- * sym:: u16 ,
345- * sym:: u32 ,
346- * sym:: u64 ,
347- * sym:: usize ,
348- * sym:: i8 ,
349- * sym:: i16 ,
350- * sym:: i32 ,
351- * sym:: i64 ,
352- * sym:: isize
353- ] ;
354- }
334+ // Constants
335+ const FROM : & str = "from" ;
336+ const MAX_VALUE : & str = "max_value" ;
337+ const MIN_VALUE : & str = "min_value" ;
338+
339+ const UINTS : & [ & str ] = & [ "u8" , "u16" , "u32" , "u64" , "usize" ] ;
340+ const SINTS : & [ & str ] = & [ "i8" , "i16" , "i32" , "i64" , "isize" ] ;
341+ const INTS : & [ & str ] = & [ "u8" , "u16" , "u32" , "u64" , "usize" , "i8" , "i16" , "i32" , "i64" , "isize" ] ;
0 commit comments