blob: 4c9aa96b5042af661f422e8290bf008a9ff94c42 [file] [log] [blame] [edit]
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::consts::Constant::{F32, F64};
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind};
use rustc_lint::LateContext;
use rustc_span::source_map::Spanned;
use super::IMPRECISE_FLOPS;
// TODO: Lint expressions of the form `(x + y).ln()` where y > 1 and
// suggest usage of `(x + (y - 1)).ln_1p()` instead
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
lhs,
rhs,
) = receiver.kind
{
let ecx = ConstEvalCtxt::new(cx);
let recv = match (ecx.eval(lhs), ecx.eval(rhs)) {
(Some(value), _) if F32(1.0) == value || F64(1.0) == value => rhs,
(_, Some(value)) if F32(1.0) == value || F64(1.0) == value => lhs,
_ => return,
};
span_lint_and_then(
cx,
IMPRECISE_FLOPS,
expr.span,
"ln(1 + x) can be computed more accurately",
|diag| {
let mut app = Applicability::MachineApplicable;
let recv = super::lib::prepare_receiver_sugg(cx, recv, &mut app);
diag.span_suggestion(expr.span, "consider using", format!("{recv}.ln_1p()"), app);
},
);
}
}