mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-22 20:53:21 +00:00
Add imprecise_flops
lint
Add lint to detect floating point operations that can be computed more accurately at the cost of performance. `cbrt`, `ln_1p` and `exp_m1` library functions call their equivalent cmath implementations which is slower but more accurate so moving checks for these under this new lint.
This commit is contained in:
parent
e94a167508
commit
ff0d44e45a
14 changed files with 67 additions and 20 deletions
|
@ -1169,6 +1169,7 @@ Released 2018-09-13
|
|||
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
|
||||
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
|
||||
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
|
||||
[`imprecise_flops`]: https://rust-lang.github.io/rust-clippy/master/index.html#imprecise_flops
|
||||
[`inconsistent_digit_grouping`]: https://rust-lang.github.io/rust-clippy/master/index.html#inconsistent_digit_grouping
|
||||
[`indexing_slicing`]: https://rust-lang.github.io/rust-clippy/master/index.html#indexing_slicing
|
||||
[`ineffective_bit_mask`]: https://rust-lang.github.io/rust-clippy/master/index.html#ineffective_bit_mask
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
|
||||
|
||||
[There are 357 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
[There are 358 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
|
||||
|
||||
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
|
||||
|
||||
|
|
|
@ -16,6 +16,39 @@ use std::f64::consts as f64_consts;
|
|||
use sugg::{format_numeric_literal, Sugg};
|
||||
use syntax::ast;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Looks for floating-point expressions that
|
||||
/// can be expressed using built-in methods to improve accuracy
|
||||
/// at the cost of performance.
|
||||
///
|
||||
/// **Why is this bad?** Negatively impacts accuracy.
|
||||
///
|
||||
/// **Known problems:** None
|
||||
///
|
||||
/// **Example:**
|
||||
///
|
||||
/// ```rust
|
||||
///
|
||||
/// let a = 3f32;
|
||||
/// let _ = a.powf(1.0 / 3.0);
|
||||
/// let _ = (1.0 + a).ln();
|
||||
/// let _ = a.exp() - 1.0;
|
||||
/// ```
|
||||
///
|
||||
/// is better expressed as
|
||||
///
|
||||
/// ```rust
|
||||
///
|
||||
/// let a = 3f32;
|
||||
/// let _ = a.cbrt();
|
||||
/// let _ = a.ln_1p();
|
||||
/// let _ = a.exp_m1();
|
||||
/// ```
|
||||
pub IMPRECISE_FLOPS,
|
||||
nursery,
|
||||
"usage of imprecise floating point operations"
|
||||
}
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Looks for floating-point expressions that
|
||||
/// can be expressed using built-in methods to improve both
|
||||
|
@ -34,12 +67,9 @@ declare_clippy_lint! {
|
|||
/// let _ = (2f32).powf(a);
|
||||
/// let _ = E.powf(a);
|
||||
/// let _ = a.powf(1.0 / 2.0);
|
||||
/// let _ = a.powf(1.0 / 3.0);
|
||||
/// let _ = a.log(2.0);
|
||||
/// let _ = a.log(10.0);
|
||||
/// let _ = a.log(E);
|
||||
/// let _ = (1.0 + a).ln();
|
||||
/// let _ = a.exp() - 1.0;
|
||||
/// let _ = a.powf(2.0);
|
||||
/// let _ = a * 2.0 + 4.0;
|
||||
/// ```
|
||||
|
@ -53,12 +83,9 @@ declare_clippy_lint! {
|
|||
/// let _ = a.exp2();
|
||||
/// let _ = a.exp();
|
||||
/// let _ = a.sqrt();
|
||||
/// let _ = a.cbrt();
|
||||
/// let _ = a.log2();
|
||||
/// let _ = a.log10();
|
||||
/// let _ = a.ln();
|
||||
/// let _ = a.ln_1p();
|
||||
/// let _ = a.exp_m1();
|
||||
/// let _ = a.powi(2);
|
||||
/// let _ = a.mul_add(2.0, 4.0);
|
||||
/// ```
|
||||
|
@ -67,7 +94,10 @@ declare_clippy_lint! {
|
|||
"usage of sub-optimal floating point operations"
|
||||
}
|
||||
|
||||
declare_lint_pass!(FloatingPointArithmetic => [SUBOPTIMAL_FLOPS]);
|
||||
declare_lint_pass!(FloatingPointArithmetic => [
|
||||
IMPRECISE_FLOPS,
|
||||
SUBOPTIMAL_FLOPS
|
||||
]);
|
||||
|
||||
// Returns the specialized log method for a given base if base is constant
|
||||
// and is one of 2, 10 and e
|
||||
|
@ -156,7 +186,7 @@ fn check_ln1p(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
|||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
IMPRECISE_FLOPS,
|
||||
expr.span,
|
||||
"ln(1 + x) can be computed more accurately",
|
||||
"consider using",
|
||||
|
@ -215,18 +245,21 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
|||
|
||||
// Check argument
|
||||
if let Some((value, _)) = constant(cx, cx.tables, &args[1]) {
|
||||
let (help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
|
||||
let (lint, help, suggestion) = if F32(1.0 / 2.0) == value || F64(1.0 / 2.0) == value {
|
||||
(
|
||||
SUBOPTIMAL_FLOPS,
|
||||
"square-root of a number can be computed more efficiently and accurately",
|
||||
format!("{}.sqrt()", Sugg::hir(cx, &args[0], "..")),
|
||||
)
|
||||
} else if F32(1.0 / 3.0) == value || F64(1.0 / 3.0) == value {
|
||||
(
|
||||
IMPRECISE_FLOPS,
|
||||
"cube-root of a number can be computed more accurately",
|
||||
format!("{}.cbrt()", Sugg::hir(cx, &args[0], "..")),
|
||||
)
|
||||
} else if let Some(exponent) = get_integer_from_float_constant(&value) {
|
||||
(
|
||||
SUBOPTIMAL_FLOPS,
|
||||
"exponentiation with integer powers can be computed more efficiently",
|
||||
format!(
|
||||
"{}.powi({})",
|
||||
|
@ -240,7 +273,7 @@ fn check_powf(cx: &LateContext<'_, '_>, expr: &Expr<'_>, args: &[Expr<'_>]) {
|
|||
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
lint,
|
||||
expr.span,
|
||||
help,
|
||||
"consider using",
|
||||
|
@ -264,7 +297,7 @@ fn check_expm1(cx: &LateContext<'_, '_>, expr: &Expr<'_>) {
|
|||
then {
|
||||
span_lint_and_sugg(
|
||||
cx,
|
||||
SUBOPTIMAL_FLOPS,
|
||||
IMPRECISE_FLOPS,
|
||||
expr.span,
|
||||
"(e.pow(x) - 1) can be computed more accurately",
|
||||
"consider using",
|
||||
|
|
|
@ -538,6 +538,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
&fallible_impl_from::FALLIBLE_IMPL_FROM,
|
||||
&float_literal::EXCESSIVE_PRECISION,
|
||||
&float_literal::LOSSY_FLOAT_LITERAL,
|
||||
&floating_point_arithmetic::IMPRECISE_FLOPS,
|
||||
&floating_point_arithmetic::SUBOPTIMAL_FLOPS,
|
||||
&format::USELESS_FORMAT,
|
||||
&formatting::POSSIBLE_MISSING_COMMA,
|
||||
|
@ -1648,6 +1649,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||
store.register_group(true, "clippy::nursery", Some("clippy_nursery"), vec![
|
||||
LintId::of(&attrs::EMPTY_LINE_AFTER_OUTER_ATTR),
|
||||
LintId::of(&fallible_impl_from::FALLIBLE_IMPL_FROM),
|
||||
LintId::of(&floating_point_arithmetic::IMPRECISE_FLOPS),
|
||||
LintId::of(&floating_point_arithmetic::SUBOPTIMAL_FLOPS),
|
||||
LintId::of(&missing_const_for_fn::MISSING_CONST_FOR_FN),
|
||||
LintId::of(&mutable_debug_assertion::DEBUG_ASSERT_WITH_MUT_CALL),
|
||||
|
|
|
@ -6,7 +6,7 @@ pub use lint::Lint;
|
|||
pub use lint::LINT_LEVELS;
|
||||
|
||||
// begin lint list, do not remove this comment, it’s used in `update_lints`
|
||||
pub const ALL_LINTS: [Lint; 357] = [
|
||||
pub const ALL_LINTS: [Lint; 358] = [
|
||||
Lint {
|
||||
name: "absurd_extreme_comparisons",
|
||||
group: "correctness",
|
||||
|
@ -749,6 +749,13 @@ pub const ALL_LINTS: [Lint; 357] = [
|
|||
deprecation: None,
|
||||
module: "implicit_return",
|
||||
},
|
||||
Lint {
|
||||
name: "imprecise_flops",
|
||||
group: "nursery",
|
||||
desc: "usage of imprecise floating point operations",
|
||||
deprecation: None,
|
||||
module: "floating_point_arithmetic",
|
||||
},
|
||||
Lint {
|
||||
name: "inconsistent_digit_grouping",
|
||||
group: "style",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
#![warn(clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 2f32;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
#![warn(clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 2f32;
|
||||
|
|
|
@ -4,7 +4,7 @@ error: (e.pow(x) - 1) can be computed more accurately
|
|||
LL | let _ = x.exp() - 1.0;
|
||||
| ^^^^^^^^^^^^^ help: consider using: `x.exp_m1()`
|
||||
|
|
||||
= note: `-D clippy::suboptimal-flops` implied by `-D warnings`
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
error: (e.pow(x) - 1) can be computed more accurately
|
||||
--> $DIR/floating_point_exp.rs:7:13
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// run-rustfix
|
||||
#![allow(dead_code, clippy::double_parens)]
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
const TWO: f32 = 2.0;
|
||||
const E: f32 = std::f32::consts::E;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
// run-rustfix
|
||||
#![allow(dead_code, clippy::double_parens)]
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
const TWO: f32 = 2.0;
|
||||
const E: f32 = std::f32::consts::E;
|
||||
|
|
|
@ -53,6 +53,8 @@ error: ln(1 + x) can be computed more accurately
|
|||
|
|
||||
LL | let _ = (1f32 + 2.).ln();
|
||||
| ^^^^^^^^^^^^^^^^ help: consider using: `2.0f32.ln_1p()`
|
||||
|
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
error: ln(1 + x) can be computed more accurately
|
||||
--> $DIR/floating_point_log.rs:25:13
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// run-rustfix
|
||||
#![warn(clippy::suboptimal_flops)]
|
||||
#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
|
||||
|
||||
fn main() {
|
||||
let x = 3f32;
|
||||
|
|
|
@ -47,6 +47,8 @@ error: cube-root of a number can be computed more accurately
|
|||
|
|
||||
LL | let _ = x.powf(1.0 / 3.0);
|
||||
| ^^^^^^^^^^^^^^^^^ help: consider using: `x.cbrt()`
|
||||
|
|
||||
= note: `-D clippy::imprecise-flops` implied by `-D warnings`
|
||||
|
||||
error: exponentiation with integer powers can be computed more efficiently
|
||||
--> $DIR/floating_point_powf.rs:14:13
|
||||
|
|
Loading…
Reference in a new issue