about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/operators/arithmetic_side_effects.rs59
-rw-r--r--tests/ui/arithmetic_side_effects.rs40
-rw-r--r--tests/ui/arithmetic_side_effects.stderr114
3 files changed, 172 insertions, 41 deletions
diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs
index d24c57c0a4b..c8a374d90b5 100644
--- a/clippy_lints/src/operators/arithmetic_side_effects.rs
+++ b/clippy_lints/src/operators/arithmetic_side_effects.rs
@@ -9,7 +9,6 @@ use rustc_ast as ast;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_lint::{LateContext, LateLintPass};
-use rustc_middle::ty::Ty;
 use rustc_session::impl_lint_pass;
 use rustc_span::source_map::{Span, Spanned};
 
@@ -78,28 +77,47 @@ impl ArithmeticSideEffects {
         )
     }
 
-    /// Explicit integers like `1` or `i32::MAX`. Does not take into consideration references.
-    fn is_literal_integer(expr: &hir::Expr<'_>, expr_refs: Ty<'_>) -> bool {
-        let is_integral = expr_refs.is_integral();
-        let is_literal = matches!(expr.kind, hir::ExprKind::Lit(_));
-        is_integral && is_literal
-    }
-
+    // Common entry-point to avoid code duplication.
     fn issue_lint(&mut self, cx: &LateContext<'_>, expr: &hir::Expr<'_>) {
         let msg = "arithmetic operation that can potentially result in unexpected side-effects";
         span_lint(cx, ARITHMETIC_SIDE_EFFECTS, expr.span, msg);
         self.expr_span = Some(expr.span);
     }
 
+    /// * If `expr` is a literal integer like `1` or `i32::MAX`, returns itself.
+    /// * Is `expr` is a literal integer reference like `&199`, returns the literal integer without
+    ///   references.
+    /// * If `expr` is anything else, returns `None`.
+    fn literal_integer<'expr, 'tcx>(
+        cx: &LateContext<'tcx>,
+        expr: &'expr hir::Expr<'tcx>,
+    ) -> Option<&'expr hir::Expr<'tcx>> {
+        let expr_refs = cx.typeck_results().expr_ty(expr).peel_refs();
+
+        if !expr_refs.is_integral() {
+            return None;
+        }
+
+        if matches!(expr.kind, hir::ExprKind::Lit(_)) {
+            return Some(expr);
+        }
+
+        if let hir::ExprKind::AddrOf(.., inn) = expr.kind && let hir::ExprKind::Lit(_) = inn.kind {
+            return Some(inn)
+        }
+
+        None
+    }
+
     /// Manages when the lint should be triggered. Operations in constant environments, hard coded
     /// types, custom allowed types and non-constant operations that won't overflow are ignored.
