Skip to content

Commit 6f37100

Browse files
committed
Move Arithmetic into Operators lint pass
1 parent dbd1a28 commit 6f37100

File tree

6 files changed

+213
-183
lines changed

6 files changed

+213
-183
lines changed

clippy_lints/src/arithmetic.rs

Lines changed: 0 additions & 170 deletions
This file was deleted.

clippy_lints/src/lib.register_lints.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,6 @@ store.register_lints(&[
3535
utils::internal_lints::UNNECESSARY_SYMBOL_STR,
3636
almost_complete_letter_range::ALMOST_COMPLETE_LETTER_RANGE,
3737
approx_const::APPROX_CONSTANT,
38-
arithmetic::FLOAT_ARITHMETIC,
39-
arithmetic::INTEGER_ARITHMETIC,
4038
as_conversions::AS_CONVERSIONS,
4139
asm_syntax::INLINE_ASM_X86_ATT_SYNTAX,
4240
asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX,
@@ -425,6 +423,8 @@ store.register_lints(&[
425423
only_used_in_recursion::ONLY_USED_IN_RECURSION,
426424
open_options::NONSENSICAL_OPEN_OPTIONS,
427425
operators::ABSURD_EXTREME_COMPARISONS,
426+
operators::FLOAT_ARITHMETIC,
427+
operators::INTEGER_ARITHMETIC,
428428
option_env_unwrap::OPTION_ENV_UNWRAP,
429429
option_if_let_else::OPTION_IF_LET_ELSE,
430430
overflow_check_conditional::OVERFLOW_CHECK_CONDITIONAL,

clippy_lints/src/lib.register_restriction.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
// Manual edits will be overwritten.
44

55
store.register_group(true, "clippy::restriction", Some("clippy_restriction"), vec![
6-
LintId::of(arithmetic::FLOAT_ARITHMETIC),
7-
LintId::of(arithmetic::INTEGER_ARITHMETIC),
86
LintId::of(as_conversions::AS_CONVERSIONS),
97
LintId::of(asm_syntax::INLINE_ASM_X86_ATT_SYNTAX),
108
LintId::of(asm_syntax::INLINE_ASM_X86_INTEL_SYNTAX),
@@ -50,6 +48,8 @@ store.register_group(true, "clippy::restriction", Some("clippy_restriction"), ve
5048
LintId::of(module_style::MOD_MODULE_FILES),
5149
LintId::of(module_style::SELF_NAMED_MODULE_FILES),
5250
LintId::of(modulo_arithmetic::MODULO_ARITHMETIC),
51+
LintId::of(operators::FLOAT_ARITHMETIC),
52+
LintId::of(operators::INTEGER_ARITHMETIC),
5353
LintId::of(panic_in_result_fn::PANIC_IN_RESULT_FN),
5454
LintId::of(panic_unimplemented::PANIC),
5555
LintId::of(panic_unimplemented::TODO),

clippy_lints/src/lib.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ mod renamed_lints;
169169
// begin lints modules, do not remove this comment, it’s used in `update_lints`
170170
mod almost_complete_letter_range;
171171
mod approx_const;
172-
mod arithmetic;
173172
mod as_conversions;
174173
mod asm_syntax;
175174
mod assertions_on_constants;
@@ -679,7 +678,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
679678
store.register_late_pass(move || Box::new(doc::DocMarkdown::new(doc_valid_idents.clone())));
680679
store.register_late_pass(|| Box::new(neg_multiply::NegMultiply));
681680
store.register_late_pass(|| Box::new(mem_forget::MemForget));
682-
store.register_late_pass(|| Box::new(arithmetic::Arithmetic::default()));
683681
store.register_late_pass(|| Box::new(assign_ops::AssignOps));
684682
store.register_late_pass(|| Box::new(let_if_seq::LetIfSeq));
685683
store.register_late_pass(|| Box::new(mixed_read_write_in_expression::EvalOrderDependence));
@@ -912,7 +910,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
912910
store.register_late_pass(|| Box::new(get_first::GetFirst));
913911
store.register_early_pass(|| Box::new(unused_rounding::UnusedRounding));
914912
store.register_early_pass(move || Box::new(almost_complete_letter_range::AlmostCompleteLetterRange::new(msrv)));
915-
store.register_late_pass(|| Box::new(operators::Operators));
913+
store.register_late_pass(|| Box::new(operators::Operators::default()));
916914
// add lints here, do not remove this comment, it's used in `new_lint`
917915
}
918916

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
use clippy_utils::consts::constant_simple;
2+
use clippy_utils::diagnostics::span_lint;
3+
use rustc_hir as hir;
4+
use rustc_lint::LateContext;
5+
use rustc_span::source_map::Span;
6+
7+
use super::{FLOAT_ARITHMETIC, INTEGER_ARITHMETIC};
8+
9+
#[derive(Default)]
10+
pub struct Context {
11+
expr_id: Option<hir::HirId>,
12+
/// This field is used to check whether expressions are constants, such as in enum discriminants
13+
/// and consts
14+
const_span: Option<Span>,
15+
}
16+
impl Context {
17+
fn skip_expr(&mut self, e: &hir::Expr<'_>) -> bool {
18+
self.expr_id.is_some() || self.const_span.map_or(false, |span| span.contains(e.span))
19+
}
20+
21+
pub fn check_binary<'tcx>(
22+
&mut self,
23+
cx: &LateContext<'tcx>,
24+
expr: &'tcx hir::Expr<'_>,
25+
op: hir::BinOpKind,
26+
l: &'tcx hir::Expr<'_>,
27+
r: &'tcx hir::Expr<'_>,
28+
) {
29+
if self.skip_expr(expr) {
30+
return;
31+
}
32+
match op {
33+
hir::BinOpKind::And
34+
| hir::BinOpKind::Or
35+
| hir::BinOpKind::BitAnd
36+
| hir::BinOpKind::BitOr
37+
| hir::BinOpKind::BitXor
38+
| hir::BinOpKind::Eq
39+
| hir::BinOpKind::Lt
40+
| hir::BinOpKind::Le
41+
| hir::BinOpKind::Ne
42+
| hir::BinOpKind::Ge
43+
| hir::BinOpKind::Gt => return,
44+
_ => (),
45+
}
46+
47+
let (l_ty, r_ty) = (cx.typeck_results().expr_ty(l), cx.typeck_results().expr_ty(r));
48+
if l_ty.peel_refs().is_integral() && r_ty.peel_refs().is_integral() {
49+
match op {
50+
hir::BinOpKind::Div | hir::BinOpKind::Rem => match &r.kind {
51+
hir::ExprKind::Lit(_lit) => (),
52+
hir::ExprKind::Unary(hir::UnOp::Neg, expr) => {
53+
if let hir::ExprKind::Lit(lit) = &expr.kind {
54+
if let rustc_ast::ast::LitKind::Int(1, _) = lit.node {
55+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
56+
self.expr_id = Some(expr.hir_id);
57+
}
58+
}
59+
},
60+
_ => {
61+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
62+
self.expr_id = Some(expr.hir_id);
63+
},
64+
},
65+
_ => {
66+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
67+
self.expr_id = Some(expr.hir_id);
68+
},
69+
}
70+
} else if r_ty.peel_refs().is_floating_point() && r_ty.peel_refs().is_floating_point() {
71+
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
72+
self.expr_id = Some(expr.hir_id);
73+
}
74+
}
75+
76+
pub fn check_negate<'tcx>(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>, arg: &'tcx hir::Expr<'_>) {
77+
if self.skip_expr(expr) {
78+
return;
79+
}
80+
let ty = cx.typeck_results().expr_ty(arg);
81+
if constant_simple(cx, cx.typeck_results(), expr).is_none() {
82+
if ty.is_integral() {
83+
span_lint(cx, INTEGER_ARITHMETIC, expr.span, "integer arithmetic detected");
84+
self.expr_id = Some(expr.hir_id);
85+
} else if ty.is_floating_point() {
86+
span_lint(cx, FLOAT_ARITHMETIC, expr.span, "floating-point arithmetic detected");
87+
self.expr_id = Some(expr.hir_id);
88+
}
89+
}
90+
}
91+
92+
pub fn expr_post(&mut self, id: hir::HirId) {
93+
if Some(id) == self.expr_id {
94+
self.expr_id = None;
95+
}
96+
}
97+
98+
pub fn enter_body(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
99+
let body_owner = cx.tcx.hir().body_owner_def_id(body.id());
100+
101+
match cx.tcx.hir().body_owner_kind(body_owner) {
102+
hir::BodyOwnerKind::Static(_) | hir::BodyOwnerKind::Const => {
103+
let body_span = cx.tcx.def_span(body_owner);
104+
105+
if let Some(span) = self.const_span {
106+
if span.contains(body_span) {
107+
return;
108+
}
109+
}
110+
self.const_span = Some(body_span);
111+
},
112+
hir::BodyOwnerKind::Fn | hir::BodyOwnerKind::Closure => (),
113+
}
114+
}
115+
116+
pub fn body_post(&mut self, cx: &LateContext<'_>, body: &hir::Body<'_>) {
117+
let body_owner = cx.tcx.hir().body_owner(body.id());
118+
let body_span = cx.tcx.hir().span(body_owner);
119+
120+
if let Some(span) = self.const_span {
121+
if span.contains(body_span) {
122+
return;
123+
}
124+
}
125+
self.const_span = None;
126+
}
127+
}

0 commit comments

Comments
 (0)