33use std:: borrow:: Cow ;
44use std:: cmp:: Ordering ;
55use std:: collections:: BTreeMap ;
6- use std:: fmt:: Display ;
76
87use if_chain:: if_chain;
98use rustc_ast:: { FloatTy , IntTy , LitFloatType , LitIntType , LitKind , UintTy } ;
@@ -12,7 +11,7 @@ use rustc_hir as hir;
1211use rustc_hir:: intravisit:: { walk_body, walk_expr, walk_ty, FnKind , NestedVisitorMap , Visitor } ;
1312use rustc_hir:: {
1413 BinOpKind , Block , Body , Expr , ExprKind , FnDecl , FnRetTy , FnSig , GenericArg , GenericParamKind , HirId , ImplItem ,
15- ImplItemKind , Item , ItemKind , Lifetime , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt , StmtKind ,
14+ ImplItemKind , Item , ItemKind , Lifetime , Lit , Local , MatchSource , MutTy , Mutability , Node , QPath , Stmt , StmtKind ,
1615 TraitFn , TraitItem , TraitItemKind , TyKind , UnOp ,
1716} ;
1817use rustc_lint:: { LateContext , LateLintPass , LintContext } ;
@@ -1225,7 +1224,8 @@ declare_clippy_lint! {
12251224}
12261225
12271226declare_clippy_lint ! {
1228- /// **What it does:** Checks for casts to the same type.
1227+ /// **What it does:** Checks for casts to the same type, casts of int literals to integer types
1228+ /// and casts of float literals to float types.
12291229 ///
12301230 /// **Why is this bad?** It's just unnecessary.
12311231 ///
@@ -1234,6 +1234,7 @@ declare_clippy_lint! {
12341234 /// **Example:**
12351235 /// ```rust
12361236 /// let _ = 2i32 as i32;
1237+ /// let _ = 0.5 as f32;
12371238 /// ```
12381239 pub UNNECESSARY_CAST ,
12391240 complexity,
@@ -1599,7 +1600,9 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
15991600 if let ExprKind :: Cast ( ref ex, _) = expr. kind {
16001601 let ( cast_from, cast_to) = ( cx. typeck_results ( ) . expr_ty ( ex) , cx. typeck_results ( ) . expr_ty ( expr) ) ;
16011602 lint_fn_to_numeric_cast ( cx, expr, ex, cast_from, cast_to) ;
1602- if let ExprKind :: Lit ( ref lit) = ex. kind {
1603+ if let Some ( lit) = get_numeric_literal ( ex) {
1604+ let literal_str = snippet_opt ( cx, lit. span ) . unwrap_or_default ( ) ;
1605+
16031606 if_chain ! {
16041607 if let LitKind :: Int ( n, _) = lit. node;
16051608 if let Some ( src) = snippet_opt( cx, lit. span) ;
@@ -1609,25 +1612,19 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
16091612 let to_nbits = fp_ty_mantissa_nbits( cast_to) ;
16101613 if from_nbits != 0 && to_nbits != 0 && from_nbits <= to_nbits && num_lit. is_decimal( ) ;
16111614 then {
1612- show_unnecessary_cast( cx, expr, n , cast_from, cast_to) ;
1615+ show_unnecessary_cast( cx, expr, num_lit . integer , cast_from, cast_to) ;
16131616 return ;
16141617 }
16151618 }
16161619
16171620 match lit. node {
1618- LitKind :: Int ( num, LitIntType :: Unsuffixed ) if cast_to. is_integral ( ) => {
1619- show_unnecessary_cast ( cx, expr, num, cast_from, cast_to) ;
1620- return ;
1621+ LitKind :: Int ( _, LitIntType :: Unsuffixed ) if cast_to. is_integral ( ) => {
1622+ show_unnecessary_cast ( cx, expr, & literal_str, cast_from, cast_to) ;
16211623 } ,
1622- LitKind :: Float ( num, LitFloatType :: Unsuffixed ) if cast_to. is_floating_point ( ) => {
1623- show_unnecessary_cast ( cx, expr, num, cast_from, cast_to) ;
1624- return ;
1624+ LitKind :: Float ( _, LitFloatType :: Unsuffixed ) if cast_to. is_floating_point ( ) => {
1625+ show_unnecessary_cast ( cx, expr, & literal_str, cast_from, cast_to) ;
16251626 } ,
1626- _ => ( ) ,
1627- } ;
1628-
1629- match lit. node {
1630- LitKind :: Int ( _, LitIntType :: Unsuffixed ) | LitKind :: Float ( _, LitFloatType :: Unsuffixed ) => { } ,
1627+ LitKind :: Int ( _, LitIntType :: Unsuffixed ) | LitKind :: Float ( _, LitFloatType :: Unsuffixed ) => ( ) ,
16311628 _ => {
16321629 if cast_from. kind ( ) == cast_to. kind ( ) && !in_external_macro ( cx. sess ( ) , expr. span ) {
16331630 span_lint (
@@ -1652,21 +1649,29 @@ impl<'tcx> LateLintPass<'tcx> for Casts {
16521649 }
16531650}
16541651
1655- fn show_unnecessary_cast < Num : Display > (
1656- cx : & LateContext < ' _ > ,
1657- expr : & Expr < ' _ > ,
1658- num : Num ,
1659- cast_from : Ty < ' _ > ,
1660- cast_to : Ty < ' _ > ,
1661- ) {
1652+ fn get_numeric_literal < ' e > ( expr : & ' e Expr < ' e > ) -> Option < & ' e Lit > {
1653+ match expr. kind {
1654+ ExprKind :: Lit ( ref lit) => Some ( lit) ,
1655+ ExprKind :: Unary ( UnOp :: UnNeg , e) => {
1656+ if let ExprKind :: Lit ( ref lit) = e. kind {
1657+ Some ( lit)
1658+ } else {
1659+ None
1660+ }
1661+ } ,
1662+ _ => None ,
1663+ }
1664+ }
1665+
1666+ fn show_unnecessary_cast ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > , literal_str : & str , cast_from : Ty < ' _ > , cast_to : Ty < ' _ > ) {
16621667 let literal_kind_name = if cast_from. is_integral ( ) { "integer" } else { "float" } ;
16631668 span_lint_and_sugg (
16641669 cx,
16651670 UNNECESSARY_CAST ,
16661671 expr. span ,
16671672 & format ! ( "casting {} literal to `{}` is unnecessary" , literal_kind_name, cast_to) ,
16681673 "try" ,
1669- format ! ( "{}_{}" , num , cast_to) ,
1674+ format ! ( "{}_{}" , literal_str , cast_to) ,
16701675 Applicability :: MachineApplicable ,
16711676 ) ;
16721677}
0 commit comments