diff options
| -rw-r--r-- | clippy_lints/src/casts/cast_sign_loss.rs | 30 |
1 files changed, 18 insertions, 12 deletions
diff --git a/clippy_lints/src/casts/cast_sign_loss.rs b/clippy_lints/src/casts/cast_sign_loss.rs index db7121928fe..20a7cbd4a1b 100644 --- a/clippy_lints/src/casts/cast_sign_loss.rs +++ b/clippy_lints/src/casts/cast_sign_loss.rs @@ -1,5 +1,8 @@ +use std::ops::ControlFlow; + use clippy_utils::consts::{constant, Constant}; use clippy_utils::diagnostics::span_lint; +use clippy_utils::visitors::{for_each_expr, Descend}; use clippy_utils::{method_chain_args, sext}; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -216,34 +219,37 @@ fn expr_muldiv_sign(cx: &LateContext<'_>, expr: &Expr<'_>) -> Sign { /// /// Expressions using other operators are preserved, so we can try to evaluate them later. fn exprs_with_muldiv_binop_peeled<'e>(expr: &'e Expr<'_>) -> Vec<&'e Expr<'e>> { - #[inline] - fn collect_operands<'e>(expr: &'e Expr<'e>, operands: &mut Vec<&'e Expr<'e>>) { - match expr.kind { - ExprKind::Binary(op, lhs, rhs) => { + let mut res = vec![]; + + for_each_expr(expr, |sub_expr| { + match sub_expr.kind { + ExprKind::Binary(op, lhs, _rhs) => { if matches!(op.node, BinOpKind::Mul | BinOpKind::Div) { // For binary operators which both contribute to the sign of the result, // collect all their operands, recursively. This ignores overflow. - collect_operands(lhs, operands); - collect_operands(rhs, operands); + ControlFlow::Continue(Descend::Yes) } else if matches!(op.node, BinOpKind::Rem) { // For binary operators where the left hand side determines the sign of the result, // only collect that side, recursively. Overflow panics, so this always holds. // // > Given remainder = dividend % divisor, the remainder will have the same sign as the dividend // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators - collect_operands(lhs, operands); + res.push(lhs); + ControlFlow::Break(()) } else { // The sign of the result of other binary operators depends on the values of the operands, // so try to evaluate the expression. - operands.push(expr); + res.push(expr); + ControlFlow::Continue(Descend::No) } }, // For other expressions, including unary operators and constants, try to evaluate the expression. - _ => operands.push(expr), + _ => { + res.push(expr); + ControlFlow::Continue(Descend::No) + }, } - } + }); - let mut res = vec![]; - collect_operands(expr, &mut res); res } |
