Skip to content

Commit 68ce04f

Browse files
committed
Use the visitor pattern instead of recusive functions
1 parent 5ae684b commit 68ce04f

File tree

1 file changed

+18
-12
lines changed

1 file changed

+18
-12
lines changed

clippy_lints/src/casts/cast_sign_loss.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use std::ops::ControlFlow;
2+
13
use clippy_utils::consts::{constant, Constant};
24
use clippy_utils::diagnostics::span_lint;
5+
use clippy_utils::visitors::{for_each_expr, Descend};
36
use clippy_utils::{method_chain_args, sext};
47
use rustc_hir::{BinOpKind, Expr, ExprKind};
58
use rustc_lint::LateContext;
@@ -216,34 +219,37 @@ fn expr_muldiv_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign {
216219
///
217220
/// Expressions using other operators are preserved, so we can try to evaluate them later.
218221
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) => {
223227
if matches!(op.node, BinOpKind::Mul | BinOpKind::Div) {
224228
// For binary operators which both contribute to the sign of the result,
225229
// collect all their operands, recursively. This ignores overflow.
226-
collect_operands(lhs, operands);
227-
collect_operands(rhs, operands);
230+
ControlFlow::Continue(Descend::Yes)
228231
} else if matches!(op.node, BinOpKind::Rem) {
229232
// For binary operators where the left hand side determines the sign of the result,
230233
// only collect that side, recursively. Overflow panics, so this always holds.
231234
//
232235
// > Given remainder = dividend % divisor, the remainder will have the same sign as the dividend
233236
// 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(())
235239
} else {
236240
// The sign of the result of other binary operators depends on the values of the operands,
237241
// so try to evaluate the expression.
238-
operands.push(expr);
242+
res.push(expr);
243+
ControlFlow::Continue(Descend::No)
239244
}
240245
},
241246
// 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+
},
243251
}
244-
}
252+
});
245253

246-
let mut res = vec![];
247-
collect_operands(expr, &mut res);
248254
res
249255
}

0 commit comments

Comments
 (0)