blob: 49f8ba4bf8256063c302cc9cf58870ceaf6201bb [file] [log] [blame] [edit]
use clippy_utils::consts::ConstEvalCtxt;
use clippy_utils::consts::Constant::Int;
use clippy_utils::diagnostics::span_lint_and_sugg;
use clippy_utils::sugg::Sugg;
use clippy_utils::{eq_expr_value, sym};
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment};
use rustc_lint::LateContext;
use rustc_span::source_map::Spanned;
use super::IMPRECISE_FLOPS;
pub(super) fn detect(cx: &LateContext<'_>, receiver: &Expr<'_>, app: &mut Applicability) -> Option<String> {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
add_lhs,
add_rhs,
) = receiver.kind
{
// check if expression of the form x * x + y * y
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
},
lmul_lhs,
lmul_rhs,
) = add_lhs.kind
&& let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
},
rmul_lhs,
rmul_rhs,
) = add_rhs.kind
&& eq_expr_value(cx, lmul_lhs, lmul_rhs)
&& eq_expr_value(cx, rmul_lhs, rmul_rhs)
{
return Some(format!(
"{}.hypot({})",
Sugg::hir_with_applicability(cx, lmul_lhs, "_", app).maybe_paren(),
Sugg::hir_with_applicability(cx, rmul_lhs, "_", app)
));
}
// check if expression of the form x.powi(2) + y.powi(2)
if let ExprKind::MethodCall(PathSegment { ident: lmethod, .. }, largs_0, [largs_1, ..], _) = add_lhs.kind
&& let ExprKind::MethodCall(PathSegment { ident: rmethod, .. }, rargs_0, [rargs_1, ..], _) = add_rhs.kind
&& lmethod.name == sym::powi
&& rmethod.name == sym::powi
&& let ecx = ConstEvalCtxt::new(cx)
&& let Some(lvalue) = ecx.eval(largs_1)
&& let Some(rvalue) = ecx.eval(rargs_1)
&& Int(2) == lvalue
&& Int(2) == rvalue
{
return Some(format!(
"{}.hypot({})",
Sugg::hir_with_applicability(cx, largs_0, "_", app).maybe_paren(),
Sugg::hir_with_applicability(cx, rargs_0, "_", app)
));
}
}
None
}
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>) {
let mut app = Applicability::MachineApplicable;
if let Some(message) = detect(cx, receiver, &mut app) {
span_lint_and_sugg(
cx,
IMPRECISE_FLOPS,
expr.span,
"hypotenuse can be computed more accurately",
"consider using",
message,
app,
);
}
}