Skip to content

Commit 7fcaa60

Browse files
committed
Auto merge of rust-lang#12692 - c410-f3r:arrrr, r=Manishearth
[arithmetic_side_effects] Fix rust-lang#12318 Fix rust-lang#12318 changelog: [arithmetic_side_effects]: Consider method calls that correspond to arithmetic symbols
2 parents fc6dfeb + 2a4dae3 commit 7fcaa60

File tree

3 files changed

+61
-16
lines changed

3 files changed

+61
-16
lines changed

clippy_lints/src/operators/arithmetic_side_effects.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,13 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
77
use rustc_lint::{LateContext, LateLintPass};
88
use rustc_middle::ty::{self, Ty};
99
use rustc_session::impl_lint_pass;
10-
use rustc_span::source_map::Spanned;
1110
use rustc_span::symbol::sym;
1211
use rustc_span::{Span, Symbol};
1312
use {rustc_ast as ast, rustc_hir as hir};
1413

1514
const HARD_CODED_ALLOWED_BINARY: &[[&str; 2]] = &[["f32", "f32"], ["f64", "f64"], ["std::string::String", "str"]];
1615
const HARD_CODED_ALLOWED_UNARY: &[&str] = &["f32", "f64", "std::num::Saturating", "std::num::Wrapping"];
17-
const INTEGER_METHODS: &[Symbol] = &[
16+
const DISALLOWED_INT_METHODS: &[Symbol] = &[
1817
sym::saturating_div,
1918
sym::wrapping_div,
2019
sym::wrapping_rem,
@@ -27,8 +26,8 @@ pub struct ArithmeticSideEffects {
2726
allowed_unary: FxHashSet<String>,
2827
// Used to check whether expressions are constants, such as in enum discriminants and consts
2928
const_span: Option<Span>,
29+
disallowed_int_methods: FxHashSet<Symbol>,
3030
expr_span: Option<Span>,
31-
integer_methods: FxHashSet<Symbol>,
3231
}
3332

3433
impl_lint_pass!(ArithmeticSideEffects => [ARITHMETIC_SIDE_EFFECTS]);
@@ -53,8 +52,8 @@ impl ArithmeticSideEffects {
5352
allowed_binary,
5453
allowed_unary,
5554
const_span: None,
55+
disallowed_int_methods: DISALLOWED_INT_METHODS.iter().copied().collect(),
5656
expr_span: None,
57-
integer_methods: INTEGER_METHODS.iter().copied().collect(),
5857
}
5958
}
6059

@@ -91,10 +90,10 @@ impl ArithmeticSideEffects {
9190
fn has_specific_allowed_type_and_operation<'tcx>(
9291
cx: &LateContext<'tcx>,
9392
lhs_ty: Ty<'tcx>,
94-
op: &Spanned<hir::BinOpKind>,
93+
op: hir::BinOpKind,
9594
rhs_ty: Ty<'tcx>,
9695
) -> bool {
97-
let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem);
96+
let is_div_or_rem = matches!(op, hir::BinOpKind::Div | hir::BinOpKind::Rem);
9897
let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| {
9998
let tcx = cx.tcx;
10099

@@ -166,21 +165,43 @@ impl ArithmeticSideEffects {
166165
None
167166
}
168167

168+
/// Methods like `add_assign` are send to their `BinOps` references.
169+
fn manage_sugar_methods<'tcx>(
170+
&mut self,
171+
cx: &LateContext<'tcx>,
172+
expr: &'tcx hir::Expr<'_>,
173+
lhs: &'tcx hir::Expr<'_>,
174+
ps: &hir::PathSegment<'_>,
175+
rhs: &'tcx hir::Expr<'_>,
176+
) {
177+
if ps.ident.name == sym::add || ps.ident.name == sym::add_assign {
178+
self.manage_bin_ops(cx, expr, hir::BinOpKind::Add, lhs, rhs);
179+
} else if ps.ident.name == sym::div || ps.ident.name == sym::div_assign {
180+
self.manage_bin_ops(cx, expr, hir::BinOpKind::Div, lhs, rhs);
181+
} else if ps.ident.name == sym::mul || ps.ident.name == sym::mul_assign {
182+
self.manage_bin_ops(cx, expr, hir::BinOpKind::Mul, lhs, rhs);
183+
} else if ps.ident.name == sym::rem || ps.ident.name == sym::rem_assign {
184+
self.manage_bin_ops(cx, expr, hir::BinOpKind::Rem, lhs, rhs);
185+
} else if ps.ident.name == sym::sub || ps.ident.name == sym::sub_assign {
186+
self.manage_bin_ops(cx, expr, hir::BinOpKind::Sub, lhs, rhs);
187+
}
188+
}
189+
169190
/// Manages when the lint should be triggered. Operations in constant environments, hard coded
170-
/// types, custom allowed types and non-constant operations that won't overflow are ignored.
191+
/// types, custom allowed types and non-constant operations that don't overflow are ignored.
171192
fn manage_bin_ops<'tcx>(
172193
&mut self,
173194
cx: &LateContext<'tcx>,
174195
expr: &'tcx hir::Expr<'_>,
175-
op: &Spanned<hir::BinOpKind>,
196+
op: hir::BinOpKind,
176197
lhs: &'tcx hir::Expr<'_>,
177198
rhs: &'tcx hir::Expr<'_>,
178199
) {
179200
if constant_simple(cx, cx.typeck_results(), expr).is_some() {
180201
return;
181202
}
182203
if !matches!(
183-
op.node,
204+
op,
184205
hir::BinOpKind::Add
185206
| hir::BinOpKind::Div
186207
| hir::BinOpKind::Mul
@@ -204,7 +225,7 @@ impl ArithmeticSideEffects {
204225
return;
205226
}
206227
let has_valid_op = if Self::is_integral(lhs_ty) && Self::is_integral(rhs_ty) {
207-
if let hir::BinOpKind::Shl | hir::BinOpKind::Shr = op.node {
228+
if let hir::BinOpKind::Shl | hir::BinOpKind::Shr = op {
208229
// At least for integers, shifts are already handled by the CTFE
209230
return;
210231
}
@@ -213,7 +234,7 @@ impl ArithmeticSideEffects {
213234
Self::literal_integer(cx, actual_rhs),
214235
) {
215236
(None, None) => false,
216-
(None, Some(n)) => match (&op.node, n) {
237+
(None, Some(n)) => match (&op, n) {
217238
// Division and module are always valid if applied to non-zero integers
218239
(hir::BinOpKind::Div | hir::BinOpKind::Rem, local_n) if local_n != 0 => true,
219240
// Adding or subtracting zeros is always a no-op
@@ -223,7 +244,7 @@ impl ArithmeticSideEffects {
223244
=> true,
224245
_ => false,
225246
},
226-
(Some(n), None) => match (&op.node, n) {
247+
(Some(n), None) => match (&op, n) {
227248
// Adding or subtracting zeros is always a no-op
228249
(hir::BinOpKind::Add | hir::BinOpKind::Sub, 0)
229250
// Multiplication by 1 or 0 will never overflow
@@ -249,6 +270,7 @@ impl ArithmeticSideEffects {
249270
&mut self,
250271
args: &'tcx [hir::Expr<'_>],
251272
cx: &LateContext<'tcx>,
273+
expr: &'tcx hir::Expr<'_>,
252274
ps: &'tcx hir::PathSegment<'_>,
253275
receiver: &'tcx hir::Expr<'_>,
254276
) {
@@ -262,7 +284,8 @@ impl ArithmeticSideEffects {
262284
if !Self::is_integral(instance_ty) {
263285
return;
264286
}
265-
if !self.integer_methods.contains(&ps.ident.name) {
287+
self.manage_sugar_methods(cx, expr, receiver, ps, arg);
288+
if !self.disallowed_int_methods.contains(&ps.ident.name) {
266289
return;
267290
}
268291
let (actual_arg, _) = peel_hir_expr_refs(arg);
@@ -310,10 +333,10 @@ impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
310333
}
311334
match &expr.kind {
312335
hir::ExprKind::AssignOp(op, lhs, rhs) | hir::ExprKind::Binary(op, lhs, rhs) => {
313-
self.manage_bin_ops(cx, expr, op, lhs, rhs);
336+
self.manage_bin_ops(cx, expr, op.node, lhs, rhs);
314337
},
315338
hir::ExprKind::MethodCall(ps, receiver, args, _) => {
316-
self.manage_method_call(args, cx, ps, receiver);
339+
self.manage_method_call(args, cx, expr, ps, receiver);
317340
},
318341
hir::ExprKind::Unary(un_op, un_expr) => {
319342
self.manage_unary_ops(cx, expr, un_expr, *un_op);

tests/ui/arithmetic_side_effects.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,4 +521,14 @@ pub fn issue_11393() {
521521
example_rem(x, maybe_zero);
522522
}
523523

524+
pub fn issue_12318() {
525+
use core::ops::{AddAssign, DivAssign, MulAssign, RemAssign, SubAssign};
526+
let mut one: i32 = 1;
527+
one.add_assign(1);
528+
one.div_assign(1);
529+
one.mul_assign(1);
530+
one.rem_assign(1);
531+
one.sub_assign(1);
532+
}
533+
524534
fn main() {}

tests/ui/arithmetic_side_effects.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,5 +715,17 @@ error: arithmetic operation that can potentially result in unexpected side-effec
715715
LL | x % maybe_zero
716716
| ^^^^^^^^^^^^^^
717717

718-
error: aborting due to 119 previous errors
718+
error: arithmetic operation that can potentially result in unexpected side-effects
719+
--> tests/ui/arithmetic_side_effects.rs:527:5
720+
|
721+
LL | one.add_assign(1);
722+
| ^^^^^^^^^^^^^^^^^
723+
724+
error: arithmetic operation that can potentially result in unexpected side-effects
725+
--> tests/ui/arithmetic_side_effects.rs:531:5
726+
|
727+
LL | one.sub_assign(1);
728+
| ^^^^^^^^^^^^^^^^^
729+
730+
error: aborting due to 121 previous errors
719731

0 commit comments

Comments
 (0)