| use clippy_utils::consts::ConstEvalCtxt; | |
| use clippy_utils::consts::Constant::{F32, F64}; | |
| use clippy_utils::diagnostics::span_lint_and_then; | |
| use clippy_utils::sugg::Sugg; | |
| use rustc_errors::Applicability; | |
| use rustc_hir::Expr; | |
| use rustc_lint::LateContext; | |
| use rustc_span::SyntaxContext; | |
| use std::f32::consts as f32_consts; | |
| use std::f64::consts as f64_consts; | |
| use super::SUBOPTIMAL_FLOPS; | |
| // Returns the specialized log method for a given base if base is constant | |
| // and is one of 2, 10 and e | |
| fn get_specialized_log_method(cx: &LateContext<'_>, base: &Expr<'_>, ctxt: SyntaxContext) -> Option<&'static str> { | |
| if let Some(value) = ConstEvalCtxt::new(cx).eval_local(base, ctxt) { | |
| if F32(2.0) == value || F64(2.0) == value { | |
| return Some("log2"); | |
| } else if F32(10.0) == value || F64(10.0) == value { | |
| return Some("log10"); | |
| } else if F32(f32_consts::E) == value || F64(f64_consts::E) == value { | |
| return Some("ln"); | |
| } | |
| } | |
| None | |
| } | |
| pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, receiver: &Expr<'_>, args: &[Expr<'_>]) { | |
| if let Some(method) = get_specialized_log_method(cx, &args[0], expr.span.ctxt()) { | |
| span_lint_and_then( | |
| cx, | |
| SUBOPTIMAL_FLOPS, | |
| expr.span, | |
| "logarithm for bases 2, 10 and e can be computed more accurately", | |
| |diag| { | |
| let mut app = Applicability::MachineApplicable; | |
| let recv = Sugg::hir_with_applicability(cx, receiver, "_", &mut app).maybe_paren(); | |
| diag.span_suggestion(expr.span, "consider using", format!("{recv}.{method}()"), app); | |
| }, | |
| ); | |
| } | |
| } |