Rollup merge of #5443 - thiagoarrais:issue-2040, r=flip1995

Some accuracy lints for floating point operations

This will add some lints for accuracy on floating point operations suggested by @clarfon in #2040 (fixes #2040).

These are the remaining lints:

- [x] x.powi(2) => x * x
- [x] x.logN() / y.logN() => x.logbase(y)
- [x] x.logbase(E) => x.log()
- [x] x.logbase(10) => x.log10()
- [x] x.logbase(2) => x.log2().
- [x] x * PI / 180 => x.to_radians()
- [x] x * 180 / PI => x.to_degrees()
- [x] (x + 1).log() => x.log_1p()
- [x] sqrt(x * x + y * y) => x.hypot(y)

changelog: Included some accuracy lints for floating point operations
This commit is contained in:
Philipp Krones 2020-07-13 15:59:41 +02:00 committed by GitHub
commit 75d43aac73
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
22 changed files with 499 additions and 32 deletions

View File

@ -1,11 +1,11 @@
use crate::consts::{
constant, constant_simple, Constant,
Constant::{F32, F64},
Constant::{Int, F32, F64},
};
use crate::utils::{higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
use crate::utils::{get_parent_expr, higher, numeric_literal, span_lint_and_sugg, sugg, SpanlessEq};
use if_chain::if_chain;
use rustc_errors::Applicability;
use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp};
use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment, UnOp};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty;
use rustc_session::{declare_lint_pass, declare_tool_lint};
@ -293,6 +293,121 @@ fn check_powf(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
}
}
fn check_powi(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
if let Some((value, _)) = constant(cx, cx.tables(), &args[1]) {
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;
}
}
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], "..")),
Applicability::MachineApplicable,
);
}
}
}
fn detect_hypot(cx: &LateContext<'_>, args: &[Expr<'_>]) -> Option<String> {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Add, ..
},
ref add_lhs,
ref add_rhs,
) = args[0].kind
{
// check if expression of the form x * x + y * y
if_chain! {
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref lmul_lhs, ref lmul_rhs) = add_lhs.kind;
if let ExprKind::Binary(Spanned { node: BinOpKind::Mul, .. }, ref rmul_lhs, ref rmul_rhs) = add_rhs.kind;
if are_exprs_equal(cx, lmul_lhs, lmul_rhs);
if are_exprs_equal(cx, rmul_lhs, rmul_rhs);
then {
return Some(format!("{}.hypot({})", Sugg::hir(cx, &lmul_lhs, ".."), Sugg::hir(cx, &rmul_lhs, "..")));
}
}
// check if expression of the form x.powi(2) + y.powi(2)
if_chain! {
if let ExprKind::MethodCall(
PathSegment { ident: lmethod_name, .. },
ref _lspan,
ref largs,
_
) = add_lhs.kind;
if let ExprKind::MethodCall(
PathSegment { ident: rmethod_name, .. },
ref _rspan,
ref rargs,
_
) = add_rhs.kind;
if lmethod_name.as_str() == "powi" && rmethod_name.as_str() == "powi";
if let Some((lvalue, _)) = constant(cx, cx.tables(), &largs[1]);
if let Some((rvalue, _)) = constant(cx, cx.tables(), &rargs[1]);
if Int(2) == lvalue && Int(2) == rvalue;
then {
return Some(format!("{}.hypot({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], "..")));
}
}
}
None
}
fn check_hypot(cx: &LateContext<'_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
if let Some(message) = detect_hypot(cx, args) {
span_lint_and_sugg(
cx,
IMPRECISE_FLOPS,
expr.span,
"hypotenuse can be computed more accurately",
"consider using",
message,
Applicability::MachineApplicable,
);
}
}
// TODO: Lint expressions of the form `x.exp() - y` where y > 1
// and suggest usage of `x.exp_m1() - (y - 1)` instead
fn check_expm1(cx: &LateContext<'_>, expr: &Expr<'_>) {
@ -344,6 +459,14 @@ fn check_mul_add(cx: &LateContext<'_>, expr: &Expr<'_>) {
rhs,
) = &expr.kind
{
if let Some(parent) = get_parent_expr(cx, expr) {
if let ExprKind::MethodCall(PathSegment { ident: method_name, .. }, _, args, _) = parent.kind {
if method_name.as_str() == "sqrt" && detect_hypot(cx, args).is_some() {
return;
}
}
}
let (recv, arg1, arg2) = if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, lhs) {
(inner_lhs, inner_rhs, rhs)
} else if let Some((inner_lhs, inner_rhs)) = is_float_mul_expr(cx, rhs) {
@ -479,6 +602,100 @@ fn check_custom_abs(cx: &LateContext<'_>, expr: &Expr<'_>) {
}
}
fn are_same_base_logs(cx: &LateContext<'_>, expr_a: &Expr<'_>, expr_b: &Expr<'_>) -> bool {
if_chain! {
if let ExprKind::MethodCall(PathSegment { ident: method_name_a, .. }, _, ref args_a, _) = expr_a.kind;
if let ExprKind::MethodCall(PathSegment { ident: method_name_b, .. }, _, ref args_b, _) = expr_b.kind;
then {
return method_name_a.as_str() == method_name_b.as_str() &&
args_a.len() == args_b.len() &&
(
["ln", "log2", "log10"].contains(&&*method_name_a.as_str()) ||
method_name_a.as_str() == "log" && args_a.len() == 2 && are_exprs_equal(cx, &args_a[1], &args_b[1])
);
}
}
false
}
fn check_log_division(cx: &LateContext<'_>, expr: &Expr<'_>) {
// check if expression of the form x.logN() / y.logN()
if_chain! {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Div, ..
},
lhs,
rhs,
) = &expr.kind;
if are_same_base_logs(cx, lhs, rhs);
if let ExprKind::MethodCall(_, _, ref largs, _) = lhs.kind;
if let ExprKind::MethodCall(_, _, ref rargs, _) = rhs.kind;
then {
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"log base can be expressed more clearly",
"consider using",
format!("{}.log({})", Sugg::hir(cx, &largs[0], ".."), Sugg::hir(cx, &rargs[0], ".."),),
Applicability::MachineApplicable,
);
}
}
}
fn check_radians(cx: &LateContext<'_>, expr: &Expr<'_>) {
if_chain! {
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Div, ..
},
div_lhs,
div_rhs,
) = &expr.kind;
if let ExprKind::Binary(
Spanned {
node: BinOpKind::Mul, ..
},
mul_lhs,
mul_rhs,
) = &div_lhs.kind;
if let Some((rvalue, _)) = constant(cx, cx.tables(), div_rhs);
if let Some((lvalue, _)) = constant(cx, cx.tables(), mul_rhs);
then {
// TODO: also check for constant values near PI/180 or 180/PI
if (F32(f32_consts::PI) == rvalue || F64(f64_consts::PI) == rvalue) &&
(F32(180_f32) == lvalue || F64(180_f64) == lvalue)
{
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"conversion to degrees can be done more accurately",
"consider using",
format!("{}.to_degrees()", Sugg::hir(cx, &mul_lhs, "..")),
Applicability::MachineApplicable,
);
} else if
(F32(180_f32) == rvalue || F64(180_f64) == rvalue) &&
(F32(f32_consts::PI) == lvalue || F64(f64_consts::PI) == lvalue)
{
span_lint_and_sugg(
cx,
SUBOPTIMAL_FLOPS,
expr.span,
"conversion to radians can be done more accurately",
"consider using",
format!("{}.to_radians()", Sugg::hir(cx, &mul_lhs, "..")),
Applicability::MachineApplicable,
);
}
}
}
}
impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if let ExprKind::MethodCall(ref path, _, args, _) = &expr.kind {
@ -489,6 +706,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
"ln" => check_ln1p(cx, expr, args),
"log" => check_log_base(cx, expr, args),
"powf" => check_powf(cx, expr, args),
"powi" => check_powi(cx, expr, args),
"sqrt" => check_hypot(cx, expr, args),
_ => {},
}
}
@ -496,6 +715,8 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic {
check_expm1(cx, expr);
check_mul_add(cx, expr);
check_custom_abs(cx, expr);
check_log_division(cx, expr);
check_radians(cx, expr);
}
}
}

