Skip to content

Commit 71ff9a0

Browse files
committed
fix mul_add uncertain sugg
1 parent 76118ec commit 71ff9a0

File tree

4 files changed

+105
-3
lines changed

4 files changed

+105
-3
lines changed

clippy_lints/src/floating_point_arithmetic.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ use clippy_utils::{
77
};
88
use rustc_ast::ast;
99
use rustc_errors::Applicability;
10-
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
10+
use rustc_hir::def::Res;
11+
use rustc_hir::{BinOpKind, Expr, ExprKind, Node, PathSegment, UnOp};
1112
use rustc_lint::{LateContext, LateLintPass};
1213
use rustc_middle::ty;
1314
use rustc_session::declare_lint_pass;
@@ -455,7 +456,32 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&'
455456
None
456457
}
457458

458-
// TODO: Fix rust-lang/rust-clippy#4735
459+
// Check if any variable in an expression has an ambiguous type (could be f32 or f64)
460+
fn has_ambiguous_float_type(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
461+
match &expr.kind {
462+
ExprKind::Path(qpath) => {
463+
if let Res::Local(hir_id) = cx.qpath_res(qpath, expr.hir_id) {
464+
if let Node::LetStmt(local) = cx.tcx.parent_hir_node(hir_id) {
465+
// If the local has no type annotation and the initializer is an unsuffixed float literal,
466+
// then the type is ambiguous
467+
if local.ty.is_none() {
468+
if let Some(init) = local.init {
469+
if let ExprKind::Lit(lit) = &init.kind {
470+
if let ast::LitKind::Float(_, ast::LitFloatType::Unsuffixed) = lit.node {
471+
return true;
472+
}
473+
}
474+
}
475+
}
476+
}
477+
}
478+
false
479+
},
480+
ExprKind::Binary(_, lhs, rhs) => has_ambiguous_float_type(cx, lhs) || has_ambiguous_float_type(cx, rhs),
481+
_ => false,
482+
}
483+
}
484+
459485
fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
460486
if let ExprKind::Binary(
461487
Spanned {
@@ -491,6 +517,12 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
491517
return;
492518
};
493519

520+
// Check if any variable in the expression has an ambiguous type (could be f32 or f64)
521+
// see: https://github.com/rust-lang/rust-clippy/issues/14897
522+
if has_ambiguous_float_type(cx, recv) {
523+
return;
524+
}
525+
494526
span_lint_and_sugg(
495527
cx,
496528
SUBOPTIMAL_FLOPS,

tests/ui/floating_point_mul_add.fixed

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,23 @@ fn _issue11831() {
6969

7070
let _ = a + b * c;
7171
}
72+
73+
fn _issue12331() {
74+
let x = 1.0;
75+
let _ = x * 2.0 + 0.5; // should not suggest mul_add
76+
let _ = 0.5 + x * 2.0; // should not suggest mul_add
77+
78+
let _ = 2.0f64.mul_add(x, 0.5);
79+
//~^ suboptimal_flops
80+
let _ = 2.0f64.mul_add(x, 0.5);
81+
//~^ suboptimal_flops
82+
83+
let _ = 2.0f64.mul_add(4.0, x);
84+
//~^ suboptimal_flops
85+
86+
let y: f64 = 1.0;
87+
let _ = y.mul_add(2.0, 0.5);
88+
//~^ suboptimal_flops
89+
let _ = 1.0f64.mul_add(2.0, 0.5);
90+
//~^ suboptimal_flops
91+
}

tests/ui/floating_point_mul_add.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,23 @@ fn _issue11831() {
6969

7070
let _ = a + b * c;
7171
}
72+
73+
fn _issue14897() {
74+
let x = 1.0;
75+
let _ = x * 2.0 + 0.5; // should not suggest mul_add
76+
let _ = 0.5 + x * 2.0; // should not suggest mul_add
77+
78+
let _ = 0.5 + 2.0 * x;
79+
//~^ suboptimal_flops
80+
let _ = 2.0 * x + 0.5;
81+
//~^ suboptimal_flops
82+
83+
let _ = x + 2.0 * 4.0;
84+
//~^ suboptimal_flops
85+
86+
let y: f64 = 1.0;
87+
let _ = y * 2.0 + 0.5;
88+
//~^ suboptimal_flops
89+
let _ = 1.0 * 2.0 + 0.5;
90+
//~^ suboptimal_flops
91+
}

tests/ui/floating_point_mul_add.stderr

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,5 +79,35 @@ error: multiply and add expressions can be calculated more efficiently and accur
7979
LL | let _ = a - (b * u as f64);
8080
| ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)`
8181

82-
error: aborting due to 13 previous errors
82+
error: multiply and add expressions can be calculated more efficiently and accurately
83+
--> tests/ui/floating_point_mul_add.rs:78:13
84+
|
85+
LL | let _ = 0.5 + 2.0 * x;
86+
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(x, 0.5)`
87+
88+
error: multiply and add expressions can be calculated more efficiently and accurately
89+
--> tests/ui/floating_point_mul_add.rs:80:13
90+
|
91+
LL | let _ = 2.0 * x + 0.5;
92+
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(x, 0.5)`
93+
94+
error: multiply and add expressions can be calculated more efficiently and accurately
95+
--> tests/ui/floating_point_mul_add.rs:83:13
96+
|
97+
LL | let _ = x + 2.0 * 4.0;
98+
| ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, x)`
99+
100+
error: multiply and add expressions can be calculated more efficiently and accurately
101+
--> tests/ui/floating_point_mul_add.rs:87:13
102+
|
103+
LL | let _ = y * 2.0 + 0.5;
104+
| ^^^^^^^^^^^^^ help: consider using: `y.mul_add(2.0, 0.5)`
105+
106+
error: multiply and add expressions can be calculated more efficiently and accurately
107+
--> tests/ui/floating_point_mul_add.rs:89:13
108+
|
109+
LL | let _ = 1.0 * 2.0 + 0.5;
110+
| ^^^^^^^^^^^^^^^ help: consider using: `1.0f64.mul_add(2.0, 0.5)`
111+
112+
error: aborting due to 18 previous errors
83113

0 commit comments

Comments
 (0)