about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-06-12 13:19:26 +0000
committerbors <bors@rust-lang.org>2019-06-12 13:19:26 +0000
commita1eb60f8ea46c99cab2be80772915506b4ce9cee (patch)
tree120dc98d6d53d1353c75349ea5c4581d68077a23
parentcefddf784373392768b84ebec7be4c697d0b029a (diff)
parentb364eb7b54b67a4a582a67648a51363bc9407904 (diff)
downloadrust-a1eb60f8ea46c99cab2be80772915506b4ce9cee.tar.gz
rust-a1eb60f8ea46c99cab2be80772915506b4ce9cee.zip
Auto merge of #4195 - thiagoarrais:division-of-integer-literals, r=flip1995
Adds lint for integer division

Hi, folks! This is my first contribution to clippy and my first real piece of Rust code.

This is supposed to add a lint that warns for division of integers (#109). Please let me know if you need any changes.

Fixes #109

changelog: Add lint for integer division
-rw-r--r--CHANGELOG.md1
-rw-r--r--README.md2
-rw-r--r--clippy_lints/src/cognitive_complexity.rs3
-rw-r--r--clippy_lints/src/integer_division.rs55
-rw-r--r--clippy_lints/src/lib.rs3
-rw-r--r--clippy_lints/src/trivially_copy_pass_by_ref.rs1
-rw-r--r--tests/ui/integer_division.rs9
-rw-r--r--tests/ui/integer_division.stderr27
8 files changed, 99 insertions, 2 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b63111cab72..5f34d24cd47 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -956,6 +956,7 @@ All notable changes to this project will be documented in this file.
 [`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
 [`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
 [`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic
+[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
 [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
 [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
 [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref
diff --git a/README.md b/README.md
index c25c83d8752..4c2e65300a6 100644
--- a/README.md
+++ b/README.md
@@ -7,7 +7,7 @@
 
 A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
 
-[There are 304 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
+[There are 305 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:
 
diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs
index 38d7307a187..f01322768fa 100644
--- a/clippy_lints/src/cognitive_complexity.rs
+++ b/clippy_lints/src/cognitive_complexity.rs
@@ -74,7 +74,8 @@ impl CognitiveComplexity {
         let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
             returns
         } else {
-            returns / 2
+            #[allow(clippy::integer_division)]
+            (returns / 2)
         };
 
         if cc + divergence < match_arms + short_circuits {
diff --git a/clippy_lints/src/integer_division.rs b/clippy_lints/src/integer_division.rs
new file mode 100644
index 00000000000..12dcfa6f661
--- /dev/null
+++ b/clippy_lints/src/integer_division.rs
@@ -0,0 +1,55 @@
+use crate::utils::span_help_and_lint;
+use if_chain::if_chain;
+use rustc::hir;
+use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
+use rustc::{declare_lint_pass, declare_tool_lint};
+
+declare_clippy_lint! {
+    /// **What it does:** Checks for division of integers
+    ///
+    /// **Why is this bad?** When outside of some very specific algorithms,
+    /// integer division is very often a mistake because it discards the
+    /// remainder.
+    ///
+    /// **Known problems:** None.
+    ///
+    /// **Example:**
+    /// ```rust
+    /// fn main() {
+    ///     let x = 3 / 2;
+    ///     println!("{}", x);
+    /// }
+    /// ```
+    pub INTEGER_DIVISION,
+    pedantic,
+    "integer division may cause loss of precision"
+}
+
+declare_lint_pass!(IntegerDivision => [INTEGER_DIVISION]);
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IntegerDivision {
+    fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
+        if is_integer_division(cx, expr) {
+            span_help_and_lint(
+                cx,
+                INTEGER_DIVISION,
+                expr.span,
+                "integer division",
+                "division of integers may cause loss of precision. consider using floats.",
+            );
+        }
+    }
+}
+
+fn is_integer_division<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) -> bool {
+    if_chain! {
+        if let hir::ExprKind::Binary(binop, left, right) = &expr.node;
+        if let hir::BinOpKind::Div = &binop.node;
+        then {
+            let (left_ty, right_ty) = (cx.tables.expr_ty(left), cx.tables.expr_ty(right));
+            return left_ty.is_integral() && right_ty.is_integral();
+        }
+    }
+
+    false
+}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index eaf8f9b5710..2bec5cb2d01 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -197,6 +197,7 @@ pub mod infinite_iter;
 pub mod inherent_impl;
 pub mod inline_fn_without_body;
 pub mod int_plus_one;
+pub mod integer_division;
 pub mod invalid_ref;
 pub mod items_after_statements;
 pub mod large_enum_variant;
@@ -580,6 +581,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
     reg.register_late_lint_pass(box transmuting_null::TransmutingNull);
     reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite);
     reg.register_late_lint_pass(box checked_conversions::CheckedConversions);
+    reg.register_late_lint_pass(box integer_division::IntegerDivision);
 
     reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
         arithmetic::FLOAT_ARITHMETIC,
@@ -624,6 +626,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
         functions::TOO_MANY_LINES,
         if_not_else::IF_NOT_ELSE,
         infinite_iter::MAYBE_INFINITE_ITER,
+        integer_division::INTEGER_DIVISION,
         items_after_statements::ITEMS_AFTER_STATEMENTS,
         literal_representation::LARGE_DIGIT_GROUPS,
         loops::EXPLICIT_INTO_ITER_LOOP,
diff --git a/clippy_lints/src/trivially_copy_pass_by_ref.rs b/clippy_lints/src/trivially_copy_pass_by_ref.rs
index 319f6311e88..e4c4000c126 100644
--- a/clippy_lints/src/trivially_copy_pass_by_ref.rs
+++ b/clippy_lints/src/trivially_copy_pass_by_ref.rs
@@ -64,6 +64,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef {
             // Cap the calculated bit width at 32-bits to reduce
             // portability problems between 32 and 64-bit targets
             let bit_width = cmp::min(bit_width, 32);
+            #[allow(clippy::integer_division)]
             let byte_width = bit_width / 8;
             // Use a limit of 2 times the register byte width
             byte_width * 2
diff --git a/tests/ui/integer_division.rs b/tests/ui/integer_division.rs
new file mode 100644
index 00000000000..800c7525752
--- /dev/null
+++ b/tests/ui/integer_division.rs
@@ -0,0 +1,9 @@
+#![warn(clippy::integer_division)]
+
+fn main() {
+    let two = 2;
+    let n = 1 / 2;
+    let o = 1 / two;
+    let p = two / 4;
+    let x = 1. / 2.0;
+}
diff --git a/tests/ui/integer_division.stderr b/tests/ui/integer_division.stderr
new file mode 100644
index 00000000000..72a232ef3d7
--- /dev/null
+++ b/tests/ui/integer_division.stderr
@@ -0,0 +1,27 @@
+error: integer division
+  --> $DIR/integer_division.rs:5:13
+   |
+LL |     let n = 1 / 2;
+   |             ^^^^^
+   |
+   = note: `-D clippy::integer-division` implied by `-D warnings`
+   = help: division of integers may cause loss of precision. consider using floats.
+
+error: integer division
+  --> $DIR/integer_division.rs:6:13
+   |
+LL |     let o = 1 / two;
+   |             ^^^^^^^
+   |
+   = help: division of integers may cause loss of precision. consider using floats.
+
+error: integer division
+  --> $DIR/integer_division.rs:7:13
+   |
+LL |     let p = two / 4;
+   |             ^^^^^^^
+   |
+   = help: division of integers may cause loss of precision. consider using floats.
+
+error: aborting due to 3 previous errors
+