Skip to content

Commit f8e949f

Browse files
committed
Recommended changes from flip1995
1 parent 0d584f3 commit f8e949f

File tree

4 files changed

+179
-81
lines changed

4 files changed

+179
-81
lines changed

clippy_lints/src/floating_point_arithmetic.rs

Lines changed: 49 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
use crate::consts::{
2-
constant, Constant,
2+
constant, constant_simple, Constant,
33
Constant::{F32, F64},
44
};
55
use crate::utils::{higher, span_lint_and_sugg, sugg, SpanlessEq};
66
use if_chain::if_chain;
77
use rustc::ty;
88
use rustc_errors::Applicability;
9-
use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Lit, UnOp};
9+
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
1010
use rustc_lint::{LateContext, LateLintPass};
1111
use rustc_session::{declare_lint_pass, declare_tool_lint};
1212
use rustc_span::source_map::Spanned;
1313

14-
use rustc_ast::ast::{self, FloatTy, LitFloatType, LitKind};
14+
use rustc_ast::ast;
1515
use std::f32::consts as f32_consts;
1616
use std::f64::consts as f64_consts;
1717
use sugg::{format_numeric_literal, Sugg};
@@ -378,20 +378,21 @@ fn check_mul_add(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
378378
fn is_testing_positive(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool {
379379
if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind {
380380
match op {
381-
BinOpKind::Gt | BinOpKind::Ge => is_zero(right) && are_exprs_equal(cx, left, test),
382-
BinOpKind::Lt | BinOpKind::Le => is_zero(left) && are_exprs_equal(cx, right, test),
381+
BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, right) && are_exprs_equal(cx, left, test),
382+
BinOpKind::Lt | BinOpKind::Le => is_zero(cx, left) && are_exprs_equal(cx, right, test),
383383
_ => false,
384384
}
385385
} else {
386386
false
387387
}
388388
}
389389

390+
/// See [`is_testing_positive`]
390391
fn is_testing_negative(cx: &LateContext<'_, '_>, expr: &Expr<'_>, test: &Expr<'_>) -> bool {
391392
if let ExprKind::Binary(Spanned { node: op, .. }, left, right) = expr.kind {
392393
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),
394+
BinOpKind::Gt | BinOpKind::Ge => is_zero(cx, left) && are_exprs_equal(cx, right, test),
395+
BinOpKind::Lt | BinOpKind::Le => is_zero(cx, right) && are_exprs_equal(cx, left, test),
395396
_ => false,
396397
}
397398
} else {
@@ -404,85 +405,69 @@ fn are_exprs_equal(cx: &LateContext<'_, '_>, expr1: &Expr<'_>, expr2: &Expr<'_>)
404405
}
405406

