Skip to content

Commit 028cddb

Browse files
committed
Finished checking for cases of absolute values
1 parent 5a21661 commit 028cddb

File tree

3 files changed

+145
-28
lines changed

3 files changed

+145
-28
lines changed

clippy_lints/src/floating_point_arithmetic.rs

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,18 @@ fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_
387387
}
388388
}
389389

390+
fn is_testing_negative(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool {
391+
if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind {
392+
match op {
393+
BinOpKind::Gt | BinOpKind::Ge => is_zero(left) && are_exprs_equal(cx, right, test),
394+
BinOpKind::Lt | BinOpKind::Le => is_zero(right) && are_exprs_equal(cx, left, test),
395+
_ => false,
396+
}
397+
} else {
398+
false
399+
}
400+
}
401+
390402
fn are_exprs_equal(cx: &LateContext<'_, '_>, expr1: &Expr<'_>, expr2: &Expr<'_>) -> bool {
391403
SpanlessEq::new(cx).ignore_fn().eq_expr(expr1, expr2)
392404
}
@@ -410,30 +422,9 @@ fn is_zero(expr: &Expr<'_>) -> bool {
410422

411423
fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
412424
if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) {
413-
if let ExprKind::Block(
414-
Block {
415-
stmts: [],
416-
expr:
417-
Some(Expr {
418-
kind: ExprKind::Unary(UnOp::UnNeg, else_expr),
419-
..
420-
}),
421-
..
422-
},
423-
_,
424-
) = else_body.kind
425-
{
426-
if let ExprKind::Block(
427-
Block {
428-
stmts: [],
429-
expr: Some(body),
430-
..
431-
},
432-
_,
433-
) = &body.kind
434-
{
425+
if let ExprKind::Block( Block { stmts: [], expr: Some(Expr { kind: ExprKind::Unary(UnOp::UnNeg, else_expr), .. }), .. }, _,) = else_body.kind {
426+
if let ExprKind::Block( Block { stmts: [], expr: Some(body), .. }, _,) = &body.kind {
435427
if are_exprs_equal(cx, else_expr, body) {
436-
dbg!("if (cond) body else -body\nbody: {:?}", &body.kind);
437428
if is_testing_positive(cx, cond, body) {
438429
span_lint_and_sugg(
439430
cx,
@@ -444,6 +435,44 @@ fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
444435
format!("{}.abs()", Sugg::hir(cx, body, "..")),
445436
Applicability::MachineApplicable,
446437
);
438+
} else if is_testing_negative(cx, cond, body) {
439+
span_lint_and_sugg(
440+
cx,
441+
SUBOPTIMAL_FLOPS,
442+
expr.span,
443+
"This looks like you've implemented your own negative absolute value function",
444+
"try",
445+
format!("-{}.abs()", Sugg::hir(cx, body, "..")),
446+
Applicability::MachineApplicable,
447+
);
448+
}
449+
}
450+
}
451+
}
452+
if let ExprKind::Block( Block { stmts: [], expr: Some(Expr { kind: ExprKind::Unary(UnOp::UnNeg, else_expr), .. }), .. }, _,) = &body.kind
453+
{
454+
if let ExprKind::Block( Block { stmts: [], expr: Some(body), .. }, _,) = &else_body.kind {
455+
if are_exprs_equal(cx, else_expr, body) {
456+
if is_testing_negative(cx, cond, body) {
457+
span_lint_and_sugg(
458+
cx,
459+
SUBOPTIMAL_FLOPS,
460+
expr.span,
461+
"This looks like you've implemented your own absolute value function",
462+
"try",
463+
format!("{}.abs()", Sugg::hir(cx, body, "..")),
464+
Applicability::MachineApplicable,
465+
);
466+
} else if is_testing_positive(cx, cond, body) {
467+
span_lint_and_sugg(
468+
cx,
469+
SUBOPTIMAL_FLOPS,
470+
expr.span,
471+
"This looks like you've implemented your own negative absolute value function",
472+
"try",
473+
format!("-{}.abs()", Sugg::hir(cx, body, "..")),
474+
Applicability::MachineApplicable,
475+
);
447476
}
448477
}
449478
}

tests/ui/floating_point_abs.rs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
#[warn(clippy::suboptimal_flops)]
1+
#![warn(clippy::suboptimal_flops)]
2+
23
struct A {
34
a: f64,
45
b: f64
@@ -28,6 +29,22 @@ fn fake_abs3(a: A) -> f64 {
2829
}
2930
}
3031

32+
fn fake_abs4(num: f64) -> f64 {
33+
if 0.0 >= num {
34+
-num
35+
} else {
36+
num
37+
}
38+
}
39+
40+
fn fake_abs5(a: A) -> f64 {
41+
if a.a < 0.0 {
42+
-a.a
43+
} else {
44+
a.a
45+
}
46+
}
47+
3148
fn fake_nabs1(num: f64) -> f64 {
3249
if num < 0.0 {
3350
num
@@ -46,9 +63,9 @@ fn fake_nabs2(num: f64) -> f64 {
4663

4764
fn fake_nabs3(a: A) -> A {
4865
A { a: if a.a >= 0.0 {
49-
a.a
50-
} else {
5166
-a.a
67+
} else {
68+
a.a
5269
}, b: a.b }
5370
}
5471

tests/ui/floating_point_abs.stderr

Lines changed: 73 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: This looks like you've implemented your own absolute value function
2-
--> $DIR/floating_point_abs.rs:4:5
2+
--> $DIR/floating_point_abs.rs:9:5
33
|
44
LL | / if num >= 0.0 {
55
LL | | num
@@ -10,5 +10,76 @@ LL | | }
1010
|
1111
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
1212

13-
error: aborting due to previous error
13+
error: This looks like you've implemented your own absolute value function
14+
--> $DIR/floating_point_abs.rs:17:5
15+
|
16+
LL | / if 0.0 < num {
17+
LL | | num
18+
LL | | } else {
19+
LL | | -num
20+
LL | | }
21+
| |_____^ help: try: `num.abs()`
22+
23+
error: This looks like you've implemented your own absolute value function
24+
--> $DIR/floating_point_abs.rs:25:5
25+
|
26+
LL | / if a.a > 0.0 {
27+
LL | | a.a
28+
LL | | } else {
29+
LL | | -a.a
30+
LL | | }
31+
| |_____^ help: try: `a.a.abs()`
32+
33+
error: This looks like you've implemented your own absolute value function
34+
--> $DIR/floating_point_abs.rs:33:5
35+
|
36+
LL | / if 0.0 >= num {
37+
LL | | -num
38+
LL | | } else {
39+
LL | | num
40+
LL | | }
41+
| |_____^ help: try: `num.abs()`
42+
43+
error: This looks like you've implemented your own absolute value function
44+
--> $DIR/floating_point_abs.rs:41:5
45+
|
46+
LL | / if a.a < 0.0 {
47+
LL | | -a.a
48+
LL | | } else {
49+
LL | | a.a
50+
LL | | }
51+
| |_____^ help: try: `a.a.abs()`
52+
53+
error: This looks like you've implemented your own negative absolute value function
54+
--> $DIR/floating_point_abs.rs:49:5
55+
|
56+
LL | / if num < 0.0 {
57+
LL | | num
58+
LL | | } else {
59+
LL | | -num
60+
LL | | }
61+
| |_____^ help: try: `-num.abs()`
62+
63+
error: This looks like you've implemented your own negative absolute value function
64+
--> $DIR/floating_point_abs.rs:57:5
65+
|
66+
LL | / if 0.0 >= num {
67+
LL | | num
68+
LL | | } else {
69+
LL | | -num
70+
LL | | }
71+
| |_____^ help: try: `-num.abs()`
72+
73+
error: This looks like you've implemented your own negative absolute value function
74+
--> $DIR/floating_point_abs.rs:65:12
75+
|
76+
LL | A { a: if a.a >= 0.0 {
77+
| ____________^
78+
LL | | -a.a
79+
LL | | } else {
80+
LL | | a.a
81+
LL | | }, b: a.b }
82+
| |_________^ help: try: `-a.a.abs()`
83+
84+
error: aborting due to 8 previous errors
1485

0 commit comments

Comments
 (0)