about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrik Sverdrup <bluss@users.noreply.github.com>2016-03-04 21:01:59 +0100
committerUlrik Sverdrup <bluss@users.noreply.github.com>2016-03-04 21:07:11 +0100
commita03222c2b16648c466f836d5eec425fc3c648aa4 (patch)
tree238d13ac9cfa9b7f14746bdcc0c2a61b47fd1600
parentc97524bef9e59a80875110b402b3fc8c139d4d64 (diff)
Do not trigger unused_assignments for overloaded AssignOps
If `v` were a type with some kind of indirection, so that `v += 1` would
have an effect even if `v` were not used anymore, the unused_assignments lint
would mark a false positive.

This exempts overloaded (non-primitive) assign ops from being treated as
assignments (they are method calls).

The previous compile-fail tests that ensure x += 1 can trigger for
primitive types continue to pass. Added a representative test for the
"view" indirection.
-rw-r--r--src/librustc/middle/liveness.rs4
-rw-r--r--src/test/run-pass/augmented-assignments.rs18
2 files changed, 21 insertions, 1 deletions
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 81f0cb1fbb2..b581466fede 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -1415,7 +1415,9 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       }
 
       hir::ExprAssignOp(_, ref l, _) => {
-        this.check_lvalue(&l);
+        if !this.ir.tcx.is_method_call(expr.id) {
+            this.check_lvalue(&l);
+        }
 
         intravisit::walk_expr(this, expr);
       }
diff --git a/src/test/run-pass/augmented-assignments.rs b/src/test/run-pass/augmented-assignments.rs
index 8c9ebcd274a..3ed9e8548dc 100644
--- a/src/test/run-pass/augmented-assignments.rs
+++ b/src/test/run-pass/augmented-assignments.rs
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![deny(unused_assignments)]
+
 use std::mem;
 use std::ops::{
     AddAssign, BitAndAssign, BitOrAssign, BitXorAssign, DivAssign, Index, MulAssign, RemAssign,
@@ -27,6 +29,8 @@ impl Slice {
     }
 }
 
+struct View<'a>(&'a mut [i32]);
+
 fn main() {
     let mut x = Int(1);
 
@@ -78,6 +82,12 @@ fn main() {
     assert_eq!(array[0], 1);
     assert_eq!(array[1], 2);
     assert_eq!(array[2], 3);
+
+    // sized indirection
+    // check that this does *not* trigger the unused_assignments lint
+    let mut array = [0, 1, 2];
+    let mut view = View(&mut array);
+    view += 1;
 }
 
 impl AddAssign for Int {
@@ -159,3 +169,11 @@ impl AddAssign<i32> for Slice {
         }
     }
 }
+
+impl<'a> AddAssign<i32> for View<'a> {
+    fn add_assign(&mut self, rhs: i32) {
+        for lhs in self.0.iter_mut() {
+            *lhs += rhs;
+        }
+    }
+}