Skip to content

Commit ba9c383

Browse files
committed
Only report error for first issued loan with conflict
Change error reporting of conflicting loans to stop earlier after printing an error for a given borrow, instead of proceeding to error on possibly every issued loan. This keeps us down to O(n) errors (for n problem lines), instead of O(n^2) errors in some cases. Fixes #27485.
1 parent bfb2603 commit ba9c383

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

src/librustc_borrowck/borrowck/check_loans.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -363,13 +363,14 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
363363
let new_loan_indices = self.loans_generated_by(node);
364364
debug!("new_loan_indices = {:?}", new_loan_indices);
365365

366-
self.each_issued_loan(node, |issued_loan| {
367-
for &new_loan_index in &new_loan_indices {
366+
for &new_loan_index in &new_loan_indices {
367+
self.each_issued_loan(node, |issued_loan| {
368368
let new_loan = &self.all_loans[new_loan_index];
369-
self.report_error_if_loans_conflict(issued_loan, new_loan);
370-
}
371-
true
372-
});
369+
// Only report an error for the first issued loan that conflicts
370+
// to avoid O(n^2) errors.
371+
self.report_error_if_loans_conflict(issued_loan, new_loan)
372+
});
373+
}
373374

374375
for (i, &x) in new_loan_indices.iter().enumerate() {
375376
let old_loan = &self.all_loans[x];
@@ -382,7 +383,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
382383

383384
pub fn report_error_if_loans_conflict(&self,
384385
old_loan: &Loan<'tcx>,
385-
new_loan: &Loan<'tcx>) {
386+
new_loan: &Loan<'tcx>)
387+
-> bool {
386388
//! Checks whether `old_loan` and `new_loan` can safely be issued
387389
//! simultaneously.
388390
@@ -397,7 +399,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
397399
self.report_error_if_loan_conflicts_with_restriction(
398400
old_loan, new_loan, old_loan, new_loan) &&
399401
self.report_error_if_loan_conflicts_with_restriction(
400-
new_loan, old_loan, old_loan, new_loan);
402+
new_loan, old_loan, old_loan, new_loan)
401403
}
402404

403405
pub fn report_error_if_loan_conflicts_with_restriction(&self,
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Test to ensure we only report an error for the first issued loan that
12+
// conflicts with a new loan, as opposed to every issued loan. This keeps us
13+
// down to O(n) errors (for n problem lines), instead of O(n^2) errors.
14+
15+
fn main() {
16+
let mut x = 1;
17+
let mut addr;
18+
loop {
19+
match 1 {
20+
1 => { addr = &mut x; }
21+
//~^ ERROR cannot borrow `x` as mutable more than once at a time
22+
2 => { addr = &mut x; }
23+
//~^ ERROR cannot borrow `x` as mutable more than once at a time
24+
_ => { addr = &mut x; }
25+
//~^ ERROR cannot borrow `x` as mutable more than once at a time
26+
}
27+
}
28+
}

0 commit comments

Comments
 (0)