9
9
10
10
11
11
use crate :: utils:: span_lint;
12
- use crate :: rustc:: hir;
12
+ use crate :: rustc:: hir:: { self , Item , ItemKind } ;
13
13
use crate :: rustc:: lint:: { LateContext , LateLintPass , LintArray , LintPass } ;
14
14
use crate :: rustc:: { declare_tool_lint, lint_array} ;
15
15
use crate :: syntax:: source_map:: Span ;
@@ -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,47 @@ 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_item ( & mut self , _: & LateContext < ' _ , ' _ > , item : & Item ) {
124
+ match item. node {
125
+ ItemKind :: Enum ( ..)
126
+ | ItemKind :: Const ( ..)
127
+ | ItemKind :: Static ( ..) => self . const_span = Some ( item. span ) ,
128
+ _ => ( ) ,
129
+ }
130
+ }
131
+
132
+ fn check_item_post ( & mut self , _: & LateContext < ' _ , ' _ > , item : & Item ) {
133
+ match item. node {
134
+ ItemKind :: Enum ( ..)
135
+ | ItemKind :: Const ( ..)
136
+ | ItemKind :: Static ( ..) => self . const_span = None ,
137
+ _ => ( ) ,
112
138
}
113
139
}
114
140
}
0 commit comments