|
| 1 | +use std::ops::ControlFlow; |
| 2 | + |
1 | 3 | use clippy_utils::consts::{constant, Constant};
|
2 | 4 | use clippy_utils::diagnostics::span_lint;
|
| 5 | +use clippy_utils::visitors::{for_each_expr, Descend}; |
3 | 6 | use clippy_utils::{method_chain_args, sext};
|
4 | 7 | use rustc_hir::{BinOpKind, Expr, ExprKind};
|
5 | 8 | use rustc_lint::LateContext;
|
@@ -216,34 +219,37 @@ fn expr_muldiv_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign {
|
216 | 219 | ///
|
217 | 220 | /// Expressions using other operators are preserved, so we can try to evaluate them later.
|
218 | 221 | fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> {
|
219 |
| - #[inline] |
220 |
| - fn collect_operands<'e>(expr: &'e Expr<'e>, operands: &mut Vec<&'e Expr<'e>>) { |
221 |
| - match expr.kind { |
222 |
| - ExprKind::Binary(op, lhs, rhs) => { |
| 222 | + let mut res = vec![]; |
| 223 | + |
| 224 | + for_each_expr(expr, |sub_expr| { |
| 225 | + match sub_expr.kind { |
| 226 | + ExprKind::Binary(op, lhs, _rhs) => { |
223 | 227 | if matches!(op.node, BinOpKind::Mul | BinOpKind::Div) {
|
224 | 228 | // For binary operators which both contribute to the sign of the result,
|
225 | 229 | // collect all their operands, recursively. This ignores overflow.
|
226 |
| - collect_operands(lhs, operands); |
227 |
| - collect_operands(rhs, operands); |
| 230 | + ControlFlow::Continue(Descend::Yes) |
228 | 231 | } else if matches!(op.node, BinOpKind::Rem) {
|
229 | 232 | // For binary operators where the left hand side determines the sign of the result,
|
230 | 233 | // only collect that side, recursively. Overflow panics, so this always holds.
|
231 | 234 | //
|
232 | 235 | // > Given remainder = dividend % divisor, the remainder will have the same sign as the dividend
|
233 | 236 | // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
|
234 |
| - collect_operands(lhs, operands); |
| 237 | + res.push(lhs); |
| 238 | + ControlFlow::Break(()) |
235 | 239 | } else {
|
236 | 240 | // The sign of the result of other binary operators depends on the values of the operands,
|
237 | 241 | // so try to evaluate the expression.
|
238 |
| - operands.push(expr); |
| 242 | + res.push(expr); |
| 243 | + ControlFlow::Continue(Descend::No) |
239 | 244 | }
|
240 | 245 | },
|
241 | 246 | // For other expressions, including unary operators and constants, try to evaluate the expression.
|
242 |
| - _ => operands.push(expr), |
| 247 | + _ => { |
| 248 | + res.push(expr); |
| 249 | + ControlFlow::Continue(Descend::No) |
| 250 | + }, |
243 | 251 | }
|
244 |
| - } |
| 252 | + }); |
245 | 253 |
|
246 |
| - let mut res = vec![]; |
247 |
| - collect_operands(expr, &mut res); |
248 | 254 | res
|
249 | 255 | }
|
0 commit comments