Adds lint for integer division

This commit is contained in:
Thiago Arrais 2019-06-11 13:53:12 -03:00
parent cefddf7843
commit b364eb7b54
8 changed files with 99 additions and 2 deletions

View file

@ -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

View file

@ -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:

View file

@ -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 {

View file

@ -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
}

View file

@ -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,

View file

@ -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

View file

@ -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;
}

View file

@ -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