View File

@ -0,0 +1,14 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
fn main() {
let x = 3f32;
let y = 4f32;
let _ = x.hypot(y);
let _ = (x + 1f32).hypot(y);
let _ = x.hypot(y);
// Cases where the lint shouldn't be applied
// TODO: linting this adds some complexity, but could be done
let _ = x.mul_add(x, y * y).sqrt();
let _ = (x * 4f32 + y * y).sqrt();
}

View File

@ -0,0 +1,14 @@
// run-rustfix
#![warn(clippy::imprecise_flops)]
fn main() {
let x = 3f32;
let y = 4f32;
let _ = (x * x + y * y).sqrt();
let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt();
let _ = (x.powi(2) + y.powi(2)).sqrt();
// Cases where the lint shouldn't be applied
// TODO: linting this adds some complexity, but could be done
let _ = x.mul_add(x, y * y).sqrt();
let _ = (x * 4f32 + y * y).sqrt();
}

View File

@ -0,0 +1,22 @@
error: hypotenuse can be computed more accurately
--> $DIR/floating_point_hypot.rs:7:13
|
LL | let _ = (x * x + y * y).sqrt();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)`
|
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
error: hypotenuse can be computed more accurately
--> $DIR/floating_point_hypot.rs:8:13
|
LL | let _ = ((x + 1f32) * (x + 1f32) + y * y).sqrt();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x + 1f32).hypot(y)`
error: hypotenuse can be computed more accurately
--> $DIR/floating_point_hypot.rs:9:13
|
LL | let _ = (x.powi(2) + y.powi(2)).sqrt();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.hypot(y)`
error: aborting due to 3 previous errors

View File

@ -25,11 +25,11 @@ fn check_ln1p() {
let _ = 2.0f32.ln_1p();
let _ = x.ln_1p();
let _ = (x / 2.0).ln_1p();
let _ = x.powi(2).ln_1p();
let _ = (x.powi(2) / 2.0).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = (x.powi(3) / 2.0).ln_1p();
let _ = ((std::f32::consts::E - 1.0)).ln_1p();
let _ = x.ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = (x + 2.0).ln_1p();
let _ = (x / 2.0).ln_1p();
// Cases where the lint shouldn't be applied
@ -43,9 +43,9 @@ fn check_ln1p() {
let _ = 2.0f64.ln_1p();
let _ = x.ln_1p();
let _ = (x / 2.0).ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = x.ln_1p();
let _ = x.powi(2).ln_1p();
let _ = x.powi(3).ln_1p();
let _ = (x + 2.0).ln_1p();
let _ = (x / 2.0).ln_1p();
// Cases where the lint shouldn't be applied

View File

@ -25,11 +25,11 @@ fn check_ln1p() {
let _ = (1f32 + 2.0).ln();
let _ = (1.0 + x).ln();
let _ = (1.0 + x / 2.0).ln();
let _ = (1.0 + x.powi(2)).ln();
let _ = (1.0 + x.powi(2) / 2.0).ln();
let _ = (1.0 + x.powi(3)).ln();
let _ = (1.0 + x.powi(3) / 2.0).ln();
let _ = (1.0 + (std::f32::consts::E - 1.0)).ln();
let _ = (x + 1.0).ln();
let _ = (x.powi(2) + 1.0).ln();
let _ = (x.powi(3) + 1.0).ln();
let _ = (x + 2.0 + 1.0).ln();
let _ = (x / 2.0 + 1.0).ln();
// Cases where the lint shouldn't be applied
@ -43,9 +43,9 @@ fn check_ln1p() {
let _ = (1f64 + 2.0).ln();
let _ = (1.0 + x).ln();
let _ = (1.0 + x / 2.0).ln();
let _ = (1.0 + x.powi(2)).ln();
let _ = (1.0 + x.powi(3)).ln();
let _ = (x + 1.0).ln();
let _ = (x.powi(2) + 1.0).ln();
let _ = (x.powi(3) + 1.0).ln();
let _ = (x + 2.0 + 1.0).ln();
let _ = (x / 2.0 + 1.0).ln();
// Cases where the lint shouldn't be applied

View File

@ -77,14 +77,14 @@ LL | let _ = (1.0 + x / 2.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:28:13
|
LL | let _ = (1.0 + x.powi(2)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (1.0 + x.powi(3)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:29:13
|
LL | let _ = (1.0 + x.powi(2) / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(2) / 2.0).ln_1p()`
LL | let _ = (1.0 + x.powi(3) / 2.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(x.powi(3) / 2.0).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:30:13
@ -101,8 +101,8 @@ LL | let _ = (x + 1.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:32:13
|
LL | let _ = (x.powi(2) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (x.powi(3) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:33:13
@ -143,8 +143,8 @@ LL | let _ = (1.0 + x / 2.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:46:13
|
LL | let _ = (1.0 + x.powi(2)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (1.0 + x.powi(3)).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:47:13
@ -155,8 +155,8 @@ LL | let _ = (x + 1.0).ln();
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:48:13
|
LL | let _ = (x.powi(2) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(2).ln_1p()`
LL | let _ = (x.powi(3) + 1.0).ln();
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.powi(3).ln_1p()`
error: ln(1 + x) can be computed more accurately
--> $DIR/floating_point_log.rs:49:13

View File

@ -0,0 +1,16 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let x = 3f32;
let y = 5f32;
let _ = x.log(y);
let _ = x.log(y);
let _ = x.log(y);
let _ = x.log(y);
// Cases where the lint shouldn't be applied
let _ = x.ln() / y.powf(3.2);
let _ = x.powf(3.2) / y.powf(3.2);
let _ = x.powf(3.2) / y.ln();
let _ = x.log(5f32) / y.log(7f32);
}

View File

@ -0,0 +1,16 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let x = 3f32;
let y = 5f32;
let _ = x.ln() / y.ln();
let _ = x.log2() / y.log2();
let _ = x.log10() / y.log10();
let _ = x.log(5f32) / y.log(5f32);
// Cases where the lint shouldn't be applied
let _ = x.ln() / y.powf(3.2);
let _ = x.powf(3.2) / y.powf(3.2);
let _ = x.powf(3.2) / y.ln();
let _ = x.log(5f32) / y.log(7f32);
}

View File

@ -0,0 +1,28 @@
error: log base can be expressed more clearly
--> $DIR/floating_point_logbase.rs:7:13
|
LL | let _ = x.ln() / y.ln();
| ^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
|
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: log base can be expressed more clearly
--> $DIR/floating_point_logbase.rs:8:13
|
LL | let _ = x.log2() / y.log2();
| ^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
error: log base can be expressed more clearly
--> $DIR/floating_point_logbase.rs:9:13
|
LL | let _ = x.log10() / y.log10();
| ^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
error: log base can be expressed more clearly
--> $DIR/floating_point_logbase.rs:10:13
|
LL | let _ = x.log(5f32) / y.log(5f32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.log(y)`
error: aborting due to 4 previous errors

View File

@ -18,4 +18,9 @@ fn main() {
let _ = a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c)) + c;
let _ = 1234.567_f64.mul_add(45.67834_f64, 0.0004_f64);
let _ = a.mul_add(a, b).sqrt();
// Cases where the lint shouldn't be applied
let _ = (a * a + b * b).sqrt();
}

View File

@ -18,4 +18,9 @@ fn main() {
let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c;
let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
let _ = (a * a + b).sqrt();
// Cases where the lint shouldn't be applied
let _ = (a * a + b * b).sqrt();
}

View File

@ -54,5 +54,11 @@ error: multiply and add expressions can be calculated more efficiently and accur
LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)`
error: aborting due to 9 previous errors
error: multiply and add expressions can be calculated more efficiently and accurately
--> $DIR/floating_point_mul_add.rs:22:13
|
LL | let _ = (a * a + b).sqrt();
| ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)`
error: aborting due to 10 previous errors

View File

@ -11,7 +11,7 @@ fn main() {
let _ = (-3.1f32).exp();
let _ = x.sqrt();
let _ = x.cbrt();
let _ = x.powi(2);
let _ = x.powi(3);
let _ = x.powi(-2);
let _ = x.powi(16_777_215);
let _ = x.powi(-16_777_215);
@ -30,7 +30,7 @@ fn main() {
let _ = (-3.1f64).exp();
let _ = x.sqrt();
let _ = x.cbrt();
let _ = x.powi(2);
let _ = x.powi(3);
let _ = x.powi(-2);
let _ = x.powi(-2_147_483_648);
let _ = x.powi(2_147_483_647);

View File

@ -11,7 +11,7 @@ fn main() {
let _ = std::f32::consts::E.powf(-3.1);
let _ = x.powf(1.0 / 2.0);
let _ = x.powf(1.0 / 3.0);
let _ = x.powf(2.0);
let _ = x.powf(3.0);
let _ = x.powf(-2.0);
let _ = x.powf(16_777_215.0);
let _ = x.powf(-16_777_215.0);
@ -30,7 +30,7 @@ fn main() {
let _ = std::f64::consts::E.powf(-3.1);
let _ = x.powf(1.0 / 2.0);
let _ = x.powf(1.0 / 3.0);
let _ = x.powf(2.0);
let _ = x.powf(3.0);
let _ = x.powf(-2.0);
let _ = x.powf(-2_147_483_648.0);
let _ = x.powf(2_147_483_647.0);

View File

@ -53,8 +53,8 @@ LL | let _ = x.powf(1.0 / 3.0);
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:14:13
|
LL | let _ = x.powf(2.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:15:13
@ -125,8 +125,8 @@ LL | let _ = x.powf(1.0 / 3.0);
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:33:13
|
LL | let _ = x.powf(2.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(2)`
LL | let _ = x.powf(3.0);
| ^^^^^^^^^^^ help: consider using: `x.powi(3)`
error: exponentiation with integer powers can be computed more efficiently
--> $DIR/floating_point_powf.rs:34:13

View File

@ -0,0 +1,19 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let one = 1;
let x = 3f32;
let _ = x * x;
let _ = x * x;
let y = 4f32;
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.powi(2) + y.powi(2)).sqrt();
}

View File

@ -0,0 +1,19 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let one = 1;
let x = 3f32;
let _ = x.powi(2);
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
let _ = x.powi(3);
let _ = x.powi(one + 1);
let _ = (x.powi(2) + y.powi(2)).sqrt();
}

View File

@ -0,0 +1,40 @@
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::suboptimal-flops` implied by `-D warnings`
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 efficiently
--> $DIR/floating_point_powi.rs:11:13
|
LL | let _ = x.powi(2) + y;
| ^^^^^^^^^^^^^ help: consider using: `x.mul_add(x, y)`
error: square can be computed more efficiently
--> $DIR/floating_point_powi.rs:12:13
|
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: square can be computed more efficiently
--> $DIR/floating_point_powi.rs:14:13
|
LL | let _ = (x + y.powi(2)).sqrt();
| ^^^^^^^^^^^^^^^ help: consider using: `y.mul_add(y, x)`
error: aborting due to 6 previous errors

View File

@ -0,0 +1,13 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let x = 3f32;
let _ = x.to_degrees();
let _ = x.to_radians();
// Cases where the lint shouldn't be applied
let _ = x * 90f32 / std::f32::consts::PI;
let _ = x * std::f32::consts::PI / 90f32;
let _ = x * 180f32 / std::f32::consts::E;
let _ = x * std::f32::consts::E / 180f32;
}

View File

@ -0,0 +1,13 @@
// run-rustfix
#![warn(clippy::suboptimal_flops)]
fn main() {
let x = 3f32;
let _ = x * 180f32 / std::f32::consts::PI;
let _ = x * std::f32::consts::PI / 180f32;
// Cases where the lint shouldn't be applied
let _ = x * 90f32 / std::f32::consts::PI;
let _ = x * std::f32::consts::PI / 90f32;
let _ = x * 180f32 / std::f32::consts::E;
let _ = x * std::f32::consts::E / 180f32;
}

View File

@ -0,0 +1,16 @@
error: conversion to degrees can be done more accurately
--> $DIR/floating_point_rad.rs:6:13
|
LL | let _ = x * 180f32 / std::f32::consts::PI;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()`
|
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
error: conversion to radians can be done more accurately
--> $DIR/floating_point_rad.rs:7:13
|
LL | let _ = x * std::f32::consts::PI / 180f32;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()`
error: aborting due to 2 previous errors