Skip to content

Commit 2c92308

Browse files
committed
Auto merge of #53177 - nikomatsakis:nll-redundant-borrows-and-escaping-values, r=pnkfelix
optimize redundant borrows and escaping paths in NLL This builds on #53168 and adds a commit that addresses #53176 -- or at least I think it does. I marked this as WIP because I want to see the test results (and measure the performance). I also want to double check we're not adding in any unsoundness here.
2 parents a77dfcc + ff7f6d5 commit 2c92308

File tree

15 files changed

+388
-202
lines changed

15 files changed

+388
-202
lines changed

src/librustc_mir/borrow_check/borrow_set.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> {
159159
location: mir::Location,
160160
) {
161161
if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue {
162-
if borrowed_place.is_unsafe_place(self.tcx, self.mir) {
162+
if borrowed_place.ignore_borrow(self.tcx, self.mir) {
163163
return;
164164
}
165165

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

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

3083
for (idx, constraint) in set.constraints.iter_enumerated().rev() {
31-
let head = &mut first_constraints[constraint.sup];
84+
let head = &mut first_constraints[D::start_region(constraint)];
3285
let next = &mut next_constraints[idx];
3386
debug_assert!(next.is_none());
3487
*next = *head;
3588
*head = Some(idx);
3689
}
3790

3891
Self {
92+
_direction: direction,
3993
first_constraints,
4094
next_constraints,
4195
}
4296
}
4397

98+
/// Given the constraint set from which this graph was built
99+
/// creates a region graph so that you can iterate over *regions*
100+
/// and not constraints.
101+
crate fn region_graph<'rg>(&'rg self, set: &'rg ConstraintSet) -> RegionGraph<'rg, D> {
102+
RegionGraph::new(set, self)
103+
}
104+
44105
/// Given a region `R`, iterate over all constraints `R: R1`.
45-
crate fn outgoing_edges(&self, region_sup: RegionVid) -> Edges<'_> {
106+
crate fn outgoing_edges(&self, region_sup: RegionVid) -> Edges<'_, D> {
46107
let first = self.first_constraints[region_sup];
47108
Edges {
48109
graph: self,
@@ -51,12 +112,12 @@ impl ConstraintGraph {
51112
}
52113
}
53114

54-
crate struct Edges<'s> {
55-
graph: &'s ConstraintGraph,
115+
crate struct Edges<'s, D: ConstraintGraphDirecton> {
116+
graph: &'s ConstraintGraph<D>,
56117
pointer: Option<ConstraintIndex>,
57118
}
58119

59-
impl<'s> Iterator for Edges<'s> {
120+
impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
60121
type Item = ConstraintIndex;
61122

62123
fn next(&mut self) -> Option<Self::Item> {
@@ -69,17 +130,20 @@ impl<'s> Iterator for Edges<'s> {
69130
}
70131
}
71132

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

77-
impl<'s> RegionGraph<'s> {
141+
impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
78142
/// Create a "dependency graph" where each region constraint `R1:
79143
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
80144
/// construct SCCs for region inference but also for error
81145
/// reporting.
82-
crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph) -> Self {
146+
crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph<D>) -> Self {
83147
Self {
84148
set,
85149
constraint_graph,
@@ -88,47 +152,47 @@ impl<'s> RegionGraph<'s> {
88152

89153
/// Given a region `R`, iterate over all regions `R1` such that
90154
/// there exists a constraint `R: R1`.
91-
crate fn sub_regions(&self, region_sup: RegionVid) -> Successors<'_> {
155+
crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> {
92156
Successors {
93157
set: self.set,
94158
edges: self.constraint_graph.outgoing_edges(region_sup),
95159
}
96160
}
97161
}
98162

99-
crate struct Successors<'s> {
163+
crate struct Successors<'s, D: ConstraintGraphDirecton> {
100164
set: &'s ConstraintSet,
101-
edges: Edges<'s>,
165+
edges: Edges<'s, D>,
102166
}
103167

104-
impl<'s> Iterator for Successors<'s> {
168+
impl<'s, D: ConstraintGraphDirecton> Iterator for Successors<'s, D> {
105169
type Item = RegionVid;
106170

107171
fn next(&mut self) -> Option<Self::Item> {
108-
self.edges.next().map(|c| self.set[c].sub)
172+
self.edges.next().map(|c| D::end_region(&self.set[c]))
109173
}
110174
}
111175

112-
impl<'s> graph::DirectedGraph for RegionGraph<'s> {
176+
impl<'s, D: ConstraintGraphDirecton> graph::DirectedGraph for RegionGraph<'s, D> {
113177
type Node = RegionVid;
114178
}
115179

116-
impl<'s> graph::WithNumNodes for RegionGraph<'s> {
180+
impl<'s, D: ConstraintGraphDirecton> graph::WithNumNodes for RegionGraph<'s, D> {
117181
fn num_nodes(&self) -> usize {
118182
self.constraint_graph.first_constraints.len()
119183
}
120184
}
121185

122-
impl<'s> graph::WithSuccessors for RegionGraph<'s> {
186+
impl<'s, D: ConstraintGraphDirecton> graph::WithSuccessors for RegionGraph<'s, D> {
123187
fn successors<'graph>(
124188
&'graph self,
125189
node: Self::Node,
126190
) -> <Self as graph::GraphSuccessors<'graph>>::Iter {
127-
self.sub_regions(node)
191+
self.outgoing_regions(node)
128192
}
129193
}
130194

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

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

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

39-
/// Constructs a graph from the constraint set; the graph makes it
40-
/// easy to find the constraints affecting a particular region
41-
/// (you should not mutate the set once this graph is
42-
/// constructed).
43-
crate fn graph(&self, num_region_vars: usize) -> graph::ConstraintGraph {
44-
graph::ConstraintGraph::new(self, num_region_vars)
39+
/// Constructs a "normal" graph from the constraint set; the graph makes it
40+
/// easy to find the constraints affecting a particular region.
41+
///
42+
/// NB: This graph contains a "frozen" view of the current
43+
/// constraints. any new constraints added to the `ConstraintSet`
44+
/// after the graph is built will not be present in the graph.
45+
crate fn graph(&self, num_region_vars: usize) -> graph::NormalConstraintGraph {
46+
graph::ConstraintGraph::new(graph::Normal, self, num_region_vars)
47+
}
48+
49+
/// Like `graph`, but constraints a reverse graph where `R1: R2`
50+
/// represents an edge `R2 -> R1`.
51+
crate fn reverse_graph(&self, num_region_vars: usize) -> graph::ReverseConstraintGraph {
52+
graph::ConstraintGraph::new(graph::Reverse, self, num_region_vars)
4553
}
4654

4755
/// Compute cycles (SCCs) in the graph of regions. In particular,
4856
/// find all regions R1, R2 such that R1: R2 and R2: R1 and group
4957
/// them into an SCC, and find the relationships between SCCs.
5058
crate fn compute_sccs(
5159
&self,
52-
constraint_graph: &graph::ConstraintGraph,
60+
constraint_graph: &graph::NormalConstraintGraph,
5361
) -> Sccs<RegionVid, ConstraintSccIndex> {
54-
let region_graph = &graph::RegionGraph::new(self, constraint_graph);
62+
let region_graph = &constraint_graph.region_graph(self);
5563
Sccs::new(region_graph)
5664
}
5765
}

src/librustc_mir/borrow_check/nll/liveness_map.rs

-77
This file was deleted.

0 commit comments

Comments
 (0)