@@ -3,26 +3,26 @@ mod cast_possible_truncation;
3
3
mod cast_possible_wrap;
4
4
mod cast_precision_loss;
5
5
mod cast_sign_loss;
6
+ mod unnecessary_cast;
6
7
mod utils;
7
8
8
9
use std:: borrow:: Cow ;
9
10
10
11
use if_chain:: if_chain;
11
- use rustc_ast:: { LitFloatType , LitIntType , LitKind } ;
12
+ use rustc_ast:: LitKind ;
12
13
use rustc_errors:: Applicability ;
13
- use rustc_hir:: { Expr , ExprKind , GenericArg , Lit , MutTy , Mutability , TyKind , UnOp } ;
14
+ use rustc_hir:: { Expr , ExprKind , GenericArg , MutTy , Mutability , TyKind , UnOp } ;
14
15
use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
15
16
use rustc_middle:: lint:: in_external_macro;
16
- use rustc_middle:: ty:: { self , FloatTy , InferTy , Ty , TypeAndMut , UintTy } ;
17
+ use rustc_middle:: ty:: { self , Ty , TypeAndMut , UintTy } ;
17
18
use rustc_semver:: RustcVersion ;
18
19
use rustc_session:: { declare_lint_pass, declare_tool_lint, impl_lint_pass} ;
19
20
use rustc_span:: symbol:: sym;
20
21
use rustc_target:: abi:: LayoutOf ;
21
22
22
23
use crate :: utils:: sugg:: Sugg ;
23
24
use crate :: utils:: {
24
- is_hir_ty_cfg_dependant, meets_msrv, numeric_literal:: NumericLiteral , snippet_opt, snippet_with_applicability,
25
- span_lint, span_lint_and_sugg, span_lint_and_then,
25
+ is_hir_ty_cfg_dependant, meets_msrv, snippet_with_applicability, span_lint, span_lint_and_sugg, span_lint_and_then,
26
26
} ;
27
27
28
28
use utils:: int_ty_to_nbits;
@@ -284,72 +284,25 @@ fn is_c_void(cx: &LateContext<'_>, ty: Ty<'_>) -> bool {
284
284
false
285
285
}
286
286
287
- /// Returns the mantissa bits wide of a fp type.
288
- /// Will return 0 if the type is not a fp
289
- fn fp_ty_mantissa_nbits ( typ : Ty < ' _ > ) -> u32 {
290
- match typ. kind ( ) {
291
- ty:: Float ( FloatTy :: F32 ) => 23 ,
292
- ty:: Float ( FloatTy :: F64 ) | ty:: Infer ( InferTy :: FloatVar ( _) ) => 52 ,
293
- _ => 0 ,
294
- }
295
- }
296
-
297
287
impl < ' tcx > LateLintPass < ' tcx > for Casts {
298
288
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
299
289
if expr. span . from_expansion ( ) {
300
290
return ;
301
291
}
302
- if let ExprKind :: Cast ( ref ex , cast_to) = expr. kind {
292
+ if let ExprKind :: Cast ( ref cast_expr , cast_to) = expr. kind {
303
293
if is_hir_ty_cfg_dependant ( cx, cast_to) {
304
294
return ;
305
295
}
306
- let ( cast_from, cast_to) = ( cx. typeck_results ( ) . expr_ty ( ex) , cx. typeck_results ( ) . expr_ty ( expr) ) ;
307
- lint_fn_to_numeric_cast ( cx, expr, ex, cast_from, cast_to) ;
308
- if let Some ( lit) = get_numeric_literal ( ex) {
309
- let literal_str = snippet_opt ( cx, ex. span ) . unwrap_or_default ( ) ;
310
-
311
- if_chain ! {
312
- if let LitKind :: Int ( n, _) = lit. node;
313
- if let Some ( src) = snippet_opt( cx, lit. span) ;
314
- if cast_to. is_floating_point( ) ;
315
- if let Some ( num_lit) = NumericLiteral :: from_lit_kind( & src, & lit. node) ;
316
- let from_nbits = 128 - n. leading_zeros( ) ;
317
- let to_nbits = fp_ty_mantissa_nbits( cast_to) ;
318
- if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit. is_decimal( ) ;
319
- then {
320
- let literal_str = if is_unary_neg( ex) { format!( "-{}" , num_lit. integer) } else { num_lit. integer. into( ) } ;
321
- show_unnecessary_cast( cx, expr, & literal_str, cast_from, cast_to) ;
322
- return ;
323
- }
324
- }
325
-
326
- match lit. node {
327
- LitKind :: Int ( _, LitIntType :: Unsuffixed ) if cast_to. is_integral ( ) => {
328
- show_unnecessary_cast ( cx, expr, & literal_str, cast_from, cast_to) ;
329
- } ,
330
- LitKind :: Float ( _, LitFloatType :: Unsuffixed ) if cast_to. is_floating_point ( ) => {
331
- show_unnecessary_cast ( cx, expr, & literal_str, cast_from, cast_to) ;
332
- } ,
333
- LitKind :: Int ( _, LitIntType :: Unsuffixed ) | LitKind :: Float ( _, LitFloatType :: Unsuffixed ) => { } ,
334
- _ => {
335
- if cast_from. kind ( ) == cast_to. kind ( ) && !in_external_macro ( cx. sess ( ) , expr. span ) {
336
- span_lint (
337
- cx,
338
- UNNECESSARY_CAST ,
339
- expr. span ,
340
- & format ! (
341
- "casting to the same type is unnecessary (`{}` -> `{}`)" ,
342
- cast_from, cast_to
343
- ) ,
344
- ) ;
345
- }
346
- } ,
347
- }
348
- }
349
- if cast_from. is_numeric ( ) && cast_to. is_numeric ( ) && !in_external_macro ( cx. sess ( ) , expr. span ) {
350
- lint_numeric_casts ( cx, expr, ex, cast_from, cast_to) ;
351
- }
296
+ let ( cast_from, cast_to) = (
297
+ cx. typeck_results ( ) . expr_ty ( cast_expr) ,
298
+ cx. typeck_results ( ) . expr_ty ( expr) ,
299
+ ) ;
352
300
301
+ if unnecessary_cast:: check ( cx, expr, cast_expr, cast_from, cast_to) {
302
+ return ;
303
+ }
304
+ lint_fn_to_numeric_cast ( cx, expr, cast_expr, cast_from, cast_to) ;
305
+ lint_numeric_casts ( cx, expr, cast_expr, cast_from, cast_to) ;
353
306
lint_cast_ptr_alignment ( cx, expr, cast_from, cast_to) ;
354
307
} else if let ExprKind :: MethodCall ( method_path, _, args, _) = expr. kind {
355
308
if_chain ! {
@@ -368,49 +321,20 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
368
321
}
369
322
}
370
323
371
- fn is_unary_neg ( expr : & Expr < ' _ > ) -> bool {
372
- matches ! ( expr. kind, ExprKind :: Unary ( UnOp :: Neg , _) )
373
- }
374
-
375
- fn get_numeric_literal < ' e > ( expr : & ' e Expr < ' e > ) -> Option < & ' e Lit > {
376
- match expr. kind {
377
- ExprKind :: Lit ( ref lit) => Some ( lit) ,
378
- ExprKind :: Unary ( UnOp :: Neg , e) => {
379
- if let ExprKind :: Lit ( ref lit) = e. kind {
380
- Some ( lit)
381
- } else {
382
- None
383
- }
384
- } ,
385
- _ => None ,
386
- }
387
- }
388
-
389
- fn show_unnecessary_cast ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , literal_str : & str , cast_from : Ty < ' _ > , cast_to : Ty < ' _ > ) {
390
- let literal_kind_name = if cast_from. is_integral ( ) { "integer" } else { "float" } ;
391
- span_lint_and_sugg (
392
- cx,
393
- UNNECESSARY_CAST ,
394
- expr. span ,
395
- & format ! ( "casting {} literal to `{}` is unnecessary" , literal_kind_name, cast_to) ,
396
- "try" ,
397
- format ! ( "{}_{}" , literal_str. trim_end_matches( '.' ) , cast_to) ,
398
- Applicability :: MachineApplicable ,
399
- ) ;
400
- }
401
-
402
324
fn lint_numeric_casts < ' tcx > (
403
325
cx : & LateContext < ' tcx > ,
404
326
expr : & Expr < ' tcx > ,
405
327
cast_op : & Expr < ' _ > ,
406
328
cast_from : Ty < ' tcx > ,
407
329
cast_to : Ty < ' tcx > ,
408
330
) {
409
- cast_possible_truncation:: check ( cx, expr, cast_from, cast_to) ;
410
- cast_possible_wrap:: check ( cx, expr, cast_from, cast_to) ;
411
- cast_precision_loss:: check ( cx, expr, cast_from, cast_to) ;
412
- cast_lossless:: check ( cx, expr, cast_op, cast_from, cast_to) ;
413
- cast_sign_loss:: check ( cx, expr, cast_op, cast_from, cast_to) ;
331
+ if cast_from. is_numeric ( ) && cast_to. is_numeric ( ) && !in_external_macro ( cx. sess ( ) , expr. span ) {
332
+ cast_possible_truncation:: check ( cx, expr, cast_from, cast_to) ;
333
+ cast_possible_wrap:: check ( cx, expr, cast_from, cast_to) ;
334
+ cast_precision_loss:: check ( cx, expr, cast_from, cast_to) ;
335
+ cast_lossless:: check ( cx, expr, cast_op, cast_from, cast_to) ;
336
+ cast_sign_loss:: check ( cx, expr, cast_op, cast_from, cast_to) ;
337
+ }
414
338
}
415
339
416
340
fn lint_cast_ptr_alignment < ' tcx > ( cx : & LateContext < ' tcx > , expr : & Expr < ' _ > , cast_from : Ty < ' tcx > , cast_to : Ty < ' tcx > ) {
0 commit comments