Lint for x.powi(2) => x * x

This commit is contained in:
Thiago Arrais 2020-04-03 13:58:52 -03:00
parent 57cdf2dc16
commit a6f1af75d7
10 changed files with 94 additions and 29 deletions

View file

@ -1,6 +1,6 @@
use crate::consts::{
constant, constant_simple, Constant,
Constant::{F32, F64},
Constant::{Int, F32, F64},
};
use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
use if_chain::if_chain;
@ -293,6 +293,30 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
}
}
fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
// Check argument
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
let (lint, help, suggestion) = match value {
Int(2) => (
IMPRECISE_FLOPS,
"square can be computed more accurately",
format!("{} * {}", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], "..")),
),
_ => return,
};
span_lint_and_sugg(
cx,
lint,
expr.span,
help,
"consider using",
suggestion,
Applicability::MachineApplicable,
);
}
}
// TODO: Lint expressions of the form `x.exp() - y` where y > 1
// and suggest usage of `x.exp_m1() - (y - 1)` instead
fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
@ -489,6 +513,7 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
"ln" => check_ln1p(cx, expr, args),
"log" => check_log_base(cx, expr, args),
"powf" => check_powf(cx, expr, args),
"powi" => check_powi(cx, expr, args),
_ => {},
}
}

View file

@ -25,11 +25,11 @@ fn check_ln1p() {
let _ = 2.0f32.ln_1p();
let _ = x.ln_1p();
let _ = (x / 2.0).ln_1p();
let _ = x.powi(2).ln_1p();
let _ = (x.powi(2) / 2.0).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = (x.powi(3) / 2.0).ln_1p();
let _ = ((std::f32::consts::E - 1.0)).ln_1p();
let _ = x.ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = (x + 2.0).ln_1p();
let _ = (x / 2.0).ln_1p();
// Cases where the lint shouldn't be applied
@ -43,9 +43,9 @@ fn check_ln1p() {
let _ = 2.0f64.ln_1p();
let _ = x.ln_1p();
let _ = (x / 2.0).ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = x.ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = (x + 2.0).ln_1p();
let _ = (x / 2.0).ln_1p();
// Cases where the lint shouldn't be applied

View file

@ -25,11 +25,11 @@ fn check_ln1p() {
let _ = (1f32 + 2.0).ln();
let _ = (1.0 + x).ln();
let _ = (1.0 + x / 2.0).ln();
let _ = (1.0 + x.powi(2)).ln();
let _ = (1.0 + x.powi(2) / 2.0).ln();
let _ = (1.0 + x.powi(3)).ln();
let _ = (1.0 + x.powi(3) / 2.0).ln();
let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
let _ = (x + 1.0).ln();
let _ = (x.powi(2) + 1.0).ln();
let _ = (x.powi(3) + 1.0).ln();
let _ = (x + 2.0 + 1.0).ln();
let _ = (x / 2.0 + 1.0).ln();
// Cases where the lint shouldn't be applied
@ -43,9 +43,9 @@ fn check_ln1p() {
let _ = (1f64 + 2.0).ln();
let _ = (1.0 + x).ln();
let _ = (1.0 + x / 2.0).ln();
let _ = (1.0 + x.powi(2)).ln();
let _ = (1.0 + x.powi(3)).ln();
let _ = (x + 1.0).ln();
let _ = (x.powi(2) + 1.0).ln();
let _ = (x.powi(3) + 1.0).ln();
let _ = (x + 2.0 + 1.0).ln();
let _ = (x / 2.0 + 1.0).ln();
// Cases where the lint shouldn't be applied

View file

@ -77,14 +77,14 @@ LL | let _ = (1.0 + x / 2.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:28:13
|
LL | let _ = (1.0 + x.powi(2)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (1.0 + x.powi(3)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:29:13
|
LL | let _ = (1.0 + x.powi(2) / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()`
LL | let _ = (1.0 + x.powi(3) / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(3) / 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:30:13
@ -101,8 +101,8 @@ LL | let _ = (x + 1.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:32:13
|
LL | let _ = (x.powi(2) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (x.powi(3) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:33:13
@ -143,8 +143,8 @@ LL | let _ = (1.0 + x / 2.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:46:13
|
LL | let _ = (1.0 + x.powi(2)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (1.0 + x.powi(3)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:47:13
@ -155,8 +155,8 @@ LL | let _ = (x + 1.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:48:13
|
LL | let _ = (x.powi(2) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (x.powi(3) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:49:13

View file

@ -11,7 +11,7 @@ fn main() {
let _ = (-3.1f32).exp();
let _ = x.sqrt();
let _ = x.cbrt();
let _ = x.powi(2);
let _ = x.powi(3);
let _ = x.powi(-2);
let _ = x.powi(16_777_215);
let _ = x.powi(-16_777_215);
@ -30,7 +30,7 @@ fn main() {
let _ = (-3.1f64).exp();
let _ = x.sqrt();
let _ = x.cbrt();
let _ = x.powi(2);
let _ = x.powi(3);
let _ = x.powi(-2);
let _ = x.powi(-2_147_483_648);
let _ = x.powi(2_147_483_647);

View file

@ -11,7 +11,7 @@ fn main() {
let _ = std::f32::consts::E.powf(-3.1);
let _ = x.powf(1.0 / 2.0);
let _ = x.powf(1.0 / 3.0);
let _ = x.powf(2.0);
let _ = x.powf(3.0);
let _ = x.powf(-2.0);
let _ = x.powf(16_777_215.0);
let _ = x.powf(-16_777_215.0);
@ -30,7 +30,7 @@ fn main() {
let _ = std::f64::consts::E.powf(-3.1);
let _ = x.powf(1.0 / 2.0);
let _ = x.powf(1.0 / 3.0);
let _ = x.powf(2.0);
let _ = x.powf(3.0);
let _ = x.powf(-2.0);
let _ = x.powf(-2_147_483_648.0);
let _ = x.powf(2_147_483_647.0);

View file

@ -53,8 +53,8 @@ LL | let _ = x.powf(1.0 / 3.0);
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:14:13
|
LL | let _ = x.powf(2.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:15:13
@ -125,8 +125,8 @@ LL | let _ = x.powf(1.0 / 3.0);
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:33:13
|
LL | let _ = x.powf(2.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:34:13

View file

@ -0,0 +1,12 @@
// run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
fn main() {
let one = 1;
let x = 3f32;
let _ = x * x;
let _ = x * x;
// Cases where the lint shouldn't be applied
let _ = x.powi(3);
let _ = x.powi(one + 1);
}

View file

@ -0,0 +1,12 @@
// run-rustfix
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
fn main() {
let one = 1;
let x = 3f32;
let _ = x.powi(2);
let _ = x.powi(1 + 1);
// Cases where the lint shouldn't be applied
let _ = x.powi(3);
let _ = x.powi(one + 1);
}

View file

@ -0,0 +1,16 @@
error: square can be computed more accurately
--> $DIR/floating_point_powi.rs:7:13
|
LL | let _ = x.powi(2);
| ^^^^^^^^^ help: consider using: `x * x`
|
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: square can be computed more accurately
--> $DIR/floating_point_powi.rs:8:13
|
LL | let _ = x.powi(1 + 1);
| ^^^^^^^^^^^^^ help: consider using: `x * x`
error: aborting due to 2 previous errors