Skip to content

Commit c0a700e

Browse files
committed
Lint for x.powi(2) => x * x
1 parent c25f26d commit c0a700e

10 files changed

+94
-29
lines changed

clippy_lints/src/floating_point_arithmetic.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use crate::consts::{
22
constant, constant_simple, Constant,
3-
Constant::{F32, F64},
3+
Constant::{Int, F32, F64},
44
};
55
use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
66
use if_chain::if_chain;
@@ -295,6 +295,30 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
295295
}
296296
}
297297

298+
fn check_powi(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
299+
// Check argument
300+
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
301+
let (lint, help, suggestion) = match value {
302+
Int(2) => (
303+
IMPRECISE_FLOPS,
304+
"square can be computed more accurately",
305+
format!("{} * {}", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], "..")),
306+
),
307+
_ => return,
308+
};
309+
310+
span_lint_and_sugg(
311+
cx,
312+
lint,
313+
expr.span,
314+
help,
315+
"consider using",
316+
suggestion,
317+
Applicability::MachineApplicable,
318+
);
319+
}
320+
}
321+
298322
// TODO: Lint expressions of the form `x.exp() - y` where y > 1
299323
// and suggest usage of `x.exp_m1() - (y - 1)` instead
300324
fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
@@ -491,6 +515,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
491515
"ln" => check_ln1p(cx, expr, args),
492516
"log" => check_log_base(cx, expr, args),
493517
"powf" => check_powf(cx, expr, args),
518+
"powi" => check_powi(cx, expr, args),
494519
_ => {},
495520
}
496521
}

