Skip to content

Commit 03871f2

Browse files
committed
[WIP] compute region values using SCCs not iterative flow
This is marked as [WIP] because it contains a number of minor refactorings that ought to be broken out.
1 parent cef59aa commit 03871f2

File tree

8 files changed

+245
-232
lines changed

8 files changed

+245
-232
lines changed

Diff for: src/librustc_mir/borrow_check/nll/constraint_generation.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
210210
for (region, location, cause) in liveness_set {
211211
debug!("generate: {:#?} is live at {:#?}", region, location);
212212
let region_vid = regioncx.to_region_vid(region);
213-
regioncx.add_live_point(region_vid, *location, &cause);
213+
regioncx.add_live_element(region_vid, *location, &cause);
214214
}
215215

216216
if let Some(all_facts) = all_facts {
@@ -242,7 +242,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
242242
.tcx
243243
.for_each_free_region(&live_ty, |live_region| {
244244
let vid = live_region.to_region_vid();
245-
self.regioncx.add_live_point(vid, location, &cause);
245+
self.regioncx.add_live_element(vid, location, &cause);
246246
});
247247
}
248248
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
// Copyright 2017 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+
use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet};
12+
use rustc::ty::RegionVid;
13+
use rustc_data_structures::graph;
14+
use rustc_data_structures::indexed_vec::IndexVec;
15+
16+
/// An initial graph which contains a node for every constraint index.
17+
/// This is basically just represented as a set of linked lists; for
18+
/// each region R, there is a linked list of constraints that lead to
19+
/// other regions. (The graph is always defined relative to some set.)
20+
crate struct FullConstraintGraph<'s> {
21+
set: &'s ConstraintSet,
22+
first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
23+
next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
24+
}
25+
26+
impl<'s> FullConstraintGraph<'s> {
27+
/// Constraint a graph where each region constraint `R1: R2` is
28+
/// treated as an edge `R2 -> R1`. This is useful for cheaply
29+
/// finding dirty constraints.
30+
crate fn new(set: &'s ConstraintSet, num_region_vars: usize) -> Self {
31+
let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
32+
let mut next_constraints = IndexVec::from_elem(None, &set.constraints);
33+
34+
for (idx, constraint) in set.constraints.iter_enumerated().rev() {
35+
let mut head = &mut first_constraints[constraint.sup];
36+
let mut next = &mut next_constraints[idx];
37+
debug_assert!(next.is_none());
38+
*next = *head;
39+
*head = Some(idx);
40+
}
41+
42+
Self { set, first_constraints, next_constraints }
43+
}
44+
45+
crate fn sub_regions(
46+
&self,
47+
region_sup: RegionVid,
48+
) -> Successors<'_> {
49+
let first = self.first_constraints[region_sup];
50+
Successors { graph: self, pointer: first }
51+
}
52+
}
53+
54+
crate struct Successors<'s> {
55+
graph: &'s FullConstraintGraph<'s>,
56+
pointer: Option<ConstraintIndex>,
57+
}
58+
59+
impl<'s> Iterator for Successors<'s> {
60+
type Item = RegionVid;
61+
62+
fn next(&mut self) -> Option<Self::Item> {
63+
if let Some(p) = self.pointer {
64+
let r = self.graph.set[p].sub;
65+
self.pointer = self.graph.next_constraints[p];
66+
Some(r)
67+
} else {
68+
None
69+
}
70+
}
71+
}
72+
73+
impl<'s> graph::DirectedGraph for FullConstraintGraph<'s> {
74+
type Node = RegionVid;
75+
}
76+
77+
impl<'s> graph::WithNumNodes for FullConstraintGraph<'s> {
78+
fn num_nodes(&self) -> usize {
79+
self.first_constraints.len()
80+
}
81+
}
82+
83+
impl<'s> graph::WithSuccessors for FullConstraintGraph<'s> {
84+
fn successors<'graph>(
85+
&'graph self,
86+
node: Self::Node,
87+
) -> <Self as graph::GraphSuccessors<'graph>>::Iter {
88+
self.sub_regions(node)
89+
}
90+
}
91+
92+
impl<'s, 'graph> graph::GraphSuccessors<'graph> for FullConstraintGraph<'s> {
93+
type Item = RegionVid;
94+
type Iter = Successors<'graph>;
95+
}
96+

