]> git.lizzy.rs Git - rust.git/commitdiff
Add `imprecise_flops` lint
authorKrishna Sai Veera Reddy <veerareddy@email.arizona.edu>
Mon, 24 Feb 2020 05:06:55 +0000 (21:06 -0800)
committerKrishna Sai Veera Reddy <veerareddy@email.arizona.edu>
Mon, 24 Feb 2020 06:36:15 +0000 (22:36 -0800)
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.

14 files changed:
CHANGELOG.md
README.md
clippy_lints/src/floating_point_arithmetic.rs
clippy_lints/src/lib.rs
src/lintlist/mod.rs
tests/ui/floating_point_exp.fixed
tests/ui/floating_point_exp.rs
tests/ui/floating_point_exp.stderr
tests/ui/floating_point_log.fixed
tests/ui/floating_point_log.rs
tests/ui/floating_point_log.stderr
tests/ui/floating_point_powf.fixed
tests/ui/floating_point_powf.rs
tests/ui/floating_point_powf.stderr

index ce696aa85501f17dc0944b0fc681cc09f4e0f544..99e84ea51931d2a5b18a09f2fbc99eece52754d8 100644 (file)
@@ -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
index 3103f960839899a29943f8064101c1d1d4e5cfff..1300c5ad47bf0bd2ba654770ae66ecf3aa03b8ed 100644 (file)
--- a/README.md
+++ b/README.md
@@ -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:
 
index 542ea5132de892d532417fee0ce1440ef40c2155..eed4f58cf902d82458c38bbe274df127b815cc71 100644 (file)
 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
     /// 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;
     /// ```
     /// 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);
     /// ```
     "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",
index 503eb9ec10d6e85389d2d946ea335f66496f2c96..c732657b2e57159c952c48487ec401f44ae7053a 100644 (file)
@@ -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),
index 5b4aad347af2029d67cca40801d7068115d1fe42..15e6a4b6036a7606969fda62247ab539d52e9f25 100644 (file)
@@ -6,7 +6,7 @@
 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",
         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",
index 1f534e3705d838ebcd4200dd9bd0fc1fb3011347..ae7805fdf018eea7228cecc02adcb4781173768e 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![warn(clippy::suboptimal_flops)]
+#![warn(clippy::imprecise_flops)]
 
 fn main() {
     let x = 2f32;
index bed8d31214085110f57ffef1cb6a1fb0baa3e896..27e0b9bcbc937a829e9e1d9ce7d7fb286c0c63d6 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![warn(clippy::suboptimal_flops)]
+#![warn(clippy::imprecise_flops)]
 
 fn main() {
     let x = 2f32;
index 7882b2c24e3aa87b3ff589d16db1e84b4a738d71..5cd999ad47cdd0d768138c901b1a9df01d891d8b 100644 (file)
@@ -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
index afe72a8dd110dce3f04531eea199994d1aa3e571..42c5e5d2bae2418c4330959aa559382a46f4940f 100644 (file)
@@ -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;
index 785b5a3bc4872980b06694264696f43c08b0541e..8be0d9ad56fc34fa07f120eda343a6ab61257047 100644 (file)
@@ -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;
index cb0bb6d652a8f12954f5bbd8bcb69f2291825727..943fbdb0b83232964312d49beedce567093ce20b 100644 (file)
@@ -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
index c5d900de32948b3f2e75987e7585ae918951c8c1..78a9d44829bb1ab708b1b39ed2fabffe2b3e24e4 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![warn(clippy::suboptimal_flops)]
+#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
 
 fn main() {
     let x = 3f32;
index cc75e230f7d003e7f195e790c5a95159b7f7a1bd..dbc1cac5cb4315cb03ceb516542e15b4aa8e21a9 100644 (file)
@@ -1,5 +1,5 @@
 // run-rustfix
-#![warn(clippy::suboptimal_flops)]
+#![warn(clippy::suboptimal_flops, clippy::imprecise_flops)]
 
 fn main() {
     let x = 3f32;
index 8f0544d4b582bb129b9a073af903fed1b9142457..ad5163f0079be937ae34e629eaa5a5148c17190a 100644 (file)
@@ -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