406407
/// Returns true iff expr is some zero literal
407-
fn is_zero(expr: &Expr<'_>) -> bool {
408-
if let ExprKind::Lit(Lit { node: lit, .. }) = &expr.kind {
409-
match lit {
410-
LitKind::Int(0, _) => true,
411-
LitKind::Float(symb, LitFloatType::Unsuffixed)
412-
| LitKind::Float(symb, LitFloatType::Suffixed(FloatTy::F64)) => {
413-
symb.as_str().parse::<f64>().unwrap() == 0.0
414-
},
415-
LitKind::Float(symb, LitFloatType::Suffixed(FloatTy::F32)) => symb.as_str().parse::<f32>().unwrap() == 0.0,
416-
_ => false,
417-
}
418-
} else {
419-
false
408+
fn is_zero(cx: &LateContext<'_, '_>, expr: &Expr<'_>) -> bool {
409+
match constant_simple(cx, cx.tables, expr) {
410+
Some(Constant::Int(i)) => i == 0,
411+
Some(Constant::F32(f)) => f == 0.0,
412+
Some(Constant::F64(f)) => f == 0.0,
413+
_ => false,
420414
}
421415
}
422416

423-
/// If the expressions are not opposites, return None
424-
/// Otherwise, return true if expr2 = -expr1, false if expr1 = -expr2 and return the positive
425-
/// expression
426-
fn are_opposites<'a>(
417+
/// If the two expressions are negations of each other, then it returns
418+
/// a tuple, in which the first element is true iff expr1 is the
419+
/// positive expressions, and the second element is the positive
420+
/// one of the two expressions
421+
/// If the two expressions are not negations of each other, then it
422+
/// returns None.
423+
fn are_negated<'a>(
427424
cx: &LateContext<'_, '_>,
428425
expr1: &'a Expr<'a>,
429426
expr2: &'a Expr<'a>,
430427
) -> Option<(bool, &'a Expr<'a>)> {
431-
if let ExprKind::Block(
432-
Block {
433-
stmts: [],
434-
expr: Some(expr1_inner),
435-
..
436-
},
437-
_,
438-
) = &expr1.kind
439-
{
440-
if let ExprKind::Block(
441-
Block {
442-
stmts: [],
443-
expr: Some(expr2_inner),
444-
..
445-
},
446-
_,
447-
) = &expr2.kind
448-
{
449-
if let ExprKind::Unary(UnOp::UnNeg, expr1_neg) = &expr1_inner.kind {
450-
if are_exprs_equal(cx, expr1_neg, expr2_inner) {
451-
return Some((false, expr2_inner));
452-
}
453-
}
454-
if let ExprKind::Unary(UnOp::UnNeg, expr2_neg) = &expr2_inner.kind {
455-
if are_exprs_equal(cx, expr1_inner, expr2_neg) {
456-
return Some((true, expr1_inner));
457-
}
458-
}
428+
if let ExprKind::Unary(UnOp::UnNeg, expr1_negated) = &expr1.kind {
429+
if are_exprs_equal(cx, expr1_negated, expr2) {
430+
return Some((false, expr2));
431+
}
432+
}
433+
if let ExprKind::Unary(UnOp::UnNeg, expr2_negated) = &expr2.kind {
434+
if are_exprs_equal(cx, expr1, expr2_negated) {
435+
return Some((true, expr1));
459436
}
460437
}
461438
None
462439
}
463440

464441
fn check_custom_abs(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
465-
if let Some((cond, body, Some(else_body))) = higher::if_block(&expr) {
466-
if let Some((expr1_pos, body)) = are_opposites(cx, body, else_body) {
467-
let pos_abs_sugg = (
468-
"This looks like you've implemented your own absolute value function",
442+
if_chain! {
443+
if let Some((cond, body, Some(else_body))) = higher::if_block(&expr);
444+
if let ExprKind::Block(block, _) = body.kind;
445+
if block.stmts.is_empty();
446+
if let Some(if_body_expr) = block.expr;
447+
if let ExprKind::Block(else_block, _) = else_body.kind;
448+
if else_block.stmts.is_empty();
449+
if let Some(else_body_expr) = else_block.expr;
450+
if let Some((if_expr_positive, body)) = are_negated(cx, if_body_expr, else_body_expr);
451+
then {
452+
let positive_abs_sugg = (
453+
"manual implementation of `abs` method",
469454
format!("{}.abs()", Sugg::hir(cx, body, "..")),
470455
);
471-
let neg_abs_sugg = (
472-
"This looks like you've implemented your own negative absolute value function",
456+
let negative_abs_sugg = (
457+
"manual implementation of negation of `abs` method",
473458
format!("-{}.abs()", Sugg::hir(cx, body, "..")),
474459
);
475460
let sugg = if is_testing_positive(cx, cond, body) {
476-
if expr1_pos {
477-
pos_abs_sugg
461+
if if_expr_positive {
462+
positive_abs_sugg
478463
} else {
479-
neg_abs_sugg
464+
negative_abs_sugg
480465
}
481466
} else if is_testing_negative(cx, cond, body) {
482-
if expr1_pos {
483-
neg_abs_sugg
467+
if if_expr_positive {
468+
negative_abs_sugg
484469
} else {
485-
pos_abs_sugg
470+
positive_abs_sugg
486471
}
487472
} else {
488473
return;

tests/ui/floating_point_abs.fixed

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// run-rustfix
2+
#![warn(clippy::suboptimal_flops)]
3+
4+
struct A {
5+
a: f64,
6+
b: f64,
7+
}
8+
9+
fn fake_abs1(num: f64) -> f64 {
10+
num.abs()
11+
}
12+
13+
fn fake_abs2(num: f64) -> f64 {
14+
num.abs()
15+
}
16+
17+
fn fake_abs3(a: A) -> f64 {
18+
a.a.abs()
19+
}
20+
21+
fn fake_abs4(num: f64) -> f64 {
22+
num.abs()
23+
}
24+
25+
fn fake_abs5(a: A) -> f64 {
26+
a.a.abs()
27+
}
28+
29+
fn fake_nabs1(num: f64) -> f64 {
30+
-num.abs()
31+
}
32+
33+
fn fake_nabs2(num: f64) -> f64 {
34+
-num.abs()
35+
}
36+
37+
fn fake_nabs3(a: A) -> A {
38+
A {
39+
a: -a.a.abs(),
40+
b: a.b,
41+
}
42+
}
43+
44+
fn not_fake_abs1(num: f64) -> f64 {
45+
if num > 0.0 {
46+
num
47+
} else {
48+
-num - 1f64
49+
}
50+
}
51+
52+
fn not_fake_abs2(num: f64) -> f64 {
53+
if num > 0.0 {
54+
num + 1.0
55+
} else {
56+
-(num + 1.0)
57+
}
58+
}
59+
60+
fn not_fake_abs3(num1: f64, num2: f64) -> f64 {
61+
if num1 > 0.0 {
62+
num2
63+
} else {
64+
-num2
65+
}
66+
}
67+
68+
fn not_fake_abs4(a: A) -> f64 {
69+
if a.a > 0.0 {
70+
a.b
71+
} else {
72+
-a.b
73+
}
74+
}
75+
76+
fn not_fake_abs5(a: A) -> f64 {
77+
if a.a > 0.0 {
78+
a.a
79+
} else {
80+
-a.b
81+
}
82+
}
83+
84+
fn main() {
85+
fake_abs1(5.0);
86+
fake_abs2(5.0);
87+
fake_abs3(A { a: 5.0, b: 5.0 } );
88+
fake_abs4(5.0);
89+
fake_abs5(A { a: 5.0, b: 5.0 } );
90+
fake_nabs1(5.0);
91+
fake_nabs2(5.0);
92+
fake_nabs3(A { a: 5.0, b: 5.0 } );
93+
not_fake_abs1(5.0);
94+
not_fake_abs2(5.0);
95+
not_fake_abs3(5.0, 5.0);
96+
not_fake_abs4(A { a: 5.0, b: 5.0 } );
97+
not_fake_abs5(A { a: 5.0, b: 5.0 } );
98+
}

tests/ui/floating_point_abs.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
// run-rustfix
12
#![warn(clippy::suboptimal_flops)]
23

34
struct A {
@@ -108,4 +109,18 @@ fn not_fake_abs5(a: A) -> f64 {
108109
}
109110
}
110111

111-
fn main() {}
112+
fn main() {
113+
fake_abs1(5.0);
114+
fake_abs2(5.0);
115+
fake_abs3(A { a: 5.0, b: 5.0 } );
116+
fake_abs4(5.0);
117+
fake_abs5(A { a: 5.0, b: 5.0 } );
118+
fake_nabs1(5.0);
119+
fake_nabs2(5.0);
120+
fake_nabs3(A { a: 5.0, b: 5.0 } );
121+
not_fake_abs1(5.0);
122+
not_fake_abs2(5.0);
123+
not_fake_abs3(5.0, 5.0);
124+
not_fake_abs4(A { a: 5.0, b: 5.0 } );
125+
not_fake_abs5(A { a: 5.0, b: 5.0 } );
126+
}

tests/ui/floating_point_abs.stderr

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

13-
error: This looks like you've implemented your own absolute value function
14-
--> $DIR/floating_point_abs.rs:17:5
13+
error: manual implementation of `abs` method
14+
--> $DIR/floating_point_abs.rs:18:5
1515
|
1616
LL | / if 0.0 < num {
1717
LL | | num
@@ -20,8 +20,8 @@ LL | | -num
2020
LL | | }
2121
| |_____^ help: try: `num.abs()`
2222

23-
error: This looks like you've implemented your own absolute value function
24-
--> $DIR/floating_point_abs.rs:25:5
23+
error: manual implementation of `abs` method
24+
--> $DIR/floating_point_abs.rs:26:5
2525
|
2626
LL | / if a.a > 0.0 {
2727
LL | | a.a
@@ -30,8 +30,8 @@ LL | | -a.a
3030
LL | | }
3131
| |_____^ help: try: `a.a.abs()`
3232

33-
error: This looks like you've implemented your own absolute value function
34-
--> $DIR/floating_point_abs.rs:33:5
33+
error: manual implementation of `abs` method
34+
--> $DIR/floating_point_abs.rs:34:5
3535
|
3636
LL | / if 0.0 >= num {
3737
LL | | -num
@@ -40,8 +40,8 @@ LL | | num
4040
LL | | }
4141
| |_____^ help: try: `num.abs()`
4242

43-
error: This looks like you've implemented your own absolute value function
44-
--> $DIR/floating_point_abs.rs:41:5
43+
error: manual implementation of `abs` method
44+
--> $DIR/floating_point_abs.rs:42:5
4545
|
4646
LL | / if a.a < 0.0 {
4747
LL | | -a.a
@@ -50,8 +50,8 @@ LL | | a.a
5050
LL | | }
5151
| |_____^ help: try: `a.a.abs()`
5252

53-
error: This looks like you've implemented your own negative absolute value function
54-
--> $DIR/floating_point_abs.rs:49:5
53+
error: manual implementation of negation of `abs` method
54+
--> $DIR/floating_point_abs.rs:50:5
5555
|
5656
LL | / if num < 0.0 {
5757
LL | | num
@@ -60,8 +60,8 @@ LL | | -num
6060
LL | | }
6161
| |_____^ help: try: `-num.abs()`
6262

63-
error: This looks like you've implemented your own negative absolute value function
64-
--> $DIR/floating_point_abs.rs:57:5
63+
error: manual implementation of negation of `abs` method
64+
--> $DIR/floating_point_abs.rs:58:5
6565
|
6666
LL | / if 0.0 >= num {
6767
LL | | num
@@ -70,8 +70,8 @@ LL | | -num
7070
LL | | }
7171
| |_____^ help: try: `-num.abs()`
7272

73-
error: This looks like you've implemented your own negative absolute value function
74-
--> $DIR/floating_point_abs.rs:66:12
73+
error: manual implementation of negation of `abs` method
74+
--> $DIR/floating_point_abs.rs:67:12
7575
|
7676
LL | a: if a.a >= 0.0 { -a.a } else { a.a },
7777
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()`

0 commit comments

Comments
 (0)