Diff for: src/librustc_mir/borrow_check/nll/constraints/mod.rs

+13-44
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,22 @@
99
// except according to those terms.
1010

1111
use rustc::ty::RegionVid;
12+
use rustc_data_structures::graph::scc::Sccs;
1213
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
1314
use borrow_check::nll::type_check::Locations;
1415

1516
use std::fmt;
1617
use std::ops::Deref;
1718

19+
mod full_graph;
20+
1821
#[derive(Clone, Default)]
1922
crate struct ConstraintSet {
2023
constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
2124
}
2225

2326
impl ConstraintSet {
24-
pub fn push(&mut self, constraint: OutlivesConstraint) {
27+
crate fn push(&mut self, constraint: OutlivesConstraint) {
2528
debug!(
2629
"ConstraintSet::push({:?}: {:?} @ {:?}",
2730
constraint.sup, constraint.sub, constraint.locations
@@ -32,12 +35,19 @@ impl ConstraintSet {
3235
}
3336
self.constraints.push(constraint);
3437
}
38+
39+
crate fn compute_sccs(&self, num_region_vars: usize) -> Sccs<RegionVid, ConstraintSccIndex> {
40+
let graph = &full_graph::FullConstraintGraph::new(self, num_region_vars);
41+
Sccs::new(graph)
42+
}
3543
}
3644

3745
impl Deref for ConstraintSet {
3846
type Target = IndexVec<ConstraintIndex, OutlivesConstraint>;
3947

40-
fn deref(&self) -> &Self::Target { &self.constraints }
48+
fn deref(&self) -> &Self::Target {
49+
&self.constraints
50+
}
4151
}
4252

4353
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -68,45 +78,4 @@ impl fmt::Debug for OutlivesConstraint {
6878

6979
newtype_index!(ConstraintIndex { DEBUG_FORMAT = "ConstraintIndex({})" });
7080

71-
crate struct ConstraintGraph {
72-
first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
73-
next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
74-
}
75-
76-
impl ConstraintGraph {
77-
/// Constraint a graph where each region constraint `R1: R2` is
78-
/// treated as an edge `R2 -> R1`. This is useful for cheaply
79-
/// finding dirty constraints.
80-
crate fn new(set: &ConstraintSet, num_region_vars: usize) -> Self {
81-
let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
82-
let mut next_constraints = IndexVec::from_elem(None, &set.constraints);
83-
84-
for (idx, constraint) in set.constraints.iter_enumerated().rev() {
85-
let mut head = &mut first_constraints[constraint.sub];
86-
let mut next = &mut next_constraints[idx];
87-
debug_assert!(next.is_none());
88-
*next = *head;
89-
*head = Some(idx);
90-
}
91-
92-
ConstraintGraph { first_constraints, next_constraints }
93-
}
94-
95-
/// Invokes `op` with the index of any constraints of the form
96-
/// `region_sup: region_sub`. These are the constraints that must
97-
/// be reprocessed when the value of `R1` changes. If you think of
98-
/// each constraint `R1: R2` as an edge `R2 -> R1`, then this
99-
/// gives the set of successors to R2.
100-
crate fn for_each_dependent(
101-
&self,
102-
region_sub: RegionVid,
103-
mut op: impl FnMut(ConstraintIndex),
104-
) {
105-
let mut p = self.first_constraints[region_sub];
106-
while let Some(dep_idx) = p {
107-
op(dep_idx);
108-
p = self.next_constraints[dep_idx];
109-
}
110-
}
111-
}
112-
81+
newtype_index!(ConstraintSccIndex { DEBUG_FORMAT = "ConstraintSccIndex({})" });

Diff for: src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {
185185

186186
stack.push(self.start_point);
187187
while let Some(p) = stack.pop() {
188-
if !self.regioncx.region_contains_point(self.borrow.region, p) {
188+
if !self.regioncx.region_contains(self.borrow.region, p) {
189189
continue;
190190
}
191191

Diff for: src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
321321

322322
while changed {
323323
changed = false;
324-
for constraint in &*self.constraints {
324+
for constraint in self.constraints.iter() {
325325
if let Some(n) = result_set[constraint.sup] {
326326
let m = n + 1;
327327
if result_set[constraint.sub]

0 commit comments

Comments
 (0)