Skip to content

Commit 4065ca9

Browse files
Move manual_mul_add into suboptimal_flops lint
1 parent 454e505 commit 4065ca9

16 files changed

+179
-290
lines changed

CHANGELOG.md

-1
Original file line numberDiff line numberDiff line change
@@ -1210,7 +1210,6 @@ Released 2018-09-13
12101210
[`lossy_float_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#lossy_float_literal
12111211
[`main_recursion`]: https://rust-lang.github.io/rust-clippy/master/index.html#main_recursion
12121212
[`manual_memcpy`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_memcpy
1213-
[`manual_mul_add`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_mul_add
12141213
[`manual_saturating_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_saturating_arithmetic
12151214
[`manual_swap`]: https://rust-lang.github.io/rust-clippy/master/index.html#manual_swap
12161215
[`many_single_char_names`]: https://rust-lang.github.io/rust-clippy/master/index.html#many_single_char_names

clippy_lints/src/floating_point_arithmetic.rs

+54-5
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use crate::consts::{
22
constant, Constant,
33
Constant::{F32, F64},
44
};
5-
use crate::utils::*;
5+
use crate::utils::{span_lint_and_sugg, sugg};
66
use if_chain::if_chain;
77
use rustc::ty;
88
use rustc_errors::Applicability;
9-
use rustc_hir::*;
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 std::f32::consts as f32_consts;
@@ -39,6 +39,7 @@ declare_clippy_lint! {
3939
/// let _ = (1.0 + a).ln();
4040
/// let _ = a.exp() - 1.0;
4141
/// let _ = a.powf(2.0);
42+
/// let _ = a * 2.0 + 4.0;
4243
/// ```
4344
///
4445
/// is better expressed as
@@ -57,6 +58,7 @@ declare_clippy_lint! {
5758
/// let _ = a.ln_1p();
5859
/// let _ = a.exp_m1();
5960
/// let _ = a.powi(2);
61+
/// let _ = a.mul_add(2.0, 4.0);
6062
/// ```
6163
pub SUBOPTIMAL_FLOPS,
6264
nursery,
@@ -211,12 +213,12 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
211213
let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
212214
(
213215
"square-root of a number can be computed more efficiently and accurately",
214-
format!("{}.sqrt()", Sugg::hir(cx, &args[0], ".."))
216+
format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")),
215217
)
216218
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
217219
(
218220
"cube-root of a number can be computed more accurately",
219-
format!("{}.cbrt()", Sugg::hir(cx, &args[0], ".."))
221+
format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")),
220222
)
221223
} else if let Some(exponent) = get_integer_from_float_constant(&value) {
222224
(
@@ -225,7 +227,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
225227
"{}.powi({})",
226228
Sugg::hir(cx, &args[0], ".."),
227229
format_numeric_literal(&exponent.to_string(), None, false)
228-
)
230+
),
229231
)
230232
} else {
231233
return;
@@ -272,6 +274,52 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
272274
}
273275
}
274276

277+
fn is_float_mul_expr<'a>(cx: &LateContext<'_, '_>, expr: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
278+
if_chain! {
279+
if let ExprKind::Binary(op, ref lhs, ref rhs) = &expr.kind;
280+
if let BinOpKind::Mul = op.node;
281+
if cx.tables.expr_ty(lhs).is_floating_point();
282+
if cx.tables.expr_ty(rhs).is_floating_point();
283+
then {
284+
return Some((lhs, rhs));
285+
}
286+
}
287+
288+
None
289+
}
290+
291+
// TODO: Fix rust-lang/rust-clippy#4735
292+
fn check_fma(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
293+
if_chain! {
294+
if let ExprKind::Binary(op, lhs, rhs) = &expr.kind;
295+
if let BinOpKind::Add = op.node;
296+
then {
297+
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
298+
(inner_lhs, inner_rhs, rhs)
299+
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
300+
(inner_lhs, inner_rhs, lhs)
301+
} else {
302+
return;
303+
};
304+
305+
span_lint_and_sugg(
306+
cx,
307+
SUBOPTIMAL_FLOPS,
308+
expr.span,
309+
"multiply and add expressions can be calculated more efficiently and accurately",
310+
"consider using",
311+
format!(
312+
"{}.mul_add({}, {})",
313+
prepare_receiver_sugg(cx, recv),
314+
Sugg::hir(cx, arg1, ".."),
315+
Sugg::hir(cx, arg2, ".."),
316+
),
317+
Applicability::MachineApplicable,
318+
);
319+
}
320+
}
321+
}
322+
275323
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
276324
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx Expr<'_>) {
277325
if let ExprKind::MethodCall(ref path, _, args) = &expr.kind {
@@ -287,6 +335,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for FloatingPointArithmetic {
287335
}
288336
} else {
289337
check_expm1(cx, expr);
338+
check_fma(cx, expr);
290339
}
291340
}
292341
}

