@@ -51,7 +51,9 @@ declare_clippy_lint! {
51
51
52
52
#[ derive( Copy , Clone , Default ) ]
53
53
pub 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 > ,
55
57
}
56
58
57
59
impl LintPass for Arithmetic {
@@ -62,9 +64,15 @@ impl LintPass for Arithmetic {
62
64
63
65
impl < ' a , ' tcx > LateLintPass < ' a , ' tcx > for Arithmetic {
64
66
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 ( ) {
66
68
return ;
67
69
}
70
+
71
+ if let Some ( span) = self . const_span {
72
+ if span. contains ( expr. span ) {
73
+ return ;
74
+ }
75
+ }
68
76
match expr. node {
69
77
hir:: ExprKind :: Binary ( ref op, ref l, ref r) => {
70
78
match op. node {
@@ -86,29 +94,60 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Arithmetic {
86
94
let ( l_ty, r_ty) = ( cx. tables . expr_ty ( l) , cx. tables . expr_ty ( r) ) ;
87
95
if l_ty. is_integral ( ) && r_ty. is_integral ( ) {
88
96
span_lint ( cx, INTEGER_ARITHMETIC , expr. span , "integer arithmetic detected" ) ;
89
- self . span = Some ( expr. span ) ;
97
+ self . expr_span = Some ( expr. span ) ;
90
98
} else if l_ty. is_floating_point ( ) && r_ty. is_floating_point ( ) {
91
99
span_lint ( cx, FLOAT_ARITHMETIC , expr. span , "floating-point arithmetic detected" ) ;
92
- self . span = Some ( expr. span ) ;
100
+ self . expr_span = Some ( expr. span ) ;
93
101
}
94
102
} ,
95
103
hir:: ExprKind :: Unary ( hir:: UnOp :: UnNeg , ref arg) => {
96
104
let ty = cx. tables . expr_ty ( arg) ;
97
105
if ty. is_integral ( ) {
98
106
span_lint ( cx, INTEGER_ARITHMETIC , expr. span , "integer arithmetic detected" ) ;
99
- self . span = Some ( expr. span ) ;
107
+ self . expr_span = Some ( expr. span ) ;
100
108
} else if ty. is_floating_point ( ) {
101
109
span_lint ( cx, FLOAT_ARITHMETIC , expr. span , "floating-point arithmetic detected" ) ;
102
- self . span = Some ( expr. span ) ;
110
+ self . expr_span = Some ( expr. span ) ;
103
111
}
104
112
} ,
105
113
_ => ( ) ,
106
114
}
107
115
}
108
116
109
117
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
+ }
112
150
}
151
+ self . const_span = None ;
113
152
}
114
153
}
0 commit comments