@@ -56,7 +56,15 @@ fn should_lint<'cx>(cx: &LateContext<'cx>, cast_op: &Expr<'_>, cast_from: Ty<'cx
56
56
}
57
57
58
58
// Don't lint if `cast_op` is known to be positive, ignoring overflow.
59
- expr_sign ( cx, cast_op, cast_from) == Sign :: ZeroOrPositive
59
+ if let Sign :: ZeroOrPositive = expr_sign ( cx, cast_op, cast_from) {
60
+ return false ;
61
+ }
62
+
63
+ if let Sign :: ZeroOrPositive = expr_muldiv_sign ( cx, cast_op) {
64
+ return false ;
65
+ }
66
+
67
+ true
60
68
} ,
61
69
62
70
( false , true ) => !cast_to. is_signed ( ) ,
@@ -134,32 +142,7 @@ fn expr_sign<'cx>(cx: &LateContext<'cx>, expr: &Expr<'_>, ty: impl Into<Option<T
134
142
}
135
143
}
136
144
137
- let mut uncertain_count = 0 ;
138
- let mut negative_count = 0 ;
139
-
140
- // Peel off possible binary expressions, for example:
141
- // x * x / y => [x, x, y]
142
- // a % b => [a]
143
- let exprs = exprs_with_muldiv_binop_peeled ( expr) ;
144
- for expr in exprs {
145
- match expr_sign ( cx, expr, None ) {
146
- Sign :: Negative => negative_count += 1 ,
147
- Sign :: Uncertain => uncertain_count += 1 ,
148
- Sign :: ZeroOrPositive => ( ) ,
149
- } ;
150
- }
151
-
152
- // A mul/div is:
153
- // - uncertain if there are any uncertain values (because they could be negative or positive),
154
- // - negative if there are an odd number of negative values,
155
- // - positive or zero otherwise.
156
- if uncertain_count > 0 {
157
- Sign :: Uncertain
158
- } else if negative_count % 2 == 1 {
159
- Sign :: Negative
160
- } else {
161
- Sign :: ZeroOrPositive
162
- }
145
+ Sign :: Uncertain
163
146
}
164
147
165
148
/// Return the sign of the `pow` call's result, ignoring overflow.
@@ -195,13 +178,46 @@ fn pow_call_result_sign(cx: &LateContext<'_>, base: &Expr<'_>, exponent: &Expr<'
195
178
}
196
179
}
197
180
181
+ /// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`],
182
+ /// which the result could always be positive under certain conditions, ignoring overflow.
183
+ ///
184
+ /// Returns the sign of the list of peeled expressions.
185
+ fn expr_muldiv_sign ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> Sign {
186
+ let mut uncertain_count = 0 ;
187
+ let mut negative_count = 0 ;
188
+
189
+ // Peel off possible binary expressions, for example:
190
+ // x * x / y => [x, x, y]
191
+ // a % b => [a]
192
+ let exprs = exprs_with_muldiv_binop_peeled ( expr) ;
193
+ for expr in exprs {
194
+ match expr_sign ( cx, expr, None ) {
195
+ Sign :: Negative => negative_count += 1 ,
196
+ Sign :: Uncertain => uncertain_count += 1 ,
197
+ Sign :: ZeroOrPositive => ( ) ,
198
+ } ;
199
+ }
200
+
201
+ // A mul/div is:
202
+ // - uncertain if there are any uncertain values (because they could be negative or positive),
203
+ // - negative if there are an odd number of negative values,
204
+ // - positive or zero otherwise.
205
+ if uncertain_count > 0 {
206
+ Sign :: Uncertain
207
+ } else if negative_count % 2 == 1 {
208
+ Sign :: Negative
209
+ } else {
210
+ Sign :: ZeroOrPositive
211
+ }
212
+ }
213
+
198
214
/// Peels binary operators such as [`BinOpKind::Mul`], [`BinOpKind::Div`] or [`BinOpKind::Rem`],
199
215
/// which the result could always be positive under certain conditions, ignoring overflow.
200
216
///
201
217
/// Expressions using other operators are preserved, so we can try to evaluate them later.
202
- fn exprs_with_muldiv_binop_peeled < ' a > ( expr : & ' a Expr < ' _ > ) -> Vec < & ' a Expr < ' a > > {
218
+ fn exprs_with_muldiv_binop_peeled < ' e > ( expr : & ' e Expr < ' _ > ) -> Vec < & ' e Expr < ' e > > {
203
219
#[ inline]
204
- fn collect_operands < ' a > ( expr : & ' a Expr < ' a > , operands : & mut Vec < & ' a Expr < ' a > > ) {
220
+ fn collect_operands < ' e > ( expr : & ' e Expr < ' e > , operands : & mut Vec < & ' e Expr < ' e > > ) {
205
221
match expr. kind {
206
222
ExprKind :: Binary ( op, lhs, rhs) => {
207
223
if matches ! ( op. node, BinOpKind :: Mul | BinOpKind :: Div ) {
0 commit comments