|
| 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