parent
db01b6789d
commit
4e706f56bd
5 changed files with 71 additions and 13 deletions
|
|
@ -8,6 +8,7 @@
|
|||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
use borrow_check::nll::type_check::Locations;
|
||||
use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet, OutlivesConstraint};
|
||||
use rustc::ty::RegionVid;
|
||||
use rustc_data_structures::graph;
|
||||
|
|
@ -31,6 +32,7 @@ crate type ReverseConstraintGraph = ConstraintGraph<Reverse>;
|
|||
crate trait ConstraintGraphDirecton: Copy + 'static {
|
||||
fn start_region(c: &OutlivesConstraint) -> RegionVid;
|
||||
fn end_region(c: &OutlivesConstraint) -> RegionVid;
|
||||
fn is_normal() -> bool;
|
||||
}
|
||||
|
||||
/// In normal mode, a `R1: R2` constraint results in an edge `R1 ->
|
||||
|
|
@ -48,6 +50,10 @@ impl ConstraintGraphDirecton for Normal {
|
|||
fn end_region(c: &OutlivesConstraint) -> RegionVid {
|
||||
c.sub
|
||||
}
|
||||
|
||||
fn is_normal() -> bool {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/// In reverse mode, a `R1: R2` constraint results in an edge `R2 ->
|
||||
|
|
@ -65,6 +71,10 @@ impl ConstraintGraphDirecton for Reverse {
|
|||
fn end_region(c: &OutlivesConstraint) -> RegionVid {
|
||||
c.sup
|
||||
}
|
||||
|
||||
fn is_normal() -> bool {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
|
||||
|
|
@ -98,8 +108,12 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
|
|||
/// Given the constraint set from which this graph was built
|
||||
/// creates a region graph so that you can iterate over *regions*
|
||||
/// and not constraints.
|
||||
crate fn region_graph<'rg>(&'rg self, set: &'rg ConstraintSet) -> RegionGraph<'rg, D> {
|
||||
RegionGraph::new(set, self)
|
||||
crate fn region_graph<'rg>(
|
||||
&'rg self,
|
||||
set: &'rg ConstraintSet,
|
||||
static_region: RegionVid,
|
||||
) -> RegionGraph<'rg, D> {
|
||||
RegionGraph::new(set, self, static_region)
|
||||
}
|
||||
|
||||
/// Given a region `R`, iterate over all constraints `R: R1`.
|
||||
|
|
@ -107,12 +121,28 @@ impl<D: ConstraintGraphDirecton> ConstraintGraph<D> {
|
|||
&'a self,
|
||||
region_sup: RegionVid,
|
||||
constraints: &'a ConstraintSet,
|
||||
static_region: RegionVid,
|
||||
) -> Edges<'a, D> {
|
||||
let first = self.first_constraints[region_sup];
|
||||
Edges {
|
||||
graph: self,
|
||||
constraints,
|
||||
pointer: first,
|
||||
//if this is the `'static` region and the graph's direction is normal,
|
||||
//then setup the Edges iterator to return all regions #53178
|
||||
if region_sup == static_region && D::is_normal() {
|
||||
Edges {
|
||||
graph: self,
|
||||
constraints,
|
||||
pointer: None,
|
||||
next_static_idx: Some(0),
|
||||
static_region,
|
||||
}
|
||||
} else {
|
||||
//otherwise, just setup the iterator as normal
|
||||
let first = self.first_constraints[region_sup];
|
||||
Edges {
|
||||
graph: self,
|
||||
constraints,
|
||||
pointer: first,
|
||||
next_static_idx: None,
|
||||
static_region,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -121,6 +151,8 @@ crate struct Edges<'s, D: ConstraintGraphDirecton> {
|
|||
graph: &'s ConstraintGraph<D>,
|
||||
constraints: &'s ConstraintSet,
|
||||
pointer: Option<ConstraintIndex>,
|
||||
next_static_idx: Option<usize>,
|
||||
static_region: RegionVid,
|
||||
}
|
||||
|
||||
impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
|
||||
|
|
@ -129,7 +161,21 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
|
|||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(p) = self.pointer {
|
||||
self.pointer = self.graph.next_constraints[p];
|
||||
|
||||
Some(self.constraints[p])
|
||||
} else if let Some(next_static_idx) = self.next_static_idx {
|
||||
self.next_static_idx =
|
||||
if next_static_idx == (self.graph.first_constraints.len() - 1) {
|
||||
None
|
||||
} else {
|
||||
Some(next_static_idx + 1)
|
||||
};
|
||||
|
||||
Some(OutlivesConstraint {
|
||||
sup: self.static_region,
|
||||
sub: next_static_idx.into(),
|
||||
locations: Locations::All,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
@ -142,6 +188,7 @@ impl<'s, D: ConstraintGraphDirecton> Iterator for Edges<'s, D> {
|
|||
crate struct RegionGraph<'s, D: ConstraintGraphDirecton> {
|
||||
set: &'s ConstraintSet,
|
||||
constraint_graph: &'s ConstraintGraph<D>,
|
||||
static_region: RegionVid,
|
||||
}
|
||||
|
||||
impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
|
||||
|
|
@ -149,10 +196,15 @@ impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
|
|||
/// R2` is treated as an edge `R1 -> R2`. We use this graph to
|
||||
/// construct SCCs for region inference but also for error
|
||||
/// reporting.
|
||||
crate fn new(set: &'s ConstraintSet, constraint_graph: &'s ConstraintGraph<D>) -> Self {
|
||||
crate fn new(
|
||||
set: &'s ConstraintSet,
|
||||
constraint_graph: &'s ConstraintGraph<D>,
|
||||
static_region: RegionVid,
|
||||
) -> Self {
|
||||
Self {
|
||||
set,
|
||||
constraint_graph,
|
||||
static_region,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -160,7 +212,7 @@ impl<'s, D: ConstraintGraphDirecton> RegionGraph<'s, D> {
|
|||
/// there exists a constraint `R: R1`.
|
||||
crate fn outgoing_regions(&self, region_sup: RegionVid) -> Successors<'_, D> {
|
||||
Successors {
|
||||
edges: self.constraint_graph.outgoing_edges(region_sup, self.set),
|
||||
edges: self.constraint_graph.outgoing_edges(region_sup, self.set, self.static_region),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,8 +58,9 @@ impl ConstraintSet {
|
|||
crate fn compute_sccs(
|
||||
&self,
|
||||
constraint_graph: &graph::NormalConstraintGraph,
|
||||
static_region: RegionVid,
|
||||
) -> Sccs<RegionVid, ConstraintSccIndex> {
|
||||
let region_graph = &constraint_graph.region_graph(self);
|
||||
let region_graph = &constraint_graph.region_graph(self, static_region);
|
||||
Sccs::new(region_graph)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -201,7 +201,10 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
// Otherwise, walk over the outgoing constraints and
|
||||
// enqueue any regions we find, keeping track of how we
|
||||
// reached them.
|
||||
for constraint in self.constraint_graph.outgoing_edges(r, &self.constraints) {
|
||||
let fr_static = self.universal_regions.fr_static;
|
||||
for constraint in self.constraint_graph.outgoing_edges(r,
|
||||
&self.constraints,
|
||||
fr_static) {
|
||||
assert_eq!(constraint.sup, r);
|
||||
let sub_region = constraint.sub;
|
||||
if let Trace::NotVisited = context[sub_region] {
|
||||
|
|
|
|||
|
|
@ -234,7 +234,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
|||
|
||||
let constraints = Rc::new(outlives_constraints); // freeze constraints
|
||||
let constraint_graph = Rc::new(constraints.graph(definitions.len()));
|
||||
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph));
|
||||
let fr_static = universal_regions.fr_static;
|
||||
let constraint_sccs = Rc::new(constraints.compute_sccs(&constraint_graph, fr_static));
|
||||
|
||||
let mut scc_values = RegionValues::new(elements, universal_regions.len(), max_universe);
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ fn regions_that_outlive_free_regions(
|
|||
// reachable from each free region, we will have all the
|
||||
// regions that are forced to outlive some free region.
|
||||
let rev_constraint_graph = constraint_set.reverse_graph(num_region_vars);
|
||||
let rev_region_graph = rev_constraint_graph.region_graph(constraint_set);
|
||||
let fr_static = universal_regions.fr_static;
|
||||
let rev_region_graph = rev_constraint_graph.region_graph(constraint_set, fr_static);
|
||||
|
||||
// Stack for the depth-first search. Start out with all the free regions.
|
||||
let mut stack: Vec<_> = universal_regions.universal_regions().collect();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue