mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-12 20:16:49 +00:00
Lint for x.powi(2) => x * x
This commit is contained in:
parent
57cdf2dc16
commit
a6f1af75d7
@ -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),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
12
tests/ui/floating_point_powi.fixed
Normal file
12
tests/ui/floating_point_powi.fixed
Normal 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);
|
||||
}
|
12
tests/ui/floating_point_powi.rs
Normal file
12
tests/ui/floating_point_powi.rs
Normal 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);
|
||||
}
|
16
tests/ui/floating_point_powi.stderr
Normal file
16
tests/ui/floating_point_powi.stderr
Normal 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
|
||||
|
Loading…
Reference in New Issue
Block a user