Skip to content

Commit a1eb60f

Browse files
committed
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
2 parents cefddf7 + b364eb7 commit a1eb60f

8 files changed

+99
-2
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,7 @@ All notable changes to this project will be documented in this file.
956956
[`inline_fn_without_body`]: https://rust-lang.github.io/rust-clippy/master/index.html#inline_fn_without_body
957957
[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
958958
[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic
959+
[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
959960
[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
960961
[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
961962
[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.
99

10-
[There are 304 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
10+
[There are 305 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
1111

1212
We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:
1313

clippy_lints/src/cognitive_complexity.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,8 @@ impl CognitiveComplexity {
7474
let ret_adjust = if match_type(cx, ret_ty, &paths::RESULT) {
7575
returns
7676
} else {
77-
returns / 2
77+
#[allow(clippy::integer_division)]
78+
(returns / 2)
7879
};
7980

8081
if cc + divergence < match_arms + short_circuits {

clippy_lints/src/integer_division.rs

+55
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use crate::utils::span_help_and_lint;
2+
use if_chain::if_chain;
3+
use rustc::hir;
4+
use rustc::lint::{LateContext, LateLintPass, LintArray, LintPass};
5+
use rustc::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// **What it does:** Checks for division of integers
9+
///
10+
/// **Why is this bad?** When outside of some very specific algorithms,
11+
/// integer division is very often a mistake because it discards the
12+
/// remainder.
13+
///
14+
/// **Known problems:** None.
15+
///
16+
/// **Example:**
17+
/// ```rust
18+
/// fn main() {
19+
/// let x = 3 / 2;
20+
/// println!("{}", x);
21+
/// }
22+
/// ```
23+
pub INTEGER_DIVISION,
24+
pedantic,
25+
"integer division may cause loss of precision"
26+
}
27+
28+
declare_lint_pass!(IntegerDivision => [INTEGER_DIVISION]);
29+
30+
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for IntegerDivision {
31+
fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
32+
if is_integer_division(cx, expr) {
33+
span_help_and_lint(
34+
cx,
35+
INTEGER_DIVISION,
36+
expr.span,
37+
"integer division",
38+
"division of integers may cause loss of precision. consider using floats.",
39+
);
40+
}
41+
}
42+
}
43+
44+
fn is_integer_division<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) -> bool {
45+
if_chain! {
46+
if let hir::ExprKind::Binary(binop, left, right) = &expr.node;
47+
if let hir::BinOpKind::Div = &binop.node;
48+
then {
49+
let (left_ty, right_ty) = (cx.tables.expr_ty(left), cx.tables.expr_ty(right));
50+
return left_ty.is_integral() && right_ty.is_integral();
51+
}
52+
}
53+
54+
false
55+
}

clippy_lints/src/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,7 @@ pub mod infinite_iter;
197197
pub mod inherent_impl;
198198
pub mod inline_fn_without_body;
199199
pub mod int_plus_one;
200+
pub mod integer_division;
200201
pub mod invalid_ref;
201202
pub mod items_after_statements;
202203
pub mod large_enum_variant;
@@ -580,6 +581,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
580581
reg.register_late_lint_pass(box transmuting_null::TransmutingNull);
581582
reg.register_late_lint_pass(box path_buf_push_overwrite::PathBufPushOverwrite);
582583
reg.register_late_lint_pass(box checked_conversions::CheckedConversions);
584+
reg.register_late_lint_pass(box integer_division::IntegerDivision);
583585

584586
reg.register_lint_group("clippy::restriction", Some("clippy_restriction"), vec![
585587
arithmetic::FLOAT_ARITHMETIC,
@@ -624,6 +626,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry<'_>, conf: &Conf) {
624626
functions::TOO_MANY_LINES,
625627
if_not_else::IF_NOT_ELSE,
626628
infinite_iter::MAYBE_INFINITE_ITER,
629+
integer_division::INTEGER_DIVISION,
627630
items_after_statements::ITEMS_AFTER_STATEMENTS,
628631
literal_representation::LARGE_DIGIT_GROUPS,
629632
loops::EXPLICIT_INTO_ITER_LOOP,

clippy_lints/src/trivially_copy_pass_by_ref.rs

+1
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ impl<'a, 'tcx> TriviallyCopyPassByRef {
6464
// Cap the calculated bit width at 32-bits to reduce
6565
// portability problems between 32 and 64-bit targets
6666
let bit_width = cmp::min(bit_width, 32);
67+
#[allow(clippy::integer_division)]
6768
let byte_width = bit_width / 8;
6869
// Use a limit of 2 times the register byte width
6970
byte_width * 2

tests/ui/integer_division.rs

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#![warn(clippy::integer_division)]
2+
3+
fn main() {
4+
let two = 2;
5+
let n = 1 / 2;
6+
let o = 1 / two;
7+
let p = two / 4;
8+
let x = 1. / 2.0;
9+
}

tests/ui/integer_division.stderr

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
error: integer division
2+
--> $DIR/integer_division.rs:5:13
3+
|
4+
LL | let n = 1 / 2;
5+
| ^^^^^
6+
|
7+
= note: `-D clippy::integer-division` implied by `-D warnings`
8+
= help: division of integers may cause loss of precision. consider using floats.
9+
10+
error: integer division
11+
--> $DIR/integer_division.rs:6:13
12+
|
13+
LL | let o = 1 / two;
14+
| ^^^^^^^
15+
|
16+
= help: division of integers may cause loss of precision. consider using floats.
17+
18+
error: integer division
19+
--> $DIR/integer_division.rs:7:13
20+
|
21+
LL | let p = two / 4;
22+
| ^^^^^^^
23+
|
24+
= help: division of integers may cause loss of precision. consider using floats.
25+
26+
error: aborting due to 3 previous errors
27+

0 commit comments

Comments
 (0)