tests/ui/floating_point_log.fixed

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ fn check_ln1p() {
2525
let _ = 2.0f32.ln_1p();
2626
let _ = x.ln_1p();
2727
let _ = (x / 2.0).ln_1p();
28-
let _ = x.powi(2).ln_1p();
29-
let _ = (x.powi(2) / 2.0).ln_1p();
28+
let _ = x.powi(3).ln_1p();
29+
let _ = (x.powi(3) / 2.0).ln_1p();
3030
let _ = ((std::f32::consts::E - 1.0)).ln_1p();
3131
let _ = x.ln_1p();
32-
let _ = x.powi(2).ln_1p();
32+
let _ = x.powi(3).ln_1p();
3333
let _ = (x + 2.0).ln_1p();
3434
let _ = (x / 2.0).ln_1p();
3535
// Cases where the lint shouldn't be applied
@@ -43,9 +43,9 @@ fn check_ln1p() {
4343
let _ = 2.0f64.ln_1p();
4444
let _ = x.ln_1p();
4545
let _ = (x / 2.0).ln_1p();
46-
let _ = x.powi(2).ln_1p();
46+
let _ = x.powi(3).ln_1p();
4747
let _ = x.ln_1p();
48-
let _ = x.powi(2).ln_1p();
48+
let _ = x.powi(3).ln_1p();
4949
let _ = (x + 2.0).ln_1p();
5050
let _ = (x / 2.0).ln_1p();
5151
// Cases where the lint shouldn't be applied

tests/ui/floating_point_log.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ fn check_ln1p() {
2525
let _ = (1f32 + 2.0).ln();
2626
let _ = (1.0 + x).ln();
2727
let _ = (1.0 + x / 2.0).ln();
28-
let _ = (1.0 + x.powi(2)).ln();
29-
let _ = (1.0 + x.powi(2) / 2.0).ln();
28+
let _ = (1.0 + x.powi(3)).ln();
29+
let _ = (1.0 + x.powi(3) / 2.0).ln();
3030
let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
3131
let _ = (x + 1.0).ln();
32-
let _ = (x.powi(2) + 1.0).ln();
32+
let _ = (x.powi(3) + 1.0).ln();
3333
let _ = (x + 2.0 + 1.0).ln();
3434
let _ = (x / 2.0 + 1.0).ln();
3535
// Cases where the lint shouldn't be applied
@@ -43,9 +43,9 @@ fn check_ln1p() {
4343
let _ = (1f64 + 2.0).ln();
4444
let _ = (1.0 + x).ln();
4545
let _ = (1.0 + x / 2.0).ln();
46-
let _ = (1.0 + x.powi(2)).ln();
46+
let _ = (1.0 + x.powi(3)).ln();
4747
let _ = (x + 1.0).ln();
48-
let _ = (x.powi(2) + 1.0).ln();
48+
let _ = (x.powi(3) + 1.0).ln();
4949
let _ = (x + 2.0 + 1.0).ln();
5050
let _ = (x / 2.0 + 1.0).ln();
5151
// Cases where the lint shouldn't be applied

tests/ui/floating_point_log.stderr

+10-10
Original file line numberDiff line numberDiff line change
@@ -77,14 +77,14 @@ LL | let _ = (1.0 + x / 2.0).ln();
7777
error: ln(1 + x) can be computed more accurately
7878
--> $DIR/floating_point_log.rs:28:13
7979
|
80-
LL | let _ = (1.0 + x.powi(2)).ln();
81-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
80+
LL | let _ = (1.0 + x.powi(3)).ln();
81+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
8282

8383
error: ln(1 + x) can be computed more accurately
8484
--> $DIR/floating_point_log.rs:29:13
8585
|
86-
LL | let _ = (1.0 + x.powi(2) / 2.0).ln();
87-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()`
86+
LL | let _ = (1.0 + x.powi(3) / 2.0).ln();
87+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(3) / 2.0).ln_1p()`
8888

8989
error: ln(1 + x) can be computed more accurately
9090
--> $DIR/floating_point_log.rs:30:13
@@ -101,8 +101,8 @@ LL | let _ = (x + 1.0).ln();
101101
error: ln(1 + x) can be computed more accurately
102102
--> $DIR/floating_point_log.rs:32:13
103103
|
104-
LL | let _ = (x.powi(2) + 1.0).ln();
105-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
104+
LL | let _ = (x.powi(3) + 1.0).ln();
105+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
106106

107107
error: ln(1 + x) can be computed more accurately
108108
--> $DIR/floating_point_log.rs:33:13
@@ -143,8 +143,8 @@ LL | let _ = (1.0 + x / 2.0).ln();
143143
error: ln(1 + x) can be computed more accurately
144144
--> $DIR/floating_point_log.rs:46:13
145145
|
146-
LL | let _ = (1.0 + x.powi(2)).ln();
147-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
146+
LL | let _ = (1.0 + x.powi(3)).ln();
147+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
148148

149149
error: ln(1 + x) can be computed more accurately
150150
--> $DIR/floating_point_log.rs:47:13
@@ -155,8 +155,8 @@ LL | let _ = (x + 1.0).ln();
155155
error: ln(1 + x) can be computed more accurately
156156
--> $DIR/floating_point_log.rs:48:13
157157
|
158-
LL | let _ = (x.powi(2) + 1.0).ln();
159-
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
158+
LL | let _ = (x.powi(3) + 1.0).ln();
159+
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
160160

161161
error: ln(1 + x) can be computed more accurately
162162
--> $DIR/floating_point_log.rs:49:13

tests/ui/floating_point_powf.fixed

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn main() {
1111
let _ = (-3.1f32).exp();
1212
let _ = x.sqrt();
1313
let _ = x.cbrt();
14-
let _ = x.powi(2);
14+
let _ = x.powi(3);
1515
let _ = x.powi(-2);
1616
let _ = x.powi(16_777_215);
1717
let _ = x.powi(-16_777_215);
@@ -30,7 +30,7 @@ fn main() {
3030
let _ = (-3.1f64).exp();
3131
let _ = x.sqrt();
3232
let _ = x.cbrt();
33-
let _ = x.powi(2);
33+
let _ = x.powi(3);
3434
let _ = x.powi(-2);
3535
let _ = x.powi(-2_147_483_648);
3636
let _ = x.powi(2_147_483_647);

tests/ui/floating_point_powf.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ fn main() {
1111
let _ = std::f32::consts::E.powf(-3.1);
1212
let _ = x.powf(1.0 / 2.0);
1313
let _ = x.powf(1.0 / 3.0);
14-
let _ = x.powf(2.0);
14+
let _ = x.powf(3.0);
1515
let _ = x.powf(-2.0);
1616
let _ = x.powf(16_777_215.0);
1717
let _ = x.powf(-16_777_215.0);
@@ -30,7 +30,7 @@ fn main() {
3030
let _ = std::f64::consts::E.powf(-3.1);
3131
let _ = x.powf(1.0 / 2.0);
3232
let _ = x.powf(1.0 / 3.0);
33-
let _ = x.powf(2.0);
33+
let _ = x.powf(3.0);
3434
let _ = x.powf(-2.0);
3535
let _ = x.powf(-2_147_483_648.0);
3636
let _ = x.powf(2_147_483_647.0);

tests/ui/floating_point_powf.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,8 @@ LL | let _ = x.powf(1.0 / 3.0);
5353
error: exponentiation with integer powers can be computed more efficiently
5454
--> $DIR/floating_point_powf.rs:14:13
5555
|
56-
LL | let _ = x.powf(2.0);
57-
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
56+
LL | let _ = x.powf(3.0);
57+
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
5858

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

131131
error: exponentiation with integer powers can be computed more efficiently
132132
--> $DIR/floating_point_powf.rs:34:13

tests/ui/floating_point_powi.fixed

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
3+
4+
fn main() {
5+
let one = 1;
6+
let x = 3f32;
7+
let _ = x * x;
8+
let _ = x * x;
9+
// Cases where the lint shouldn't be applied
10+
let _ = x.powi(3);
11+
let _ = x.powi(one + 1);
12+
}

tests/ui/floating_point_powi.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// run-rustfix
2+
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
3+
4+
fn main() {
5+
let one = 1;
6+
let x = 3f32;
7+
let _ = x.powi(2);
8+
let _ = x.powi(1 + 1);
9+
// Cases where the lint shouldn't be applied
10+
let _ = x.powi(3);
11+
let _ = x.powi(one + 1);
12+
}

tests/ui/floating_point_powi.stderr

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: square can be computed more accurately
2+
--> $DIR/floating_point_powi.rs:7:13
3+
|
4+
LL | let _ = x.powi(2);
5+
| ^^^^^^^^^ help: consider using: `x * x`
6+
|
7+
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
8+
9+
error: square can be computed more accurately
10+
--> $DIR/floating_point_powi.rs:8:13
11+
|
12+
LL | let _ = x.powi(1 + 1);
13+
| ^^^^^^^^^^^^^ help: consider using: `x * x`
14+
15+
error: aborting due to 2 previous errors
16+

0 commit comments

Comments
 (0)