about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs40
-rw-r--r--src/test/ui/borrowck/mut-borrow-in-loop.rs40
-rw-r--r--src/test/ui/borrowck/mut-borrow-in-loop.stderr29
-rw-r--r--src/test/ui/borrowck/mut-borrow-outside-loop.rs26
-rw-r--r--src/test/ui/borrowck/mut-borrow-outside-loop.stderr23
5 files changed, 145 insertions, 13 deletions
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index b84cd212c4a..e70b7f89a67 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -466,19 +466,33 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             let mut err = match (new_loan.kind, old_loan.kind) {
                 (ty::MutBorrow, ty::MutBorrow) => {
                     let mut err = struct_span_err!(self.bccx, new_loan.span, E0499,
-                                                  "cannot borrow `{}`{} as mutable \
-                                                  more than once at a time",
-                                                  nl, new_loan_msg);
-                    err.span_label(
-                            old_loan.span,
-                            format!("first mutable borrow occurs here{}", old_loan_msg));
-                    err.span_label(
-                            new_loan.span,
-                            format!("second mutable borrow occurs here{}", new_loan_msg));
-                    err.span_label(
-                            previous_end_span,
-                            "first borrow ends here");
-                    err
+                                                      "cannot borrow `{}`{} as mutable \
+                                                      more than once at a time",
+                                                      nl, new_loan_msg);
+
+                    if new_loan.span == old_loan.span {
+                        // Both borrows are happening in the same place
+                        // Meaning the borrow is occuring in a loop
+                        err.span_label(
+                                new_loan.span,
+                                format!("mutable borrow starts here in previous \
+                                        iteration of loop{}", new_loan_msg));
+                        err.span_label(
+                                previous_end_span,
+                                "mutable borrow ends here");
+                        err
+                    } else {
+                       err.span_label(
+                                old_loan.span,
+                                format!("first mutable borrow occurs here{}", old_loan_msg));
+                        err.span_label(
+                                new_loan.span,
+                                format!("second mutable borrow occurs here{}", new_loan_msg));
+                        err.span_label(
+                                previous_end_span,
+                                "first borrow ends here");
+                        err
+                    }
                 }
 
                 (ty::UniqueImmBorrow, ty::UniqueImmBorrow) => {
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.rs b/src/test/ui/borrowck/mut-borrow-in-loop.rs
new file mode 100644
index 00000000000..addda427753
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-in-loop.rs
@@ -0,0 +1,40 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// produce special borrowck message inside all kinds of loops
+
+struct FuncWrapper<'a, T : 'a> {
+    func : fn(&'a mut T) -> ()
+}
+
+impl<'a, T : 'a> FuncWrapper<'a, T> {
+    fn in_loop(self, arg : &'a mut T) {
+        loop {
+            (self.func)(arg)
+        }
+    }
+
+    fn in_while(self, arg : &'a mut T) {
+        while true {
+            (self.func)(arg)
+        }
+    }
+
+    fn in_for(self, arg : &'a mut T) {
+        let v : Vec<()> = vec![];
+        for _ in v.iter() {
+            (self.func)(arg)
+        }
+    }
+}
+
+fn main() {
+}
+
diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.stderr
new file mode 100644
index 00000000000..a34d524d28f
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-in-loop.stderr
@@ -0,0 +1,29 @@
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:20:25
+   |
+20 |             (self.func)(arg)
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+21 |         }
+22 |     }
+   |     - mutable borrow ends here
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:26:25
+   |
+26 |             (self.func)(arg)
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+27 |         }
+28 |     }
+   |     - mutable borrow ends here
+
+error[E0499]: cannot borrow `*arg` as mutable more than once at a time
+  --> $DIR/mut-borrow-in-loop.rs:33:25
+   |
+33 |             (self.func)(arg)
+   |                         ^^^ mutable borrow starts here in previous iteration of loop
+34 |         }
+35 |     }
+   |     - mutable borrow ends here
+
+error: aborting due to 3 previous errors
+
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.rs b/src/test/ui/borrowck/mut-borrow-outside-loop.rs
new file mode 100644
index 00000000000..97092b7f9d7
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.rs
@@ -0,0 +1,26 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ensure borrowck messages are correct outside special case
+
+fn main() {
+    let mut void = ();
+
+    let first = &mut void;
+    let second = &mut void;
+
+    loop {
+        let mut inner_void = ();
+
+        let inner_first = &mut inner_void;
+        let inner_second = &mut inner_void;
+    }
+}
+
diff --git a/src/test/ui/borrowck/mut-borrow-outside-loop.stderr b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr
new file mode 100644
index 00000000000..02b32dc363a
--- /dev/null
+++ b/src/test/ui/borrowck/mut-borrow-outside-loop.stderr
@@ -0,0 +1,23 @@
+error[E0499]: cannot borrow `void` as mutable more than once at a time
+  --> $DIR/mut-borrow-outside-loop.rs:17:23
+   |
+16 |     let first = &mut void;
+   |                      ---- first mutable borrow occurs here
+17 |     let second = &mut void;
+   |                       ^^^^ second mutable borrow occurs here
+...
+25 | }
+   | - first borrow ends here
+
+error[E0499]: cannot borrow `inner_void` as mutable more than once at a time
+  --> $DIR/mut-borrow-outside-loop.rs:23:33
+   |
+22 |         let inner_first = &mut inner_void;
+   |                                ---------- first mutable borrow occurs here
+23 |         let inner_second = &mut inner_void;
+   |                                 ^^^^^^^^^^ second mutable borrow occurs here
+24 |     }
+   |     - first borrow ends here
+
+error: aborting due to 2 previous errors
+