Skip to content

Commit 6be9491

Browse files
committed
Reclassify powi(2) lint under suboptimal_flops
1 parent 6dc066f commit 6be9491

File tree

4 files changed

+75
-46
lines changed

4 files changed

+75
-46
lines changed

clippy_lints/src/floating_point_arithmetic.rs

+44-25
Original file line numberDiff line numberDiff line change
@@ -294,37 +294,56 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
294294
}
295295

296296
fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
297-
// Check argument
298297
if let Some((value, _)) = constant(cx, cx.tables(), &args[1]) {
299-
// TODO: need more specific check. this is too wide. remember also to include tests
300-
if let Some(parent) = get_parent_expr(cx, expr) {
301-
if let Some(grandparent) = get_parent_expr(cx, parent) {
302-
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind {
303-
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
304-
return;
298+
if value == Int(2) {
299+
if let Some(parent) = get_parent_expr(cx, expr) {
300+
if let Some(grandparent) = get_parent_expr(cx, parent) {
301+
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = grandparent.kind {
302+
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
303+
return;
304+
}
305305
}
306306
}
307+
308+
if let ExprKind::Binary(
309+
Spanned {
310+
node: BinOpKind::Add, ..
311+
},
312+
ref lhs,
313+
ref rhs,
314+
) = parent.kind
315+
{
316+
let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };
317+
318+
span_lint_and_sugg(
319+
cx,
320+
SUBOPTIMAL_FLOPS,
321+
parent.span,
322+
"square can be computed more efficiently",
323+
"consider using",
324+
format!(
325+
"{}.mul_add({}, {})",
326+
Sugg::hir(cx, &args[0], ".."),
327+
Sugg::hir(cx, &args[0], ".."),
328+
Sugg::hir(cx, &other_addend, ".."),
329+
),
330+
Applicability::MachineApplicable,
331+
);
332+
333+
return;
334+
}
307335
}
308-
}
309336

310-
let (lint, help, suggestion) = match value {
311-
Int(2) => (
312-
IMPRECISE_FLOPS,
313-
"square can be computed more accurately",
337+
span_lint_and_sugg(
338+
cx,
339+
SUBOPTIMAL_FLOPS,
340+
expr.span,
341+
"square can be computed more efficiently",
342+
"consider using",
314343
format!("{} * {}", Sugg::hir(cx, &args[0], ".."), Sugg::hir(cx, &args[0], "..")),
315-
),
316-
_ => return,
317-
};
318-
319-
span_lint_and_sugg(
320-
cx,
321-
lint,
322-
expr.span,
323-
help,
324-
"consider using",
325-
suggestion,
326-
Applicability::MachineApplicable,
327-
);
344+
Applicability::MachineApplicable,
345+
);
346+
}
328347
}
329348
}
330349

tests/ui/floating_point_powi.fixed

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-rustfix
2-
#![warn(clippy::imprecise_flops)]
2+
#![warn(clippy::suboptimal_flops)]
33

44
fn main() {
55
let one = 1;
@@ -8,10 +8,12 @@ fn main() {
88
let _ = x * x;
99

1010
let y = 4f32;
11-
let _ = (x * x + y).sqrt();
12-
let _ = (x + y * y).sqrt();
11+
let _ = x.mul_add(x, y);
12+
let _ = y.mul_add(y, x);
13+
let _ = x.mul_add(x, y).sqrt();
14+
let _ = y.mul_add(y, x).sqrt();
1315
// Cases where the lint shouldn't be applied
1416
let _ = x.powi(3);
1517
let _ = x.powi(one + 1);
16-
let _ = x.hypot(y);
18+
let _ = (x.powi(2) + y.powi(2)).sqrt();
1719
}

tests/ui/floating_point_powi.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// run-rustfix
2-
#![warn(clippy::imprecise_flops)]
2+
#![warn(clippy::suboptimal_flops)]
33

44
fn main() {
55
let one = 1;
@@ -8,6 +8,8 @@ fn main() {
88
let _ = x.powi(1 + 1);
99

1010
let y = 4f32;
11+
let _ = x.powi(2) + y;
12+
let _ = x + y.powi(2);
1113
let _ = (x.powi(2) + y).sqrt();
1214
let _ = (x + y.powi(2)).sqrt();
1315
// Cases where the lint shouldn't be applied

tests/ui/floating_point_powi.stderr

+22-16
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,40 @@
1-
error: square can be computed more accurately
1+
error: square can be computed more efficiently
22
--> $DIR/floating_point_powi.rs:7:13
33
|
44
LL | let _ = x.powi(2);
55
| ^^^^^^^^^ help: consider using: `x * x`
66
|
7-
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
7+
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
88

9-
error: square can be computed more accurately
9+
error: square can be computed more efficiently
1010
--> $DIR/floating_point_powi.rs:8:13
1111
|
1212
LL | let _ = x.powi(1 + 1);
1313
| ^^^^^^^^^^^^^ help: consider using: `x * x`
1414

15-
error: square can be computed more accurately
16-
--> $DIR/floating_point_powi.rs:11:14
15+
error: square can be computed more efficiently
16+
--> $DIR/floating_point_powi.rs:11:13
1717
|
18-
LL | let _ = (x.powi(2) + y).sqrt();
19-
| ^^^^^^^^^ help: consider using: `x * x`
18+
LL | let _ = x.powi(2) + y;
19+
| ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
2020

21-
error: square can be computed more accurately
22-
--> $DIR/floating_point_powi.rs:12:18
21+
error: square can be computed more efficiently
22+
--> $DIR/floating_point_powi.rs:12:13
2323
|
24-
LL | let _ = (x + y.powi(2)).sqrt();
25-
| ^^^^^^^^^ help: consider using: `y * y`
24+
LL | let _ = x + y.powi(2);
25+
| ^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
26+
27+
error: square can be computed more efficiently
28+
--> $DIR/floating_point_powi.rs:13:13
29+
|
30+
LL | let _ = (x.powi(2) + y).sqrt();
31+
| ^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
2632

27-
error: hypotenuse can be computed more accurately
28-
--> $DIR/floating_point_powi.rs:16:13
33+
error: square can be computed more efficiently
34+
--> $DIR/floating_point_powi.rs:14:13
2935
|
30-
LL | let _ = (x.powi(2) + y.powi(2)).sqrt();
31-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)`
36+
LL | let _ = (x + y.powi(2)).sqrt();
37+
| ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
3238

33-
error: aborting due to 5 previous errors
39+
error: aborting due to 6 previous errors
3440

0 commit comments

Comments
 (0)