mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-06 20:28:33 +00:00
Move IntegerDivision
into Operators
lint pass
This commit is contained in:
parent
83de67cfec
commit
a8df16ae1d
@ -1,61 +0,0 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_help;
|
|
||||||
use if_chain::if_chain;
|
|
||||||
use rustc_hir as hir;
|
|
||||||
use rustc_lint::{LateContext, LateLintPass};
|
|
||||||
use rustc_session::{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.
|
|
||||||
///
|
|
||||||
/// ### Example
|
|
||||||
/// ```rust
|
|
||||||
/// let x = 3 / 2;
|
|
||||||
/// println!("{}", x);
|
|
||||||
/// ```
|
|
||||||
///
|
|
||||||
/// Use instead:
|
|
||||||
/// ```rust
|
|
||||||
/// let x = 3f32 / 2f32;
|
|
||||||
/// println!("{}", x);
|
|
||||||
/// ```
|
|
||||||
#[clippy::version = "1.37.0"]
|
|
||||||
pub INTEGER_DIVISION,
|
|
||||||
restriction,
|
|
||||||
"integer division may cause loss of precision"
|
|
||||||
}
|
|
||||||
|
|
||||||
declare_lint_pass!(IntegerDivision => [INTEGER_DIVISION]);
|
|
||||||
|
|
||||||
impl<'tcx> LateLintPass<'tcx> for IntegerDivision {
|
|
||||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
|
|
||||||
if is_integer_division(cx, expr) {
|
|
||||||
span_lint_and_help(
|
|
||||||
cx,
|
|
||||||
INTEGER_DIVISION,
|
|
||||||
expr.span,
|
|
||||||
"integer division",
|
|
||||||
None,
|
|
||||||
"division of integers may cause loss of precision. consider using floats",
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_integer_division<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) -> bool {
|
|
||||||
if_chain! {
|
|
||||||
if let hir::ExprKind::Binary(binop, left, right) = &expr.kind;
|
|
||||||
if binop.node == hir::BinOpKind::Div;
|
|
||||||
then {
|
|
||||||
let (left_ty, right_ty) = (cx.typeck_results().expr_ty(left), cx.typeck_results().expr_ty(right));
|
|
||||||
return left_ty.is_integral() && right_ty.is_integral();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
@ -194,7 +194,6 @@ store.register_lints(&[
|
|||||||
init_numbered_fields::INIT_NUMBERED_FIELDS,
|
init_numbered_fields::INIT_NUMBERED_FIELDS,
|
||||||
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
inline_fn_without_body::INLINE_FN_WITHOUT_BODY,
|
||||||
int_plus_one::INT_PLUS_ONE,
|
int_plus_one::INT_PLUS_ONE,
|
||||||
integer_division::INTEGER_DIVISION,
|
|
||||||
invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS,
|
invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS,
|
||||||
items_after_statements::ITEMS_AFTER_STATEMENTS,
|
items_after_statements::ITEMS_AFTER_STATEMENTS,
|
||||||
iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR,
|
iter_not_returning_iterator::ITER_NOT_RETURNING_ITERATOR,
|
||||||
@ -434,6 +433,7 @@ store.register_lints(&[
|
|||||||
operators::IDENTITY_OP,
|
operators::IDENTITY_OP,
|
||||||
operators::INEFFECTIVE_BIT_MASK,
|
operators::INEFFECTIVE_BIT_MASK,
|
||||||
operators::INTEGER_ARITHMETIC,
|
operators::INTEGER_ARITHMETIC,
|
||||||
|
operators::INTEGER_DIVISION,
|
||||||
operators::MISREFACTORED_ASSIGN_OP,
|
operators::MISREFACTORED_ASSIGN_OP,
|
||||||
operators::OP_REF,
|
operators::OP_REF,
|
||||||
operators::VERBOSE_BIT_MASK,
|
operators::VERBOSE_BIT_MASK,
|
||||||
|
@ -25,7 +25,6 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
|
|||||||
LintId::of(implicit_return::IMPLICIT_RETURN),
|
LintId::of(implicit_return::IMPLICIT_RETURN),
|
||||||
LintId::of(indexing_slicing::INDEXING_SLICING),
|
LintId::of(indexing_slicing::INDEXING_SLICING),
|
||||||
LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL),
|
LintId::of(inherent_impl::MULTIPLE_INHERENT_IMPL),
|
||||||
LintId::of(integer_division::INTEGER_DIVISION),
|
|
||||||
LintId::of(large_include_file::LARGE_INCLUDE_FILE),
|
LintId::of(large_include_file::LARGE_INCLUDE_FILE),
|
||||||
LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE),
|
LintId::of(let_underscore::LET_UNDERSCORE_MUST_USE),
|
||||||
LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION),
|
LintId::of(literal_representation::DECIMAL_LITERAL_REPRESENTATION),
|
||||||
@ -52,6 +51,7 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
|
|||||||
LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
|
LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
|
||||||
LintId::of(operators::FLOAT_ARITHMETIC),
|
LintId::of(operators::FLOAT_ARITHMETIC),
|
||||||
LintId::of(operators::INTEGER_ARITHMETIC),
|
LintId::of(operators::INTEGER_ARITHMETIC),
|
||||||
|
LintId::of(operators::INTEGER_DIVISION),
|
||||||
LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
|
LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
|
||||||
LintId::of(panic_unimplemented::PANIC),
|
LintId::of(panic_unimplemented::PANIC),
|
||||||
LintId::of(panic_unimplemented::TODO),
|
LintId::of(panic_unimplemented::TODO),
|
||||||
|
@ -254,7 +254,6 @@ mod inherent_to_string;
|
|||||||
mod init_numbered_fields;
|
mod init_numbered_fields;
|
||||||
mod inline_fn_without_body;
|
mod inline_fn_without_body;
|
||||||
mod int_plus_one;
|
mod int_plus_one;
|
||||||
mod integer_division;
|
|
||||||
mod invalid_upcast_comparisons;
|
mod invalid_upcast_comparisons;
|
||||||
mod items_after_statements;
|
mod items_after_statements;
|
||||||
mod iter_not_returning_iterator;
|
mod iter_not_returning_iterator;
|
||||||
@ -734,7 +733,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
|
|||||||
store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants));
|
store.register_late_pass(|| Box::new(assertions_on_constants::AssertionsOnConstants));
|
||||||
store.register_late_pass(|| Box::new(transmuting_null::TransmutingNull));
|
store.register_late_pass(|| Box::new(transmuting_null::TransmutingNull));
|
||||||
store.register_late_pass(|| Box::new(path_buf_push_overwrite::PathBufPushOverwrite));
|
store.register_late_pass(|| Box::new(path_buf_push_overwrite::PathBufPushOverwrite));
|
||||||
store.register_late_pass(|| Box::new(integer_division::IntegerDivision));
|
|
||||||
store.register_late_pass(|| Box::new(inherent_to_string::InherentToString));
|
store.register_late_pass(|| Box::new(inherent_to_string::InherentToString));
|
||||||
let max_trait_bounds = conf.max_trait_bounds;
|
let max_trait_bounds = conf.max_trait_bounds;
|
||||||
store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
|
store.register_late_pass(move || Box::new(trait_bounds::TraitBounds::new(max_trait_bounds)));
|
||||||
|
27
clippy_lints/src/operators/integer_division.rs
Normal file
27
clippy_lints/src/operators/integer_division.rs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
use clippy_utils::diagnostics::span_lint_and_help;
|
||||||
|
use rustc_hir as hir;
|
||||||
|
use rustc_lint::LateContext;
|
||||||
|
|
||||||
|
use super::INTEGER_DIVISION;
|
||||||
|
|
||||||
|
pub(crate) fn check<'tcx>(
|
||||||
|
cx: &LateContext<'tcx>,
|
||||||
|
expr: &'tcx hir::Expr<'_>,
|
||||||
|
op: hir::BinOpKind,
|
||||||
|
left: &'tcx hir::Expr<'_>,
|
||||||
|
right: &'tcx hir::Expr<'_>,
|
||||||
|
) {
|
||||||
|
if op == hir::BinOpKind::Div
|
||||||
|
&& cx.typeck_results().expr_ty(left).is_integral()
|
||||||
|
&& cx.typeck_results().expr_ty(right).is_integral()
|
||||||
|
{
|
||||||
|
span_lint_and_help(
|
||||||
|
cx,
|
||||||
|
INTEGER_DIVISION,
|
||||||
|
expr.span,
|
||||||
|
"integer division",
|
||||||
|
None,
|
||||||
|
"division of integers may cause loss of precision. consider using floats",
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -11,6 +11,7 @@ mod eq_op;
|
|||||||
mod erasing_op;
|
mod erasing_op;
|
||||||
mod float_equality_without_abs;
|
mod float_equality_without_abs;
|
||||||
mod identity_op;
|
mod identity_op;
|
||||||
|
mod integer_division;
|
||||||
mod misrefactored_assign_op;
|
mod misrefactored_assign_op;
|
||||||
mod numeric_arithmetic;
|
mod numeric_arithmetic;
|
||||||
mod op_ref;
|
mod op_ref;
|
||||||
@ -437,6 +438,32 @@ declare_clippy_lint! {
|
|||||||
"using identity operations, e.g., `x + 0` or `y / 1`"
|
"using identity operations, e.g., `x + 0` or `y / 1`"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
///
|
||||||
|
/// ### Example
|
||||||
|
/// ```rust
|
||||||
|
/// let x = 3 / 2;
|
||||||
|
/// println!("{}", x);
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// Use instead:
|
||||||
|
/// ```rust
|
||||||
|
/// let x = 3f32 / 2f32;
|
||||||
|
/// println!("{}", x);
|
||||||
|
/// ```
|
||||||
|
#[clippy::version = "1.37.0"]
|
||||||
|
pub INTEGER_DIVISION,
|
||||||
|
restriction,
|
||||||
|
"integer division may cause loss of precision"
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Operators {
|
pub struct Operators {
|
||||||
arithmetic_context: numeric_arithmetic::Context,
|
arithmetic_context: numeric_arithmetic::Context,
|
||||||
verbose_bit_mask_threshold: u64,
|
verbose_bit_mask_threshold: u64,
|
||||||
@ -457,6 +484,7 @@ impl_lint_pass!(Operators => [
|
|||||||
ERASING_OP,
|
ERASING_OP,
|
||||||
FLOAT_EQUALITY_WITHOUT_ABS,
|
FLOAT_EQUALITY_WITHOUT_ABS,
|
||||||
IDENTITY_OP,
|
IDENTITY_OP,
|
||||||
|
INTEGER_DIVISION,
|
||||||
]);
|
]);
|
||||||
impl Operators {
|
impl Operators {
|
||||||
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
|
pub fn new(verbose_bit_mask_threshold: u64) -> Self {
|
||||||
@ -486,6 +514,7 @@ impl<'tcx> LateLintPass<'tcx> for Operators {
|
|||||||
double_comparison::check(cx, op.node, lhs, rhs, e.span);
|
double_comparison::check(cx, op.node, lhs, rhs, e.span);
|
||||||
duration_subsec::check(cx, e, op.node, lhs, rhs);
|
duration_subsec::check(cx, e, op.node, lhs, rhs);
|
||||||
float_equality_without_abs::check(cx, e, op.node, lhs, rhs);
|
float_equality_without_abs::check(cx, e, op.node, lhs, rhs);
|
||||||
|
integer_division::check(cx, e, op.node, lhs, rhs);
|
||||||
},
|
},
|
||||||
ExprKind::AssignOp(op, lhs, rhs) => {
|
ExprKind::AssignOp(op, lhs, rhs) => {
|
||||||
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
|
self.arithmetic_context.check_binary(cx, e, op.node, lhs, rhs);
|
||||||
|
Loading…
Reference in New Issue
Block a user