1
1
//! lint on manually implemented checked conversions that could be transformed into `try_from`
2
2
3
3
use if_chain:: if_chain;
4
- use lazy_static:: lazy_static;
5
4
use rustc:: hir:: * ;
6
5
use rustc:: lint:: { in_external_macro, LateContext , LateLintPass , LintArray , LintContext , LintPass } ;
7
6
use rustc:: { declare_lint_pass, declare_tool_lint} ;
8
7
use rustc_errors:: Applicability ;
9
8
use syntax:: ast:: LitKind ;
10
- use syntax:: symbol:: Symbol ;
11
9
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 } ;
13
11
14
12
declare_clippy_lint ! {
15
13
/// **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) -
104
102
struct Conversion < ' a > {
105
103
cvt : ConversionType ,
106
104
expr_to_cast : & ' a Expr ,
107
- to_type : Option < Symbol > ,
105
+ to_type : Option < & ' a str > ,
108
106
}
109
107
110
108
/// The kind of conversion that is checked
@@ -140,7 +138,7 @@ impl<'a> Conversion<'a> {
140
138
}
141
139
142
140
/// 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 > > {
144
142
ConversionType :: try_new ( from_type, to_type) . map ( |cvt| Conversion {
145
143
cvt,
146
144
expr_to_cast,
@@ -160,7 +158,7 @@ impl<'a> Conversion<'a> {
160
158
161
159
impl ConversionType {
162
160
/// 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 > {
164
162
if UINTS . contains ( & from) {
165
163
Some ( ConversionType :: FromUnsigned )
166
164
} else if SINTS . contains ( & from) {
@@ -182,7 +180,7 @@ fn check_upper_bound(expr: &Expr) -> Option<Conversion<'_>> {
182
180
if_chain ! {
183
181
if let ExprKind :: Binary ( ref op, ref left, ref right) = & expr. node;
184
182
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 ) ;
186
184
187
185
then {
188
186
Conversion :: try_new( candidate, from, to)
@@ -222,17 +220,17 @@ fn check_lower_bound_zero<'a>(candidate: &'a Expr, check: &'a Expr) -> Option<Co
222
220
223
221
/// Check for `expr >= (to_type::min_value() as from_type)`
224
222
fn 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 ) {
226
224
Conversion :: try_new ( candidate, from, to)
227
225
} else {
228
226
None
229
227
}
230
228
}
231
229
232
230
/// 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 ) > {
234
232
// `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 ! {
236
234
// to_type::maxmin_value(), from_type
237
235
if let ExprKind :: Cast ( ref limit, ref from_type) = & expr. node;
238
236
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
246
244
} ;
247
245
248
246
// `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 ( || {
250
248
if_chain ! {
251
249
// `from_type::from, to_type::maxmin_value()`
252
250
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
255
253
if let limit = & args[ 0 ] ;
256
254
// `from_type::from`
257
255
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 ) ;
259
257
260
258
then {
261
259
Some ( ( limit, from_sym) )
@@ -285,34 +283,31 @@ fn get_types_from_cast(expr: &Expr, func: Symbol, types: &[Symbol]) -> Option<(S
285
283
}
286
284
287
285
/// 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 > {
289
287
if_chain ! {
290
288
if let QPath :: TypeRelative ( ref ty, ref path) = & path;
291
- if path. ident. name == function;
289
+ if path. ident. name. as_str ( ) == function;
292
290
if let TyKind :: Path ( QPath :: Resolved ( None , ref tp) ) = & ty. node;
293
291
if let [ int] = & * tp. segments;
294
- let name = int. ident. name;
295
- if candidates. contains( & name) ;
292
+ let name = & int. ident. name. as_str( ) ;
296
293
297
294
then {
298
- Some ( name)
295
+ candidates . iter ( ) . find ( |c| name == * c ) . cloned ( )
299
296
} else {
300
297
None
301
298
}
302
299
}
303
300
}
304
301
305
302
/// 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 > {
307
304
if_chain ! {
308
305
if let QPath :: Resolved ( _, ref path) = * path;
309
306
if let [ ty] = & * path. segments;
307
+ let name = & ty. ident. name. as_str( ) ;
310
308
311
309
then {
312
- INTS
313
- . iter( )
314
- . find( |c| ty. ident. name == * * c)
315
- . cloned( )
310
+ INTS . iter( ) . find( |c| name == * c) . cloned( )
316
311
} else {
317
312
None
318
313
}
@@ -328,27 +323,19 @@ fn transpose<T, U>(lhs: Option<T>, rhs: Option<U>) -> Option<(T, U)> {
328
323
}
329
324
330
325
/// 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 ) > {
332
327
match op. node {
333
328
BinOpKind :: Le => Some ( ( left, right) ) ,
334
329
BinOpKind :: Ge => Some ( ( right, left) ) ,
335
330
_ => None ,
336
331
}
337
332
}
338
333
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