Skip to content

Commit 887296e

Browse files
committed
make it possible to customize the RegionGraph direction
1 parent a92bf8d commit 887296e

File tree

3 files changed

+93
-31
lines changed

3 files changed

+93
-31
lines changed

src/librustc_mir/borrow_check/nll/constraints/graph.rs

+86-24
Original file line numberDiff line numberDiff line change
@@ -8,41 +8,100 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet};
11+
use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet, OutlivesConstraint};
1212
use rustc::ty::RegionVid;
1313
use rustc_data_structures::graph;
1414
use rustc_data_structures::indexed_vec::IndexVec;
1515

16-
crate struct ConstraintGraph {
16+
/// The construct graph organizes the constraints by their end-points.
17+
/// It can be used to view a `R1: R2` constraint as either an edge `R1
18+
/// -> R2` or `R2 -> R1` depending on the direction type `D`.
19+
crate struct ConstraintGraph<D: ConstraintGraphDirecton> {
20+
_direction: D,
1721
first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
1822
next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
1923
}
2024

21-
impl ConstraintGraph {
25+
crate type NormalConstraintGraph = ConstraintGraph<Normal>;
26+
27+
/// Marker trait that controls whether a `R1: R2` constraint
28+
/// represents an edge `R1 -> R2` or `R2 -> R1`.
29+
crate trait ConstraintGraphDirecton: Copy + 'static {
30+
fn start_region(c: &OutlivesConstraint) -> RegionVid;
31+
fn end_region(c: &OutlivesConstraint) -> RegionVid;
32+
}
33+
34+
/// In normal mode, a `R1: R2` constraint results in an edge `R1 ->
35+
/// R2`. This is what we use when constructing the SCCs for
36+
/// inference. This is because we compute the value of R1 by union'ing
37+
/// all the things that it relies on.
38+
#[derive(Copy, Clone, Debug)]
39+
crate struct Normal;
40+
41+
impl ConstraintGraphDirecton for Normal {
42+
fn start_region(c: &OutlivesConstraint) -> RegionVid {
43+
c.sup
44+
}
45+
46+
fn end_region(c: &OutlivesConstraint) -> RegionVid {
47+
c.sub
48+
}
49+
}
50+
51+
/// In reverse mode, a `R1: R2` constraint results in an edge `R2 ->
52+
/// R1`. We use this for optimizing liveness computation, because then
53+
/// we wish to iterate from a region (e.g., R2) to all the regions
54+
/// that will outlive it (e.g., R1).
55+
#[derive(Copy, Clone, Debug)]
56+
crate struct Reverse;
57+
58+
impl ConstraintGraphDirecton for Reverse {
59+
fn start_region(c: &OutlivesConstraint) -> RegionVid {
60+
c.sub
61+
}
62+
63+
fn end_region(c: &OutlivesConstraint) -> RegionVid {
64+
c.sup
65+
}
66+
}
67+
68+
impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
2269
/// Create a "dependency graph" where each region constraint `R1:
2370
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
2471
/// construct SCCs for region inference but also for error
2572
/// reporting.
26-
crate fn new(set: &ConstraintSet, num_region_vars: usize) -> Self {
73+
crate fn new(
74+
direction: D,
75+
set: &ConstraintSet,
76+
num_region_vars: usize,
77+
) -> Self {
2778
let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
2879
let mut next_constraints = IndexVec::from_elem(None, &set.constraints);
2980

3081
for (idx, constraint) in set.constraints.iter_enumerated().rev() {
31-
let head = &mut first_constraints[constraint.sup];
82+
let head = &mut first_constraints[D::start_region(constraint)];
3283
let next = &mut next_constraints[idx];
3384
debug_assert!(next.is_none());
3485
*next = *head;
3586
*head = Some(idx);
3687
}
3788

3889
Self {
90+
_direction: direction,
3991
first_constraints,
4092
next_constraints,
4193
}
4294
}
4395

96+
/// Given the constraint set from which this graph was built
97+
/// creates a region graph so that you can iterate over *regions*
98+
/// and not constraints.
99+
crate fn region_graph<'rg>(&'rg self, set: &'rg ConstraintSet) -> RegionGraph<'rg, D> {
100+
RegionGraph::new(set, self)
101+
}
102+
44103
/// Given a region `R`, iterate over all constraints `R: R1`.
45-
crate fn outgoing_edges(&self, region_sup: RegionVid) -> Edges<'_> {
104+
crate fn outgoing_edges(&self, region_sup: RegionVid) -> Edges<'_, D> {
46105
let first = self.first_constraints[region_sup];
47106
Edges {
48107
graph: self,
@@ -51,12 +110,12 @@ impl ConstraintGraph {
51110
}
52111
}
53112

54-
crate struct Edges<'s> {
55-
graph: &'s ConstraintGraph,
113+
crate struct Edges<'s, D: ConstraintGraphDirecton> {
114+
graph: &'s ConstraintGraph<D>,
56115
pointer: Option<ConstraintIndex>,
57116
}
58117

59-
impl<'s> Iterator for Edges<'s> {
118+
impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
60119
type Item = ConstraintIndex;
61120

62121
fn next(&mut self) -> Option<Self::Item> {
@@ -69,17 +128,20 @@ impl<'s> Iterator for Edges<'s> {
69128
}
70129
}
71130

72-
crate struct RegionGraph<'s> {
131+
/// This struct brings together a constraint set and a (normal, not
132+
/// reverse) constraint graph. It implements the graph traits and is
133+
/// usd for doing the SCC computation.
134+
crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
73135
set: &'s ConstraintSet,
74-
constraint_graph: &'s ConstraintGraph,
136+
constraint_graph: &'s ConstraintGraph<D>,
75137
}
76138

77-
impl<'s> RegionGraph<'s> {
139+
impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
78140
/// Create a "dependency graph" where each region constraint `R1:
79141
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
80142
/// construct SCCs for region inference but also for error
81143
/// reporting.
82-
crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph) -> Self {
144+
crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph<D>) -> Self {
83145
Self {
84146
set,
85147
constraint_graph,
@@ -88,47 +150,47 @@ impl<'s> RegionGraph<'s> {
88150

89151
/// Given a region `R`, iterate over all regions `R1` such that
90152
/// there exists a constraint `R: R1`.
91-
crate fn sub_regions(&self, region_sup: RegionVid) -> Successors<'_> {
153+
crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> {
92154
Successors {
93155
set: self.set,
94156
edges: self.constraint_graph.outgoing_edges(region_sup),
95157
}
96158
}
97159
}
98160

99-
crate struct Successors<'s> {
161+
crate struct Successors<'s, D: ConstraintGraphDirecton> {
100162
set: &'s ConstraintSet,
101-
edges: Edges<'s>,
163+
edges: Edges<'s, D>,
102164
}
103165

104-
impl<'s> Iterator for Successors<'s> {
166+
impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> {
105167
type Item = RegionVid;
106168

107169
fn next(&mut self) -> Option<Self::Item> {
108-
self.edges.next().map(|c| self.set[c].sub)
170+
self.edges.next().map(|c| D::end_region(&self.set[c]))
109171
}
110172
}
111173

112-
impl<'s> graph::DirectedGraph for RegionGraph<'s> {
174+
impl<'s, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, D> {
113175
type Node = RegionVid;
114176
}
115177

116-
impl<'s> graph::WithNumNodes for RegionGraph<'s> {
178+
impl<'s, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, D> {
117179
fn num_nodes(&self) -> usize {
118180
self.constraint_graph.first_constraints.len()
119181
}
120182
}
121183

122-
impl<'s> graph::WithSuccessors for RegionGraph<'s> {
184+
impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> {
123185
fn successors<'graph>(
124186
&'graph self,
125187
node: Self::Node,
126188
) -> <Self as graph::GraphSuccessors<'graph>>::Iter {
127-
self.sub_regions(node)
189+
self.outgoing_regions(node)
128190
}
129191
}
130192

131-
impl<'s, 'graph> graph::GraphSuccessors<'graph> for RegionGraph<'s> {
193+
impl<'s, 'graph, D: ConstraintGraphDirecton> graph::GraphSuccessors<'graph> for RegionGraph<'s, D> {
132194
type Item = RegionVid;
133-
type Iter = Successors<'graph>;
195+
type Iter = Successors<'graph, D>;
134196
}

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

+5-5
Original file line numberDiff line numberDiff line change
@@ -36,24 +36,24 @@ impl ConstraintSet {
3636
self.constraints.push(constraint);
3737
}
3838

39-
/// Constructs a graph from the constraint set; the graph makes it
39+
/// Constructs a "normal" graph from the constraint set; the graph makes it
4040
/// easy to find the constraints affecting a particular region.
4141
///
4242
/// NB: This graph contains a "frozen" view of the current
4343
/// constraints. any new constraints added to the `ConstraintSet`
4444
/// after the graph is built will not be present in the graph.
45-
crate fn graph(&self, num_region_vars: usize) -> graph::ConstraintGraph {
46-
graph::ConstraintGraph::new(self, num_region_vars)
45+
crate fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph {
46+
graph::ConstraintGraph::new(graph::Normal, self, num_region_vars)
4747
}
4848

4949
/// Compute cycles (SCCs) in the graph of regions. In particular,
5050
/// find all regions R1, R2 such that R1: R2 and R2: R1 and group
5151
/// them into an SCC, and find the relationships between SCCs.
5252
crate fn compute_sccs(
5353
&self,
54-
constraint_graph: &graph::ConstraintGraph,
54+
constraint_graph: &graph::NormalConstraintGraph,
5555
) -> Sccs<RegionVid, ConstraintSccIndex> {
56-
let region_graph = &graph::RegionGraph::new(self, constraint_graph);
56+
let region_graph = &constraint_graph.region_graph(self);
5757
Sccs::new(region_graph)
5858
}
5959
}

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

+2-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
// except according to those terms.
1010

1111
use super::universal_regions::UniversalRegions;
12-
use borrow_check::nll::constraints::graph::ConstraintGraph;
12+
use borrow_check::nll::constraints::graph::NormalConstraintGraph;
1313
use borrow_check::nll::constraints::{
1414
ConstraintIndex, ConstraintSccIndex, ConstraintSet, OutlivesConstraint,
1515
};
@@ -61,7 +61,7 @@ pub struct RegionInferenceContext<'tcx> {
6161
/// The constraint-set, but in graph form, making it easy to traverse
6262
/// the constraints adjacent to a particular region. Used to construct
6363
/// the SCC (see `constraint_sccs`) and for error reporting.
64-
constraint_graph: Rc<ConstraintGraph>,
64+
constraint_graph: Rc<NormalConstraintGraph>,
6565

6666
/// The SCC computed from `constraints` and the constraint graph. Used to compute the values
6767
/// of each region.

0 commit comments

Comments
 (0)