Skip to content

Commit 92786a4

Browse files
committed
consolidate and use find_sub_region_live_at for everything
remove the old blame system
1 parent 078220d commit 92786a4

File tree

4 files changed

+47
-96
lines changed

4 files changed

+47
-96
lines changed

src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
5454
borrow_region_vid
5555
);
5656

57-
let region_sub = regioncx.find_constraint(borrow_region_vid, context.loc);
57+
let region_sub = regioncx.find_sub_region_live_at(borrow_region_vid, context.loc);
5858

5959
debug!(
6060
"explain_why_borrow_contains_point: region_sub={:?}",

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

Lines changed: 24 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::nll::region_infer::values::ToElementIndex;
1211
use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext};
1312
use borrow_check::nll::type_check::Locations;
1413
use rustc::hir::def_id::DefId;
@@ -75,11 +74,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
7574
mir: &Mir<'tcx>,
7675
from_region: RegionVid,
7776
target_test: impl Fn(RegionVid) -> bool,
78-
) -> (ConstraintCategory, Span) {
77+
) -> (ConstraintCategory, Span, RegionVid) {
7978
debug!("best_blame_constraint(from_region={:?})", from_region);
8079

8180
// Find all paths
82-
let path = self
81+
let (path, target_region) = self
8382
.find_constraint_paths_between_regions(from_region, target_test)
8483
.unwrap();
8584
debug!("best_blame_constraint: path={:#?}", path);
@@ -98,19 +97,24 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9897
categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0));
9998
debug!("best_blame_constraint: sorted_path={:?}", categorized_path);
10099

101-
*categorized_path.first().unwrap()
100+
let &(category, span) = categorized_path.first().unwrap();
101+
102+
(category, span, target_region)
102103
}
103104

104105
/// Walks the graph of constraints (where `'a: 'b` is considered
105106
/// an edge `'a -> 'b`) to find all paths from `from_region` to
106107
/// `to_region`. The paths are accumulated into the vector
107108
/// `results`. The paths are stored as a series of
108109
/// `ConstraintIndex` values -- in other words, a list of *edges*.
110+
///
111+
/// Returns: a series of constraints as well as the region `R`
112+
/// that passed the target test.
109113
fn find_constraint_paths_between_regions(
110114
&self,
111115
from_region: RegionVid,
112116
target_test: impl Fn(RegionVid) -> bool,
113-
) -> Option<Vec<ConstraintIndex>> {
117+
) -> Option<(Vec<ConstraintIndex>, RegionVid)> {
114118
let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions);
115119
context[from_region] = Trace::StartRegion;
116120

@@ -138,7 +142,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
138142

139143
Trace::StartRegion => {
140144
result.reverse();
141-
return Some(result);
145+
return Some((result, r));
142146
}
143147
}
144148
}
@@ -253,7 +257,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
253257
) {
254258
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
255259

256-
let (category, span) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr);
260+
let (category, span, _) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr);
257261

258262
// Check if we can use one of the "nice region errors".
259263
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
@@ -393,82 +397,21 @@ impl<'tcx> RegionInferenceContext<'tcx> {
393397
diag.buffer(errors_buffer);
394398
}
395399

