Skip to content

Commit

Permalink
Reclassify powi(2) lint under suboptimal_flops
Browse files Browse the repository at this point in the history
  • Loading branch information
thiagoarrais committed Jun 22, 2020
1 parent ace14d3 commit 0729c8c
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 46 deletions.
69 changes: 44 additions & 25 deletions clippy_lints/src/floating_point_arithmetic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -294,37 +294,56 @@ 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]) {
// TODO: need more specific check. this is too wide. remember also to include tests
if let Some(parent) = get_parent_expr(cx, expr) {
if let Some(grandparent) = get_parent_expr(cx, parent) {
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args) = grandparent.kind {
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
return;
if value == Int(2) {
if let Some(parent) = get_parent_expr(cx, expr) {
if let Some(grandparent) = get_parent_expr(cx, parent) {
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args) = grandparent.kind {
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
return;
}
}
}

if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
ref lhs,
ref rhs,
) = parent.kind
{
let other_addend = if lhs.hir_id == expr.hir_id { rhs } else { lhs };

span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
parent.span,
"square can be computed more efficiently",
"consider using",
format!(
"{}.mul_add({}, {})",
Sugg::hir(cx, &args[0], ".."),
Sugg::hir(cx, &args[0], ".."),
Sugg::hir(cx, &other_addend, ".."),
),
Applicability::MachineApplicable,
);

return;
}
}
}

let (lint, help, suggestion) = match value {
Int(2) => (
IMPRECISE_FLOPS,
"square can be computed more accurately",
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"square can be computed more efficiently",
"consider using",
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,
);
Applicability::MachineApplicable,
);
}
}
}

Expand Down
10 changes: 6 additions & 4 deletions tests/ui/floating_point_powi.fixed
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
#![warn(clippy::suboptimal_flops)]

fn main() {
let one = 1;
Expand All @@ -8,10 +8,12 @@ fn main() {
let _ = x * x;

let y = 4f32;
let _ = (x * x + y).sqrt();
let _ = (x + y * y).sqrt();
let _ = x.mul_add(x, y);
let _ = y.mul_add(y, x);
let _ = x.mul_add(x, y).sqrt();
let _ = y.mul_add(y, x).sqrt();
// Cases where the lint shouldn't be applied
let _ = x.powi(3);
let _ = x.powi(one + 1);
let _ = x.hypot(y);
let _ = (x.powi(2) + y.powi(2)).sqrt();
}
4 changes: 3 additions & 1 deletion tests/ui/floating_point_powi.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
#![warn(clippy::suboptimal_flops)]

fn main() {
let one = 1;
Expand All @@ -8,6 +8,8 @@ fn main() {
let _ = x.powi(1 + 1);

let y = 4f32;
let _ = x.powi(2) + y;
let _ = x + y.powi(2);
let _ = (x.powi(2) + y).sqrt();
let _ = (x + y.powi(2)).sqrt();
// Cases where the lint shouldn't be applied
Expand Down
38 changes: 22 additions & 16 deletions tests/ui/floating_point_powi.stderr
Original file line number Diff line number Diff line change
@@ -1,34 +1,40 @@
error: square can be computed more accurately
error: square can be computed more efficiently
--> $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`
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`

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

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

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

error: square can be computed more efficiently
--> $DIR/floating_point_powi.rs:13:13
|
LL | let _ = (x.powi(2) + y).sqrt();
| ^^^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`

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

error: aborting due to 5 previous errors
error: aborting due to 6 previous errors

0 comments on commit 0729c8c

Please sign in to comment.