Skip to content

Commit

Permalink
[WIP] compute region values using SCCs not iterative flow
Browse files Browse the repository at this point in the history
This is marked as [WIP] because it contains a number of minor
refactorings that ought to be broken out.
  • Loading branch information
nikomatsakis committed Jul 2, 2018
1 parent cef59aa commit 03871f2
Show file tree
Hide file tree
Showing 8 changed files with 245 additions and 232 deletions.
4 changes: 2 additions & 2 deletions src/librustc_mir/borrow_check/nll/constraint_generation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -210,7 +210,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
for (region, location, cause) in liveness_set {
debug!("generate: {:#?} is live at {:#?}", region, location);
let region_vid = regioncx.to_region_vid(region);
regioncx.add_live_point(region_vid, *location, &cause);
regioncx.add_live_element(region_vid, *location, &cause);
}

if let Some(all_facts) = all_facts {
Expand Down Expand Up @@ -242,7 +242,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> {
.tcx
.for_each_free_region(&live_ty, |live_region| {
let vid = live_region.to_region_vid();
self.regioncx.add_live_point(vid, location, &cause);
self.regioncx.add_live_element(vid, location, &cause);
});
}
}
96 changes: 96 additions & 0 deletions src/librustc_mir/borrow_check/nll/constraints/full_graph.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use borrow_check::nll::constraints::{ConstraintIndex, ConstraintSet};
use rustc::ty::RegionVid;
use rustc_data_structures::graph;
use rustc_data_structures::indexed_vec::IndexVec;

/// An initial graph which contains a node for every constraint index.
/// This is basically just represented as a set of linked lists; for
/// each region R, there is a linked list of constraints that lead to
/// other regions. (The graph is always defined relative to some set.)
crate struct FullConstraintGraph<'s> {
set: &'s ConstraintSet,
first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
}

impl<'s> FullConstraintGraph<'s> {
/// Constraint a graph where each region constraint `R1: R2` is
/// treated as an edge `R2 -> R1`. This is useful for cheaply
/// finding dirty constraints.
crate fn new(set: &'s ConstraintSet, num_region_vars: usize) -> Self {
let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
let mut next_constraints = IndexVec::from_elem(None, &set.constraints);

for (idx, constraint) in set.constraints.iter_enumerated().rev() {
let mut head = &mut first_constraints[constraint.sup];
let mut next = &mut next_constraints[idx];
debug_assert!(next.is_none());
*next = *head;
*head = Some(idx);
}

Self { set, first_constraints, next_constraints }
}

crate fn sub_regions(
&self,
region_sup: RegionVid,
) -> Successors<'_> {
let first = self.first_constraints[region_sup];
Successors { graph: self, pointer: first }
}
}

crate struct Successors<'s> {
graph: &'s FullConstraintGraph<'s>,
pointer: Option<ConstraintIndex>,
}

impl<'s> Iterator for Successors<'s> {
type Item = RegionVid;

fn next(&mut self) -> Option<Self::Item> {
if let Some(p) = self.pointer {
let r = self.graph.set[p].sub;
self.pointer = self.graph.next_constraints[p];
Some(r)
} else {
None
}
}
}

impl<'s> graph::DirectedGraph for FullConstraintGraph<'s> {
type Node = RegionVid;
}

impl<'s> graph::WithNumNodes for FullConstraintGraph<'s> {
fn num_nodes(&self) -> usize {
self.first_constraints.len()
}
}

impl<'s> graph::WithSuccessors for FullConstraintGraph<'s> {
fn successors<'graph>(
&'graph self,
node: Self::Node,
) -> <Self as graph::GraphSuccessors<'graph>>::Iter {
self.sub_regions(node)
}
}

impl<'s, 'graph> graph::GraphSuccessors<'graph> for FullConstraintGraph<'s> {
type Item = RegionVid;
type Iter = Successors<'graph>;
}

57 changes: 13 additions & 44 deletions src/librustc_mir/borrow_check/nll/constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,22 @@
// except according to those terms.

use rustc::ty::RegionVid;
use rustc_data_structures::graph::scc::Sccs;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use borrow_check::nll::type_check::Locations;

use std::fmt;
use std::ops::Deref;

mod full_graph;

#[derive(Clone, Default)]
crate struct ConstraintSet {
constraints: IndexVec<ConstraintIndex, OutlivesConstraint>,
}

impl ConstraintSet {
pub fn push(&mut self, constraint: OutlivesConstraint) {
crate fn push(&mut self, constraint: OutlivesConstraint) {
debug!(
"ConstraintSet::push({:?}: {:?} @ {:?}",
constraint.sup, constraint.sub, constraint.locations
Expand All @@ -32,12 +35,19 @@ impl ConstraintSet {
}
self.constraints.push(constraint);
}

crate fn compute_sccs(&self, num_region_vars: usize) -> Sccs<RegionVid, ConstraintSccIndex> {
let graph = &full_graph::FullConstraintGraph::new(self, num_region_vars);
Sccs::new(graph)
}
}

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

fn deref(&self) -> &Self::Target { &self.constraints }
fn deref(&self) -> &Self::Target {
&self.constraints
}
}

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

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

crate struct ConstraintGraph {
first_constraints: IndexVec<RegionVid, Option<ConstraintIndex>>,
next_constraints: IndexVec<ConstraintIndex, Option<ConstraintIndex>>,
}

impl ConstraintGraph {
/// Constraint a graph where each region constraint `R1: R2` is
/// treated as an edge `R2 -> R1`. This is useful for cheaply
/// finding dirty constraints.
crate fn new(set: &ConstraintSet, num_region_vars: usize) -> Self {
let mut first_constraints = IndexVec::from_elem_n(None, num_region_vars);
let mut next_constraints = IndexVec::from_elem(None, &set.constraints);

for (idx, constraint) in set.constraints.iter_enumerated().rev() {
let mut head = &mut first_constraints[constraint.sub];
let mut next = &mut next_constraints[idx];
debug_assert!(next.is_none());
*next = *head;
*head = Some(idx);
}

ConstraintGraph { first_constraints, next_constraints }
}

/// Invokes `op` with the index of any constraints of the form
/// `region_sup: region_sub`. These are the constraints that must
/// be reprocessed when the value of `R1` changes. If you think of
/// each constraint `R1: R2` as an edge `R2 -> R1`, then this
/// gives the set of successors to R2.
crate fn for_each_dependent(
&self,
region_sub: RegionVid,
mut op: impl FnMut(ConstraintIndex),
) {
let mut p = self.first_constraints[region_sub];
while let Some(dep_idx) = p {
op(dep_idx);
p = self.next_constraints[dep_idx];
}
}
}

newtype_index!(ConstraintSccIndex { DEBUG_FORMAT = "ConstraintSccIndex({})" });
2 changes: 1 addition & 1 deletion src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> {

stack.push(self.start_point);
while let Some(p) = stack.pop() {
if !self.regioncx.region_contains_point(self.borrow.region, p) {
if !self.regioncx.region_contains(self.borrow.region, p) {
continue;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {

while changed {
changed = false;
for constraint in &*self.constraints {
for constraint in self.constraints.iter() {
if let Some(n) = result_set[constraint.sup] {
let m = n + 1;
if result_set[constraint.sub]
Expand Down
Loading

0 comments on commit 03871f2

Please sign in to comment.