396-
// Find some constraint `X: Y` where:
397-
// - `fr1: X` transitively
398-
// - and `Y` is live at `elem`
399-
crate fn find_constraint(&self, fr1: RegionVid, elem: Location) -> RegionVid {
400-
let index = self.blame_constraint(fr1, elem);
401-
self.constraints[index].sub
402-
}
403-
404-
/// Tries to finds a good span to blame for the fact that `fr1`
405-
/// contains `fr2`.
406-
pub(super) fn blame_constraint(
407-
&self,
408-
fr1: RegionVid,
409-
elem: impl ToElementIndex,
410-
) -> ConstraintIndex {
411-
// Find everything that influenced final value of `fr`.
412-
let influenced_fr1 = self.dependencies(fr1);
413-
414-
// Try to find some outlives constraint `'X: fr2` where `'X`
415-
// influenced `fr1`. Blame that.
416-
//
417-
// NB, this is a pretty bad choice most of the time. In
418-
// particular, the connection between `'X` and `fr1` may not
419-
// be obvious to the user -- not to mention the naive notion
420-
// of dependencies, which doesn't account for the locations of
421-
// contraints at all. But it will do for now.
422-
let relevant_constraint = self.constraints
423-
.iter_enumerated()
424-
.filter_map(|(i, constraint)| {
425-
if !self.liveness_constraints.contains(constraint.sub, elem) {
426-
None
427-
} else {
428-
influenced_fr1[constraint.sup]
429-
.map(|distance| (distance, i))
430-
}
400+
// Finds some region R such that `fr1: R` and `R` is live at
401+
// `elem`.
402+
crate fn find_sub_region_live_at(&self, fr1: RegionVid, elem: Location) -> RegionVid {
403+
// Find all paths
404+
let (_path, r) = self
405+
.find_constraint_paths_between_regions(fr1, |r| {
406+
self.liveness_constraints.contains(r, elem)
431407
})
432-
.min() // constraining fr1 with fewer hops *ought* to be more obvious
433-
.map(|(_dist, i)| i);
434-
435-
relevant_constraint.unwrap_or_else(|| {
436-
bug!(
437-
"could not find any constraint to blame for {:?}: {:?}",
438-
fr1,
439-
elem,
440-
);
441-
})
408+
.unwrap();
409+
r
442410
}
443411

444-
/// Finds all regions whose values `'a` may depend on in some way.
445-
/// For each region, returns either `None` (does not influence
446-
/// `'a`) or `Some(d)` which indicates that it influences `'a`
447-
/// with distinct `d` (minimum number of edges that must be
448-
/// traversed).
449-
///
450-
/// Used during error reporting, extremely naive and inefficient.
451-
fn dependencies(&self, r0: RegionVid) -> IndexVec<RegionVid, Option<usize>> {
452-
let mut result_set = IndexVec::from_elem(None, &self.definitions);
453-
let mut changed = true;
454-
result_set[r0] = Some(0); // distance 0 from `r0`
455-
456-
while changed {
457-
changed = false;
458-
for constraint in self.constraints.iter() {
459-
if let Some(n) = result_set[constraint.sup] {
460-
let m = n + 1;
461-
if result_set[constraint.sub]
462-
.map(|distance| m < distance)
463-
.unwrap_or(true)
464-
{
465-
result_set[constraint.sub] = Some(m);
466-
changed = true;
467-
}
468-
}
469-
}
470-
}
471-
472-
result_set
412+
// Finds a good span to blame for the fact that `fr1` outlives `fr2`.
413+
crate fn find_outlives_blame_span(&self, mir: &Mir<'tcx>, fr1: RegionVid, fr2: RegionVid) -> Span {
414+
let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
415+
span
473416
}
474417
}

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -884,8 +884,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
884884
longer_fr, shorter_fr,
885885
);
886886

887-
let blame_index = self.blame_constraint(longer_fr, shorter_fr);
888-
let blame_span = self.constraints[blame_index].locations.span(mir);
887+
let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
889888

890889
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
891890
// Shrink `fr` until we find a non-local region (if we do).

src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,28 +2,37 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time
22
--> $DIR/mut-borrow-in-loop.rs:20:25
33
|
44
LL | (self.func)(arg) //~ ERROR cannot borrow
5-
| ------------^^^-
6-
| | |
7-
| | mutable borrow starts here in previous iteration of loop
8-
| borrow later used here
5+
| ^^^ mutable borrow starts here in previous iteration of loop
6+
|
7+
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
8+
--> $DIR/mut-borrow-in-loop.rs:17:6
9+
|
10+
LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
11+
| ^^
912

1013
error[E0499]: cannot borrow `*arg` as mutable more than once at a time
1114
--> $DIR/mut-borrow-in-loop.rs:26:25
1215
|
1316
LL | (self.func)(arg) //~ ERROR cannot borrow
14-
| ------------^^^-
15-
| | |
16-
| | mutable borrow starts here in previous iteration of loop
17-
| borrow later used here
17+
| ^^^ mutable borrow starts here in previous iteration of loop
18+
|
19+
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
20+
--> $DIR/mut-borrow-in-loop.rs:17:6
21+
|
22+
LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
23+
| ^^
1824

1925
error[E0499]: cannot borrow `*arg` as mutable more than once at a time
2026
--> $DIR/mut-borrow-in-loop.rs:33:25
2127
|
2228
LL | (self.func)(arg) //~ ERROR cannot borrow
23-
| ------------^^^-
24-
| | |
25-
| | mutable borrow starts here in previous iteration of loop
26-
| borrow later used here
29+
| ^^^ mutable borrow starts here in previous iteration of loop
30+
|
31+
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 17:6...
32+
--> $DIR/mut-borrow-in-loop.rs:17:6
33+
|
34+
LL | impl<'a, T : 'a> FuncWrapper<'a, T> {
35+
| ^^
2736

2837
error: aborting due to 3 previous errors
2938

0 commit comments

Comments
 (0)