@@ -51,7 +51,9 @@ declare_clippy_lint! {
5151
5252#[ derive( Copy , Clone , Default ) ]
5353pub struct Arithmetic {
54- span : Option < Span > ,
54+ expr_span : Option < Span > ,
55+ /// This field is used to check whether expressions are constants, such as in enum discriminants and consts
56+ const_span : Option < Span > ,
5557}
5658
5759impl LintPass for Arithmetic {
@@ -62,9 +64,15 @@ impl LintPass for Arithmetic {
6264
6365impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for Arithmetic {
6466 fn check_expr ( & mut self , cx : & LateContext < ' a , ' tcx > , expr : & ' tcx hir:: Expr ) {
65- if self . span . is_some ( ) {
67+ if self . expr_span . is_some ( ) {
6668 return ;
6769 }
70+
71+ if let Some ( span) = self . const_span {
72+ if span. contains ( expr. span ) {
73+ return ;
74+ }
75+ }
6876 match expr. node {
6977 hir:: ExprKind :: Binary ( ref op, ref l, ref r) => {
7078 match op. node {
@@ -86,29 +94,60 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
8694 let ( l_ty, r_ty) = ( cx. tables . expr_ty ( l) , cx. tables . expr_ty ( r) ) ;
8795 if l_ty. is_integral ( ) && r_ty. is_integral ( ) {
8896 span_lint ( cx, INTEGER_ARITHMETIC , expr. span , "integer arithmetic detected" ) ;
89- self . span = Some ( expr. span ) ;
97+ self . expr_span = Some ( expr. span ) ;
9098 } else if l_ty. is_floating_point ( ) && r_ty. is_floating_point ( ) {
9199 span_lint ( cx, FLOAT_ARITHMETIC , expr. span , "floating-point arithmetic detected" ) ;
92- self . span = Some ( expr. span ) ;
100+ self . expr_span = Some ( expr. span ) ;
93101 }
94102 } ,
95103 hir:: ExprKind :: Unary ( hir:: UnOp :: UnNeg , ref arg) => {
96104 let ty = cx. tables . expr_ty ( arg) ;
97105 if ty. is_integral ( ) {
98106 span_lint ( cx, INTEGER_ARITHMETIC , expr. span , "integer arithmetic detected" ) ;
99- self . span = Some ( expr. span ) ;
107+ self . expr_span = Some ( expr. span ) ;
100108 } else if ty. is_floating_point ( ) {
101109 span_lint ( cx, FLOAT_ARITHMETIC , expr. span , "floating-point arithmetic detected" ) ;
102- self . span = Some ( expr. span ) ;
110+ self . expr_span = Some ( expr. span ) ;
103111 }
104112 } ,
105113 _ => ( ) ,
106114 }
107115 }
108116
109117 fn check_expr_post ( & mut self , _: & LateContext < ' a , ' tcx > , expr : & ' tcx hir:: Expr ) {
110- if Some ( expr. span ) == self . span {
111- self . span = None ;
118+ if Some ( expr. span ) == self . expr_span {
119+ self . expr_span = None ;
120+ }
121+ }
122+
123+ fn check_body ( & mut self , cx : & LateContext < ' _ , ' _ > , body : & hir:: Body ) {
124+ let body_owner = cx. tcx . hir . body_owner ( body. id ( ) ) ;
125+
126+ match cx. tcx . hir . body_owner_kind ( body_owner) {
127+ hir:: BodyOwnerKind :: Static ( _)
128+ | hir:: BodyOwnerKind :: Const => {
129+ let body_span = cx. tcx . hir . span ( body_owner) ;
130+
131+ if let Some ( span) = self . const_span {
132+ if span. contains ( body_span) {
133+ return ;
134+ }
135+ }
136+ self . const_span = Some ( body_span) ;
137+ }
138+ hir:: BodyOwnerKind :: Fn => ( ) ,
139+ }
140+ }
141+
142+ fn check_body_post ( & mut self , cx : & LateContext < ' _ , ' _ > , body : & hir:: Body ) {
143+ let body_owner = cx. tcx . hir . body_owner ( body. id ( ) ) ;
144+ let body_span = cx. tcx . hir . span ( body_owner) ;
145+
146+ if let Some ( span) = self . const_span {
147+ if span. contains ( body_span) {
148+ return ;
149+ }
112150 }
151+ self . const_span = None ;
113152 }
114153}
0 commit comments