diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 43e9cdd73c4..ff5d364b968 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -363,13 +363,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let new_loan_indices = self.loans_generated_by(node); debug!("new_loan_indices = {:?}", new_loan_indices); - self.each_issued_loan(node, |issued_loan| { - for &new_loan_index in &new_loan_indices { + for &new_loan_index in &new_loan_indices { + self.each_issued_loan(node, |issued_loan| { let new_loan = &self.all_loans[new_loan_index]; - self.report_error_if_loans_conflict(issued_loan, new_loan); - } - true - }); + // Only report an error for the first issued loan that conflicts + // to avoid O(n^2) errors. + self.report_error_if_loans_conflict(issued_loan, new_loan) + }); + } for (i, &x) in new_loan_indices.iter().enumerate() { let old_loan = &self.all_loans[x]; @@ -382,7 +383,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { pub fn report_error_if_loans_conflict(&self, old_loan: &Loan<'tcx>, - new_loan: &Loan<'tcx>) { + new_loan: &Loan<'tcx>) + -> bool { //! Checks whether `old_loan` and `new_loan` can safely be issued //! simultaneously. @@ -397,7 +399,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { self.report_error_if_loan_conflicts_with_restriction( old_loan, new_loan, old_loan, new_loan) && self.report_error_if_loan_conflicts_with_restriction( - new_loan, old_loan, old_loan, new_loan); + new_loan, old_loan, old_loan, new_loan) } pub fn report_error_if_loan_conflicts_with_restriction(&self, diff --git a/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs new file mode 100644 index 00000000000..38e0e27a7b9 --- /dev/null +++ b/src/test/compile-fail/borrowck-mut-borrow-linear-errors.rs @@ -0,0 +1,28 @@ +// Copyright 2015 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. + +// Test to ensure we only report an error for the first issued loan that +// conflicts with a new loan, as opposed to every issued loan. This keeps us +// down to O(n) errors (for n problem lines), instead of O(n^2) errors. + +fn main() { + let mut x = 1; + let mut addr; + loop { + match 1 { + 1 => { addr = &mut x; } + //~^ ERROR cannot borrow `x` as mutable more than once at a time + 2 => { addr = &mut x; } + //~^ ERROR cannot borrow `x` as mutable more than once at a time + _ => { addr = &mut x; } + //~^ ERROR cannot borrow `x` as mutable more than once at a time + } + } +}