diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index b84cd212c4ab4..e70b7f89a6767 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 0000000000000..addda42775399 --- /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 or the MIT license +// , 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 0000000000000..a34d524d28f2e --- /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 0000000000000..97092b7f9d759 --- /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 or the MIT license +// , 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 0000000000000..02b32dc363ae7 --- /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 +