-    fn manage_bin_ops(
+    fn manage_bin_ops<'tcx>(
         &mut self,
-        cx: &LateContext<'_>,
-        expr: &hir::Expr<'_>,
+        cx: &LateContext<'tcx>,
+        expr: &hir::Expr<'tcx>,
         op: &Spanned<hir::BinOpKind>,
-        lhs: &hir::Expr<'_>,
-        rhs: &hir::Expr<'_>,
+        lhs: &hir::Expr<'tcx>,
+        rhs: &hir::Expr<'tcx>,
     ) {
         if constant_simple(cx, cx.typeck_results(), expr).is_some() {
             return;
@@ -119,14 +137,11 @@ impl ArithmeticSideEffects {
         if self.is_allowed_ty(cx, lhs) || self.is_allowed_ty(cx, rhs) {
             return;
         }
-        let has_valid_op = match (
-            Self::is_literal_integer(lhs, cx.typeck_results().expr_ty(lhs).peel_refs()),
-            Self::is_literal_integer(rhs, cx.typeck_results().expr_ty(rhs).peel_refs()),
-        ) {
-            (true, true) => true,
-            (true, false) => Self::has_valid_op(op, lhs),
-            (false, true) => Self::has_valid_op(op, rhs),
-            (false, false) => false,
+        let has_valid_op = match (Self::literal_integer(cx, lhs), Self::literal_integer(cx, rhs)) {
+            (None, None) => false,
+            (None, Some(local_expr)) => Self::has_valid_op(op, local_expr),
+            (Some(local_expr), None) => Self::has_valid_op(op, local_expr),
+            (Some(_), Some(_)) => true,
         };
         if !has_valid_op {
             self.issue_lint(cx, expr);
@@ -135,7 +150,7 @@ impl ArithmeticSideEffects {
 }
 
 impl<'tcx> LateLintPass<'tcx> for ArithmeticSideEffects {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &hir::Expr<'tcx>) {
         if self.expr_span.is_some() || self.const_span.map_or(false, |sp| sp.contains(expr.span)) {
             return;
         }
diff --git a/tests/ui/arithmetic_side_effects.rs b/tests/ui/arithmetic_side_effects.rs
index dd24f5aa592..6741e148547 100644
--- a/tests/ui/arithmetic_side_effects.rs
+++ b/tests/ui/arithmetic_side_effects.rs
@@ -2,11 +2,12 @@
     clippy::assign_op_pattern,
     clippy::erasing_op,
     clippy::identity_op,
+    clippy::op_ref,
     clippy::unnecessary_owned_empty_strings,
     arithmetic_overflow,
     unconditional_panic
 )]
-#![feature(inline_const, saturating_int_impl)]
+#![feature(const_mut_refs, inline_const, saturating_int_impl)]
 #![warn(clippy::arithmetic_side_effects)]
 
 use core::num::{Saturating, Wrapping};
@@ -79,33 +80,50 @@ pub fn const_ops_should_not_trigger_the_lint() {
     const _: i32 = 1 + 1;
     let _ = const { 1 + 1 };
 
-    const _: i32 = { let mut n = -1; n = -(-1); n = -n; n };
-    let _ = const { let mut n = -1; n = -(-1); n = -n; n };
+    const _: i32 = { let mut n = 1; n = -1; n = -(-1); n = -n; n };
+    let _ = const { let mut n = 1; n = -1; n = -(-1); n = -n; n };
 }
 
-pub fn non_overflowing_runtime_ops_or_ops_already_handled_by_the_compiler() {
+pub fn non_overflowing_ops_or_ops_already_handled_by_the_compiler_should_not_trigger_the_lint() {
     let mut _n = i32::MAX;
 
     // Assign
     _n += 0;
+    _n += &0;
     _n -= 0;
+    _n -= &0;
     _n /= 99;
+    _n /= &99;
     _n %= 99;
+    _n %= &99;
     _n *= 0;
+    _n *= &0;
     _n *= 1;
+    _n *= &1;
 
     // Binary
     _n = _n + 0;
+    _n = _n + &0;
     _n = 0 + _n;
+    _n = &0 + _n;
     _n = _n - 0;
+    _n = _n - &0;
     _n = 0 - _n;
+    _n = &0 - _n;
     _n = _n / 99;
+    _n = _n / &99;
     _n = _n % 99;
+    _n = _n % &99;
     _n = _n * 0;
+    _n = _n * &0;
     _n = 0 * _n;
+    _n = &0 * _n;
     _n = _n * 1;
+    _n = _n * &1;
     _n = 1 * _n;
+    _n = &1 * _n;
     _n = 23 + 85;
+    _n = &23 + &85;
 
     // Unary
     _n = -1;
@@ -117,23 +135,37 @@ pub fn overflowing_runtime_ops() {
 
     // Assign
     _n += 1;
+    _n += &1;
     _n -= 1;
+    _n -= &1;
     _n /= 0;
+    _n /= &0;
     _n %= 0;
+    _n %= &0;
     _n *= 2;
+    _n *= &2;
 
     // Binary
     _n = _n + 1;
+    _n = _n + &1;
     _n = 1 + _n;
+    _n = &1 + _n;
     _n = _n - 1;
+    _n = _n - &1;
     _n = 1 - _n;
+    _n = &1 - _n;
     _n = _n / 0;
+    _n = _n / &0;
     _n = _n % 0;
+    _n = _n % &0;
     _n = _n * 2;
+    _n = _n * &2;
     _n = 2 * _n;
+    _n = &2 * _n;
 
     // Unary
     _n = -_n;
+    _n = -&_n;
 }
 
 fn main() {}
diff --git a/tests/ui/arithmetic_side_effects.stderr b/tests/ui/arithmetic_side_effects.stderr
index a2a856efbff..4dce13b624b 100644
--- a/tests/ui/arithmetic_side_effects.stderr
+++ b/tests/ui/arithmetic_side_effects.stderr
@@ -1,5 +1,5 @@
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:119:5
+  --> $DIR/arithmetic_side_effects.rs:137:5
    |
 LL |     _n += 1;
    |     ^^^^^^^
@@ -7,82 +7,166 @@ LL |     _n += 1;
    = note: `-D clippy::arithmetic-side-effects` implied by `-D warnings`
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:120:5
+  --> $DIR/arithmetic_side_effects.rs:138:5
+   |
+LL |     _n += &1;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:139:5
    |
 LL |     _n -= 1;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:121:5
+  --> $DIR/arithmetic_side_effects.rs:140:5
+   |
+LL |     _n -= &1;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:141:5
    |
 LL |     _n /= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:122:5
+  --> $DIR/arithmetic_side_effects.rs:142:5
+   |
+LL |     _n /= &0;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:143:5
    |
 LL |     _n %= 0;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:123:5
+  --> $DIR/arithmetic_side_effects.rs:144:5
+   |
+LL |     _n %= &0;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:145:5
    |
 LL |     _n *= 2;
    |     ^^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:126:10
+  --> $DIR/arithmetic_side_effects.rs:146:5
+   |
+LL |     _n *= &2;
+   |     ^^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:149:10
    |
 LL |     _n = _n + 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:127:10
+  --> $DIR/arithmetic_side_effects.rs:150:10
+   |
+LL |     _n = _n + &1;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:151:10
    |
 LL |     _n = 1 + _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:128:10
+  --> $DIR/arithmetic_side_effects.rs:152:10
+   |
+LL |     _n = &1 + _n;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:153:10
    |
 LL |     _n = _n - 1;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:129:10
+  --> $DIR/arithmetic_side_effects.rs:154:10
+   |
+LL |     _n = _n - &1;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:155:10
    |
 LL |     _n = 1 - _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:130:10
+  --> $DIR/arithmetic_side_effects.rs:156:10
+   |
+LL |     _n = &1 - _n;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:157:10
    |
 LL |     _n = _n / 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:131:10
+  --> $DIR/arithmetic_side_effects.rs:158:10
+   |
+LL |     _n = _n / &0;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:159:10
    |
 LL |     _n = _n % 0;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:132:10
+  --> $DIR/arithmetic_side_effects.rs:160:10
+   |
+LL |     _n = _n % &0;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:161:10
    |
 LL |     _n = _n * 2;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:133:10
+  --> $DIR/arithmetic_side_effects.rs:162:10
+   |
+LL |     _n = _n * &2;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:163:10
    |
 LL |     _n = 2 * _n;
    |          ^^^^^^
 
 error: arithmetic operation that can potentially result in unexpected side-effects
-  --> $DIR/arithmetic_side_effects.rs:136:10
+  --> $DIR/arithmetic_side_effects.rs:164:10
+   |
+LL |     _n = &2 * _n;
+   |          ^^^^^^^
+
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:167:10
    |
 LL |     _n = -_n;
    |          ^^^
 
-error: aborting due to 14 previous errors
+error: arithmetic operation that can potentially result in unexpected side-effects
+  --> $DIR/arithmetic_side_effects.rs:168:10
+   |
+LL |     _n = -&_n;
+   |          ^^^^
+
+error: aborting due to 28 previous errors