Skip to content

Commit 6f353fd

Browse files
committed
Auto merge of rust-lang#10310 - c410-f3r:arith-2, r=Alexendoo
[arithmetic_side_effects] Fix rust-lang#10209 Fix rust-lang#10209 --- changelog: Enhancement: [`arithmetic_side_effects`]: No longer lints, if safe constant values are used. [rust-lang#10310](rust-lang/rust-clippy#10310) <!-- changelog_checked -->
2 parents ad2135e + 1ed8ed3 commit 6f353fd

File tree

3 files changed

+146
-112
lines changed

3 files changed

+146
-112
lines changed

clippy_lints/src/operators/arithmetic_side_effects.rs

+20-13
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
use super::ARITHMETIC_SIDE_EFFECTS;
22
use clippy_utils::{
3-
consts::{constant, constant_simple},
3+
consts::{constant, constant_simple, Constant},
44
diagnostics::span_lint,
5-
peel_hir_expr_refs, peel_hir_expr_unary,
5+
is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary,
66
};
77
use rustc_ast as ast;
88
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -97,17 +97,19 @@ impl ArithmeticSideEffects {
9797
self.expr_span = Some(expr.span);
9898
}
9999

100-
/// If `expr` is not a literal integer like `1`, returns `None`.
100+
/// Returns the numeric value of a literal integer originated from `expr`, if any.
101101
///
102-
/// Returns the absolute value of the expression, if this is an integer literal.
103-
fn literal_integer(expr: &hir::Expr<'_>) -> Option<u128> {
102+
/// Literal integers can be originated from adhoc declarations like `1`, associated constants
103+
/// like `i32::MAX` or constant references like `N` from `const N: i32 = 1;`,
104+
fn literal_integer(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option<u128> {
104105
let actual = peel_hir_expr_unary(expr).0;
105106
if let hir::ExprKind::Lit(ref lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node {
106-
Some(n)
107+
return Some(n)
107108
}
108-
else {
109-
None
109+
if let Some((Constant::Int(n), _)) = constant(cx, cx.typeck_results(), expr) {
110+
return Some(n);
110111
}
112+
None
111113
}
112114

113115
/// Manages when the lint should be triggered. Operations in constant environments, hard coded
@@ -143,7 +145,10 @@ impl ArithmeticSideEffects {
143145
let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
144146
let (actual_lhs, lhs_ref_counter) = peel_hir_expr_refs(lhs);
145147
let (actual_rhs, rhs_ref_counter) = peel_hir_expr_refs(rhs);
146-
match (Self::literal_integer(actual_lhs), Self::literal_integer(actual_rhs)) {
148+
match (
149+
Self::literal_integer(cx, actual_lhs),
150+
Self::literal_integer(cx, actual_rhs),
151+
) {
147152
(None, None) => false,
148153
(None, Some(n)) | (Some(n), None) => match (&op.node, n) {
149154
(hir::BinOpKind::Div | hir::BinOpKind::Rem, 0) => false,
@@ -180,20 +185,22 @@ impl ArithmeticSideEffects {
180185
return;
181186
}
182187
let actual_un_expr = peel_hir_expr_refs(un_expr).0;
183-
if Self::literal_integer(actual_un_expr).is_some() {
188+
if Self::literal_integer(cx, actual_un_expr).is_some() {
184189
return;
185190
}
186191
self.issue_lint(cx, expr);
187192
}
188193

189-
fn should_skip_expr(&mut self, expr: &hir::Expr<'_>) -> bool {
190-
self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span))
194+
fn should_skip_expr(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool {
195+
is_lint_allowed(cx, ARITHMETIC_SIDE_EFFECTS, expr.hir_id)
196+
|| self.expr_span.is_some()
197+
|| self.const_span.map_or(false, |sp| sp.contains(expr.span))
191198
}
192199
}
193200

194201
impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
195202
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
196-
if self.should_skip_expr(expr) {
203+
if self.should_skip_expr(cx, expr) {
197204
return;
198205
}
199206
match &expr.kind {

tests/ui/arithmetic_side_effects.rs

+27
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313

1414
use core::num::{Saturating, Wrapping};
1515

16+
const ONE: i32 = 1;
17+
const ZERO: i32 = 0;
18+
1619
#[derive(Clone, Copy)]
1720
pub struct Custom;
1821

@@ -182,6 +185,10 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
182185
_n += &0;
183186
_n -= 0;
184187
_n -= &0;
188+
_n += ZERO;
189+
_n += &ZERO;
190+
_n -= ZERO;
191+
_n -= &ZERO;
185192
_n /= 99;
186193
_n /= &99;
187194
_n %= 99;
@@ -190,10 +197,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
190197
_n *= &0;
191198
_n *= 1;
192199
_n *= &1;
200+
_n *= ZERO;
201+
_n *= &ZERO;
202+
_n *= ONE;
203+
_n *= &ONE;
193204
_n += -0;
194205
_n += &-0;
195206
_n -= -0;
196207
_n -= &-0;
208+
_n += -ZERO;
209+
_n += &-ZERO;
210+
_n -= -ZERO;
211+
_n -= &-ZERO;
197212
_n /= -99;
198213
_n /= &-99;
199214
_n %= -99;
@@ -208,10 +223,18 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
208223
_n = _n + &0;
209224
_n = 0 + _n;
210225
_n = &0 + _n;
226+
_n = _n + ZERO;
227+
_n = _n + &ZERO;
228+
_n = ZERO + _n;
229+
_n = &ZERO + _n;
211230
_n = _n - 0;
212231
_n = _n - &0;
213232
_n = 0 - _n;
214233
_n = &0 - _n;
234+
_n = _n - ZERO;
235+
_n = _n - &ZERO;
236+
_n = ZERO - _n;
237+
_n = &ZERO - _n;
215238
_n = _n / 99;
216239
_n = _n / &99;
217240
_n = _n % 99;
@@ -222,6 +245,10 @@ pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_tri
222245
_n = &0 * _n;
223246
_n = _n * 1;
224247
_n = _n * &1;
248+
_n = ZERO * _n;
249+
_n = &ZERO * _n;
250+
_n = _n * ONE;
251+
_n = _n * &ONE;
225252
_n = 1 * _n;
226253
_n = &1 * _n;
227254
_n = 23 + 85;

0 commit comments

Comments
 (0)