clippy_lints/src/lib.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ pub mod exit;
208208
pub mod explicit_write;
209209
pub mod fallible_impl_from;
210210
pub mod float_literal;
211+
pub mod floating_point_arithmetic;
211212
pub mod format;
212213
pub mod formatting;
213214
pub mod functions;
@@ -248,7 +249,6 @@ pub mod missing_const_for_fn;
248249
pub mod missing_doc;
249250
pub mod missing_inline;
250251
pub mod modulo_arithmetic;
251-
pub mod mul_add;
252252
pub mod multiple_crate_versions;
253253
pub mod mut_key;
254254
pub mod mut_mut;
@@ -691,7 +691,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
691691
&missing_doc::MISSING_DOCS_IN_PRIVATE_ITEMS,
692692
&missing_inline::MISSING_INLINE_IN_PUBLIC_ITEMS,
693693
&modulo_arithmetic::MODULO_ARITHMETIC,
694-
&mul_add::MANUAL_MUL_ADD,
695694
&multiple_crate_versions::MULTIPLE_CRATE_VERSIONS,
696695
&mut_key::MUTABLE_KEY_TYPE,
697696
&mut_mut::MUT_MUT,
@@ -967,7 +966,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
967966
store.register_late_pass(|| box inherent_to_string::InherentToString);
968967
store.register_late_pass(|| box trait_bounds::TraitBounds);
969968
store.register_late_pass(|| box comparison_chain::ComparisonChain);
970-
store.register_late_pass(|| box mul_add::MulAddCheck);
971969
store.register_late_pass(|| box mut_key::MutableKeyType);
972970
store.register_late_pass(|| box modulo_arithmetic::ModuloArithmetic);
973971
store.register_early_pass(|| box reference::DerefAddrOf);
@@ -1652,7 +1650,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16521650
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
16531651
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
16541652
LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN),
1655-
LintId::of(&mul_add::MANUAL_MUL_ADD),
16561653
LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
16571654
LintId::of(&mutex_atomic::MUTEX_INTEGER),
16581655
LintId::of(&needless_borrow::NEEDLESS_BORROW),

clippy_lints/src/mul_add.rs

-111
This file was deleted.

src/lintlist/mod.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1022,13 +1022,6 @@ pub const ALL_LINTS: [Lint; 357] = [
10221022
deprecation: None,
10231023
module: "loops",
10241024
},
1025-
Lint {
1026-
name: "manual_mul_add",
1027-
group: "nursery",
1028-
desc: "Using `a.mul_add(b, c)` for floating points has higher numerical precision than `a * b + c`",
1029-
deprecation: None,
1030-
module: "mul_add",
1031-
},
10321025
Lint {
10331026
name: "manual_saturating_arithmetic",
10341027
group: "style",

tests/ui/floating_point_fma.fixed

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// run-rustfix
2+
#![warn(clippy::suboptimal_flops)]
3+
4+
fn main() {
5+
let a: f64 = 1234.567;
6+
let b: f64 = 45.67834;
7+
let c: f64 = 0.0004;
8+
let d: f64 = 0.0001;
9+
10+
let _ = a.mul_add(b, c);
11+
let _ = a.mul_add(b, c);
12+
let _ = 2.0f64.mul_add(4.0, a);
13+
let _ = 2.0f64.mul_add(4., a);
14+
15+
let _ = a.mul_add(b, c);
16+
let _ = a.mul_add(b, c);
17+
let _ = (a * b).mul_add(c, d);
18+
19+
let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c;
20+
let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64);
21+
}

tests/ui/floating_point_fma.rs

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// run-rustfix
2+
#![warn(clippy::suboptimal_flops)]
3+
4+
fn main() {
5+
let a: f64 = 1234.567;
6+
let b: f64 = 45.67834;
7+
let c: f64 = 0.0004;
8+
let d: f64 = 0.0001;
9+
10+
let _ = a * b + c;
11+
let _ = c + a * b;
12+
let _ = a + 2.0 * 4.0;
13+
let _ = a + 2. * 4.;
14+
15+
let _ = (a * b) + c;
16+
let _ = c + (a * b);
17+
let _ = a * b * c + d;
18+
19+
let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
20+
let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
21+
}

tests/ui/floating_point_fma.stderr

+58
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
error: multiply and add expressions can be calculated more efficiently and accurately
2+
--> $DIR/floating_point_fma.rs:10:13
3+
|
4+
LL | let _ = a * b + c;
5+
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
6+
|
7+
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
8+
9+
error: multiply and add expressions can be calculated more efficiently and accurately
10+
--> $DIR/floating_point_fma.rs:11:13
11+
|
12+
LL | let _ = c + a * b;
13+
| ^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
14+
15+
error: multiply and add expressions can be calculated more efficiently and accurately
16+
--> $DIR/floating_point_fma.rs:12:13
17+
|
18+
LL | let _ = a + 2.0 * 4.0;
19+
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)`
20+
21+
error: multiply and add expressions can be calculated more efficiently and accurately
22+
--> $DIR/floating_point_fma.rs:13:13
23+
|
24+
LL | let _ = a + 2. * 4.;
25+
| ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)`
26+
27+
error: multiply and add expressions can be calculated more efficiently and accurately
28+
--> $DIR/floating_point_fma.rs:15:13
29+
|
30+
LL | let _ = (a * b) + c;
31+
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
32+
33+
error: multiply and add expressions can be calculated more efficiently and accurately
34+
--> $DIR/floating_point_fma.rs:16:13
35+
|
36+
LL | let _ = c + (a * b);
37+
| ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)`
38+
39+
error: multiply and add expressions can be calculated more efficiently and accurately
40+
--> $DIR/floating_point_fma.rs:17:13
41+
|
42+
LL | let _ = a * b * c + d;
43+
| ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)`
44+
45+
error: multiply and add expressions can be calculated more efficiently and accurately
46+
--> $DIR/floating_point_fma.rs:19:13
47+
|
48+
LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
49+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))`
50+
51+
error: multiply and add expressions can be calculated more efficiently and accurately
52+
--> $DIR/floating_point_fma.rs:20:13
53+
|
54+
LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
55+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
56+
57+
error: aborting due to 9 previous errors
58+

0 commit comments

Comments
 (0)