Fix `powi` suggestion and add general improvements

This commit is contained in:
Krishna Sai Veera Reddy 2020-02-22 20:29:22 -08:00
parent 6dacb1aa67
commit bc706e3ba9
1 changed files with 34 additions and 38 deletions

View File

@ -11,7 +11,7 @@ use rustc_lint::{LateContext, LateLintPass};
use rustc_session::{declare_lint_pass, declare_tool_lint}; use rustc_session::{declare_lint_pass, declare_tool_lint};
use std::f32::consts as f32_consts; use std::f32::consts as f32_consts;
use std::f64::consts as f64_consts; use std::f64::consts as f64_consts;
use sugg::Sugg; use sugg::{format_numeric_literal, Sugg};
use syntax::ast; use syntax::ast;
declare_clippy_lint! { declare_clippy_lint! {
@ -159,23 +159,23 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
} }
} }
// Returns an integer if the float constant is a whole number and it // Returns an integer if the float constant is a whole number and it can be
// can be converted to an integer without loss // converted to an integer without loss of precision. For now we only check
// TODO: Add a better check to determine whether the float can be // ranges [-16777215, 16777216) for type f32 as whole number floats outside
// casted without loss // this range are lossy and ambiguous.
#[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_possible_truncation)]
fn get_integer_from_float_constant(value: &Constant) -> Option<i64> { fn get_integer_from_float_constant(value: &Constant) -> Option<i32> {
match value { match value {
F32(num) if (num.trunc() - num).abs() <= std::f32::EPSILON => { F32(num) if num.fract() == 0.0 => {
if *num > -16_777_217.0 && *num < 16_777_217.0 { if (-16_777_215.0..16_777_216.0).contains(num) {
Some(num.round() as i64) Some(num.round() as i32)
} else { } else {
None None
} }
}, },
F64(num) if (num.trunc() - num).abs() <= std::f64::EPSILON => { F64(num) if num.fract() == 0.0 => {
if *num > -9_007_199_254_740_993.0 && *num < 9_007_199_254_740_993.0 { if (-2_147_483_648.0..2_147_483_648.0).contains(num) {
Some(num.round() as i64) Some(num.round() as i32)
} else { } else {
None None
} }
@ -187,15 +187,13 @@ fn get_integer_from_float_constant(value: &Constant) -> Option<i64> {
fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) { fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
// Check receiver // Check receiver
if let Some((value, _)) = constant(cx, cx.tables, &args[0]) { if let Some((value, _)) = constant(cx, cx.tables, &args[0]) {
let method; let method = if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
"exp"
if F32(f32_consts::E) == value || F64(f64_consts::E) == value {
method = "exp";
} else if F32(2.0) == value || F64(2.0) == value { } else if F32(2.0) == value || F64(2.0) == value {
method = "exp2"; "exp2"
} else { } else {
return; return;
} };
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
@ -210,30 +208,28 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
// Check argument // Check argument
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) { if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
let help; let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
let method; (
"square-root of a number can be computed more efficiently and accurately",
if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value { format!("{}.sqrt()", Sugg::hir(cx, &args[0], ".."))
help = "square-root of a number can be computed more efficiently and accurately"; )
method = "sqrt";
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value { } else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
help = "cube-root of a number can be computed more accurately"; (
method = "cbrt"; "cube-root of a number can be computed more accurately",
format!("{}.cbrt()", Sugg::hir(cx, &args[0], ".."))
)
} else if let Some(exponent) = get_integer_from_float_constant(&value) { } else if let Some(exponent) = get_integer_from_float_constant(&value) {
span_lint_and_sugg( (
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"exponentiation with integer powers can be computed more efficiently", "exponentiation with integer powers can be computed more efficiently",
"consider using", format!(
format!("{}.powi({})", Sugg::hir(cx, &args[0], ".."), exponent), "{}.powi({})",
Applicability::MachineApplicable, Sugg::hir(cx, &args[0], ".."),
); format_numeric_literal(&exponent.to_string(), None, false)
)
return; )
} else { } else {
return; return;
} };
span_lint_and_sugg( span_lint_and_sugg(
cx, cx,
@ -241,7 +237,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
expr.span, expr.span,
help, help,
"consider using", "consider using",
format!("{}.{}()", Sugg::hir(cx, &args[0], ".."), method), suggestion,
Applicability::MachineApplicable, Applicability::MachineApplicable,
); );
} }