split into two matrices
This commit is contained in:
parent
40498bae65
commit
3f0fb4f7d8
|
@ -43,12 +43,27 @@ impl<C: Idx> BitVector<C> {
|
||||||
self.data.iter().map(|e| e.count_ones() as usize).sum()
|
self.data.iter().map(|e| e.count_ones() as usize).sum()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if `self` contains the bit `bit`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn contains(&self, bit: C) -> bool {
|
pub fn contains(&self, bit: C) -> bool {
|
||||||
let (word, mask) = word_mask(bit);
|
let (word, mask) = word_mask(bit);
|
||||||
(self.data[word] & mask) != 0
|
(self.data[word] & mask) != 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// True if `self` contains all the bits in `other`.
|
||||||
|
///
|
||||||
|
/// The two vectors must have the same length.
|
||||||
|
#[inline]
|
||||||
|
pub fn contains_all(&self, other: &BitVector<C>) -> bool {
|
||||||
|
assert_eq!(self.data.len(), other.data.len());
|
||||||
|
self.data.iter().zip(&other.data).all(|(a, b)| (a & b) == *b)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn is_empty(&self) -> bool {
|
||||||
|
self.data.iter().all(|a| *a == 0)
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns true if the bit has changed.
|
/// Returns true if the bit has changed.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn insert(&mut self, bit: C) -> bool {
|
pub fn insert(&mut self, bit: C) -> bool {
|
||||||
|
@ -349,6 +364,10 @@ impl<R: Idx, C: Idx> SparseBitMatrix<R, C> {
|
||||||
self.vector.len()
|
self.vector.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn rows(&self) -> impl Iterator<Item = R> {
|
||||||
|
self.vector.indices()
|
||||||
|
}
|
||||||
|
|
||||||
/// Iterates through all the columns set to true in a given row of
|
/// Iterates through all the columns set to true in a given row of
|
||||||
/// the matrix.
|
/// the matrix.
|
||||||
pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
|
pub fn iter<'a>(&'a self, row: R) -> impl Iterator<Item = C> + 'a {
|
||||||
|
@ -522,3 +541,45 @@ fn matrix_iter() {
|
||||||
}
|
}
|
||||||
assert!(iter.next().is_none());
|
assert!(iter.next().is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn sparse_matrix_iter() {
|
||||||
|
let mut matrix = SparseBitMatrix::new(64, 100);
|
||||||
|
matrix.add(3, 22);
|
||||||
|
matrix.add(3, 75);
|
||||||
|
matrix.add(2, 99);
|
||||||
|
matrix.add(4, 0);
|
||||||
|
matrix.merge(3, 5);
|
||||||
|
|
||||||
|
let expected = [99];
|
||||||
|
let mut iter = expected.iter();
|
||||||
|
for i in matrix.iter(2) {
|
||||||
|
let j = *iter.next().unwrap();
|
||||||
|
assert_eq!(i, j);
|
||||||
|
}
|
||||||
|
assert!(iter.next().is_none());
|
||||||
|
|
||||||
|
let expected = [22, 75];
|
||||||
|
let mut iter = expected.iter();
|
||||||
|
for i in matrix.iter(3) {
|
||||||
|
let j = *iter.next().unwrap();
|
||||||
|
assert_eq!(i, j);
|
||||||
|
}
|
||||||
|
assert!(iter.next().is_none());
|
||||||
|
|
||||||
|
let expected = [0];
|
||||||
|
let mut iter = expected.iter();
|
||||||
|
for i in matrix.iter(4) {
|
||||||
|
let j = *iter.next().unwrap();
|
||||||
|
assert_eq!(i, j);
|
||||||
|
}
|
||||||
|
assert!(iter.next().is_none());
|
||||||
|
|
||||||
|
let expected = [22, 75];
|
||||||
|
let mut iter = expected.iter();
|
||||||
|
for i in matrix.iter(5) {
|
||||||
|
let j = *iter.next().unwrap();
|
||||||
|
assert_eq!(i, j);
|
||||||
|
}
|
||||||
|
assert!(iter.next().is_none());
|
||||||
|
}
|
||||||
|
|
|
@ -48,9 +48,6 @@ pub struct RegionInferenceContext<'tcx> {
|
||||||
/// from as well as its final inferred value.
|
/// from as well as its final inferred value.
|
||||||
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
definitions: IndexVec<RegionVid, RegionDefinition<'tcx>>,
|
||||||
|
|
||||||
/// Maps from points/universal-regions to a `RegionElementIndex`.
|
|
||||||
elements: Rc<RegionValueElements>,
|
|
||||||
|
|
||||||
/// The liveness constraints added to each region. For most
|
/// The liveness constraints added to each region. For most
|
||||||
/// regions, these start out empty and steadily grow, though for
|
/// regions, these start out empty and steadily grow, though for
|
||||||
/// each universally quantified region R they start out containing
|
/// each universally quantified region R they start out containing
|
||||||
|
@ -219,14 +216,13 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
|
|
||||||
let mut scc_values = RegionValues::new(elements);
|
let mut scc_values = RegionValues::new(elements);
|
||||||
|
|
||||||
for (region, location_set) in liveness_constraints.iter_enumerated() {
|
for region in liveness_constraints.regions_with_points() {
|
||||||
let scc = constraint_sccs.scc(region);
|
let scc = constraint_sccs.scc(region);
|
||||||
scc_values.merge_into(scc, location_set);
|
scc_values.merge_row(scc, region, &liveness_constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
definitions,
|
definitions,
|
||||||
elements: elements.clone(),
|
|
||||||
liveness_constraints,
|
liveness_constraints,
|
||||||
constraints,
|
constraints,
|
||||||
constraint_graph,
|
constraint_graph,
|
||||||
|
@ -273,7 +269,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// For each universally quantified region X:
|
// For each universally quantified region X:
|
||||||
let elements = self.elements.clone();
|
|
||||||
let universal_regions = self.universal_regions.clone();
|
let universal_regions = self.universal_regions.clone();
|
||||||
for variable in universal_regions.universal_regions() {
|
for variable in universal_regions.universal_regions() {
|
||||||
// These should be free-region variables.
|
// These should be free-region variables.
|
||||||
|
@ -283,9 +278,9 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add all nodes in the CFG to liveness constraints
|
// Add all nodes in the CFG to liveness constraints
|
||||||
for point_index in elements.all_point_indices() {
|
let variable_scc = self.constraint_sccs.scc(variable);
|
||||||
self.add_live_element(variable, point_index);
|
self.liveness_constraints.add_all_points(variable);
|
||||||
}
|
self.scc_values.add_all_points(variable_scc);
|
||||||
|
|
||||||
// Add `end(X)` into the set for X.
|
// Add `end(X)` into the set for X.
|
||||||
self.add_live_element(variable, variable);
|
self.add_live_element(variable, variable);
|
||||||
|
@ -782,7 +777,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
|
||||||
// now). Therefore, the sup-region outlives the sub-region if,
|
// now). Therefore, the sup-region outlives the sub-region if,
|
||||||
// for each universal region R1 in the sub-region, there
|
// for each universal region R1 in the sub-region, there
|
||||||
// exists some region R2 in the sup-region that outlives R1.
|
// exists some region R2 in the sup-region that outlives R1.
|
||||||
let universal_outlives = self.scc_values
|
let universal_outlives = self
|
||||||
|
.scc_values
|
||||||
.universal_regions_outlived_by(sub_region_scc)
|
.universal_regions_outlived_by(sub_region_scc)
|
||||||
.all(|r1| {
|
.all(|r1| {
|
||||||
self.scc_values
|
self.scc_values
|
||||||
|
|
|
@ -10,11 +10,12 @@
|
||||||
|
|
||||||
use rustc::mir::{BasicBlock, Location, Mir};
|
use rustc::mir::{BasicBlock, Location, Mir};
|
||||||
use rustc::ty::RegionVid;
|
use rustc::ty::RegionVid;
|
||||||
use rustc_data_structures::bitvec::{BitVector, SparseBitMatrix};
|
use rustc_data_structures::bitvec::SparseBitMatrix;
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
use rustc_data_structures::indexed_vec::IndexVec;
|
use rustc_data_structures::indexed_vec::IndexVec;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
use std::ops::Range;
|
||||||
|
|
||||||
/// Maps between the various kinds of elements of a region value to
|
/// Maps between the various kinds of elements of a region value to
|
||||||
/// the internal indices that w use.
|
/// the internal indices that w use.
|
||||||
|
@ -50,34 +51,29 @@ impl RegionValueElements {
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
statements_before_block,
|
statements_before_block,
|
||||||
num_universal_regions,
|
|
||||||
num_points,
|
num_points,
|
||||||
|
num_universal_regions,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Total number of element indices that exist.
|
fn point_from_location(&self, location: Location) -> PointIndex {
|
||||||
crate fn num_elements(&self) -> usize {
|
let Location {
|
||||||
self.num_points + self.num_universal_regions
|
block,
|
||||||
|
statement_index,
|
||||||
|
} = location;
|
||||||
|
let start_index = self.statements_before_block[block];
|
||||||
|
PointIndex::new(start_index + statement_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts an element of a region value into a `RegionElementIndex`.
|
/// Range coverting all point indices.
|
||||||
crate fn index<T: ToElementIndex>(&self, elem: T) -> RegionElementIndex {
|
fn all_points(&self) -> Range<PointIndex> {
|
||||||
elem.to_element_index(self)
|
PointIndex::new(0)..PointIndex::new(self.num_points)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over the `RegionElementIndex` for all points in the CFG.
|
/// Converts a particular `RegionElementIndex` to a location, if
|
||||||
crate fn all_point_indices<'a>(&'a self) -> impl Iterator<Item = RegionElementIndex> + 'a {
|
/// that is what it represents. Returns `None` otherwise.
|
||||||
(0..self.num_points).map(move |i| RegionElementIndex::new(i + self.num_universal_regions))
|
crate fn to_location(&self, i: PointIndex) -> Location {
|
||||||
}
|
let point_index = i.index();
|
||||||
|
|
||||||
/// Converts a particular `RegionElementIndex` to the `RegionElement` it represents.
|
|
||||||
crate fn to_element(&self, i: RegionElementIndex) -> RegionElement {
|
|
||||||
debug!("to_element(i={:?})", i);
|
|
||||||
|
|
||||||
if let Some(r) = self.to_universal_region(i) {
|
|
||||||
RegionElement::UniversalRegion(r)
|
|
||||||
} else {
|
|
||||||
let point_index = i.index() - self.num_universal_regions;
|
|
||||||
|
|
||||||
// Find the basic block. We have a vector with the
|
// Find the basic block. We have a vector with the
|
||||||
// starting index of the statement in each block. Imagine
|
// starting index of the statement in each block. Imagine
|
||||||
|
@ -104,36 +100,16 @@ impl RegionValueElements {
|
||||||
.last()
|
.last()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
RegionElement::Location(Location {
|
Location {
|
||||||
block,
|
block,
|
||||||
statement_index: point_index - first_index,
|
statement_index: point_index - first_index,
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Converts a particular `RegionElementIndex` to a universal
|
|
||||||
/// region, if that is what it represents. Returns `None`
|
|
||||||
/// otherwise.
|
|
||||||
crate fn to_universal_region(&self, i: RegionElementIndex) -> Option<RegionVid> {
|
|
||||||
if i.index() < self.num_universal_regions {
|
|
||||||
Some(RegionVid::new(i.index()))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A newtype for the integers that represent one of the possible
|
/// A single integer representing a `Location` in the MIR control-flow
|
||||||
/// elements in a region. These are the rows in the `SparseBitMatrix` that
|
/// graph. Constructed efficiently from `RegionValueElements`.
|
||||||
/// is used to store the values of all regions. They have the following
|
newtype_index!(PointIndex { DEBUG_FORMAT = "PointIndex({})" });
|
||||||
/// convention:
|
|
||||||
///
|
|
||||||
/// - The first N indices represent free regions (where N = universal_regions.len()).
|
|
||||||
/// - The remainder represent the points in the CFG (see `point_indices` map).
|
|
||||||
///
|
|
||||||
/// You can convert a `RegionElementIndex` into a `RegionElement`
|
|
||||||
/// using the `to_region_elem` method.
|
|
||||||
newtype_index!(RegionElementIndex { DEBUG_FORMAT = "RegionElementIndex({})" });
|
|
||||||
|
|
||||||
/// An individual element in a region value -- the value of a
|
/// An individual element in a region value -- the value of a
|
||||||
/// particular region variable consists of a set of these elements.
|
/// particular region variable consists of a set of these elements.
|
||||||
|
@ -142,36 +118,9 @@ crate enum RegionElement {
|
||||||
/// A point in the control-flow graph.
|
/// A point in the control-flow graph.
|
||||||
Location(Location),
|
Location(Location),
|
||||||
|
|
||||||
/// An in-scope, universally quantified region (e.g., a lifetime parameter).
|
/// A universally quantified region from the root universe (e.g.,
|
||||||
UniversalRegion(RegionVid),
|
/// a lifetime parameter).
|
||||||
}
|
RootUniversalRegion(RegionVid),
|
||||||
|
|
||||||
crate trait ToElementIndex: Debug + Copy {
|
|
||||||
fn to_element_index(self, elements: &RegionValueElements) -> RegionElementIndex;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToElementIndex for Location {
|
|
||||||
fn to_element_index(self, elements: &RegionValueElements) -> RegionElementIndex {
|
|
||||||
let Location {
|
|
||||||
block,
|
|
||||||
statement_index,
|
|
||||||
} = self;
|
|
||||||
let start_index = elements.statements_before_block[block];
|
|
||||||
RegionElementIndex::new(elements.num_universal_regions + start_index + statement_index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToElementIndex for RegionVid {
|
|
||||||
fn to_element_index(self, elements: &RegionValueElements) -> RegionElementIndex {
|
|
||||||
assert!(self.index() < elements.num_universal_regions);
|
|
||||||
RegionElementIndex::new(self.index())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToElementIndex for RegionElementIndex {
|
|
||||||
fn to_element_index(self, _elements: &RegionValueElements) -> RegionElementIndex {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Stores the values for a set of regions. These are stored in a
|
/// Stores the values for a set of regions. These are stored in a
|
||||||
|
@ -181,7 +130,8 @@ impl ToElementIndex for RegionElementIndex {
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
crate struct RegionValues<N: Idx> {
|
crate struct RegionValues<N: Idx> {
|
||||||
elements: Rc<RegionValueElements>,
|
elements: Rc<RegionValueElements>,
|
||||||
matrix: SparseBitMatrix<N, RegionElementIndex>,
|
points: SparseBitMatrix<N, PointIndex>,
|
||||||
|
free_regions: SparseBitMatrix<N, RegionVid>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<N: Idx> RegionValues<N> {
|
impl<N: Idx> RegionValues<N> {
|
||||||
|
@ -191,7 +141,8 @@ impl<N: Idx> RegionValues<N> {
|
||||||
crate fn new(elements: &Rc<RegionValueElements>) -> Self {
|
crate fn new(elements: &Rc<RegionValueElements>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
elements: elements.clone(),
|
elements: elements.clone(),
|
||||||
matrix: SparseBitMatrix::new(elements.num_elements()),
|
points: SparseBitMatrix::new(elements.num_points),
|
||||||
|
free_regions: SparseBitMatrix::new(elements.num_universal_regions),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,53 +153,83 @@ impl<N: Idx> RegionValues<N> {
|
||||||
r: N,
|
r: N,
|
||||||
elem: impl ToElementIndex,
|
elem: impl ToElementIndex,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
let i = self.elements.index(elem);
|
|
||||||
debug!("add(r={:?}, elem={:?})", r, elem);
|
debug!("add(r={:?}, elem={:?})", r, elem);
|
||||||
self.matrix.add(r, i)
|
elem.add_to_row(self, r)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds all the control-flow points to the values for `r`.
|
||||||
|
crate fn add_all_points(&mut self, r: N) {
|
||||||
|
// FIXME OMG so inefficient. We'll fix later.
|
||||||
|
for p in self.elements.all_points() {
|
||||||
|
self.points.add(r, p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
|
/// Add all elements in `r_from` to `r_to` (because e.g. `r_to:
|
||||||
/// r_from`).
|
/// r_from`).
|
||||||
crate fn add_region(&mut self, r_to: N, r_from: N) -> bool {
|
crate fn add_region(&mut self, r_to: N, r_from: N) -> bool {
|
||||||
self.matrix.merge(r_from, r_to)
|
self.points.merge(r_from, r_to) | self.free_regions.merge(r_from, r_to)
|
||||||
|
// FIXME universes?
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if the region `r` contains the given element.
|
/// True if the region `r` contains the given element.
|
||||||
crate fn contains(&self, r: N, elem: impl ToElementIndex) -> bool {
|
crate fn contains(
|
||||||
let i = self.elements.index(elem);
|
&self,
|
||||||
self.matrix.contains(r, i)
|
r: N,
|
||||||
|
elem: impl ToElementIndex,
|
||||||
|
) -> bool {
|
||||||
|
elem.contained_in_row(self, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates through each row and the accompanying bit set.
|
/// Iterate through each region that has a value in this set.
|
||||||
pub fn iter_enumerated<'a>(
|
crate fn regions_with_points<'a>(&'a self) -> impl Iterator<Item = N> {
|
||||||
&'a self
|
self.points.rows()
|
||||||
) -> impl Iterator<Item = (N, &'a BitVector<RegionElementIndex>)> + 'a {
|
|
||||||
self.matrix.iter_enumerated()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merge a row, `from`, originating in another `RegionValues` into the `into` row.
|
/// `self[to] |= values[from]`, essentially: that is, take all the
|
||||||
pub fn merge_into(&mut self, into: N, from: &BitVector<RegionElementIndex>) -> bool {
|
/// elements for the region `from` from `values` and add them to
|
||||||
self.matrix.merge_into(into, from)
|
/// the region `to` in `self`.
|
||||||
|
crate fn merge_row<M: Idx>(&mut self, to: N, from: M, values: &RegionValues<M>) {
|
||||||
|
if let Some(set) = values.points.row(from) {
|
||||||
|
self.points.merge_into(to, set);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(set) = values.free_regions.row(from) {
|
||||||
|
self.free_regions.merge_into(to, set);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// True if `sup_region` contains all the CFG points that
|
/// True if `sup_region` contains all the CFG points that
|
||||||
/// `sub_region` contains. Ignores universal regions.
|
/// `sub_region` contains. Ignores universal regions.
|
||||||
crate fn contains_points(&self, sup_region: N, sub_region: N) -> bool {
|
crate fn contains_points(
|
||||||
|
&self,
|
||||||
|
sup_region: N,
|
||||||
|
sub_region: N,
|
||||||
|
) -> bool {
|
||||||
// This could be done faster by comparing the bitsets. But I
|
// This could be done faster by comparing the bitsets. But I
|
||||||
// am lazy.
|
// am lazy.
|
||||||
self.element_indices_contained_in(sub_region)
|
if let Some(sub_row) = self.points.row(sub_region) {
|
||||||
.skip_while(|&i| self.elements.to_universal_region(i).is_some())
|
if let Some(sup_row) = self.points.row(sup_region) {
|
||||||
.all(|e| self.contains(sup_region, e))
|
sup_row.contains_all(sub_row)
|
||||||
|
} else {
|
||||||
|
// sup row is empty, so sub row must be empty
|
||||||
|
sub_row.is_empty()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// sub row is empty, always true
|
||||||
|
true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterate over the value of the region `r`, yielding up element
|
/// Returns the locations contained within a given region `r`.
|
||||||
/// indices. You may prefer `universal_regions_outlived_by` or
|
crate fn locations_outlived_by<'a>(
|
||||||
/// `elements_contained_in`.
|
|
||||||
crate fn element_indices_contained_in<'a>(
|
|
||||||
&'a self,
|
&'a self,
|
||||||
r: N,
|
r: N,
|
||||||
) -> impl Iterator<Item = RegionElementIndex> + 'a {
|
) -> impl Iterator<Item = Location> + 'a {
|
||||||
self.matrix.iter(r).map(move |i| i)
|
self.points
|
||||||
|
.row(r)
|
||||||
|
.into_iter()
|
||||||
|
.flat_map(move |set| set.iter().map(move |p| self.elements.to_location(p)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns just the universal regions that are contained in a given region's value.
|
/// Returns just the universal regions that are contained in a given region's value.
|
||||||
|
@ -256,10 +237,10 @@ impl<N: Idx> RegionValues<N> {
|
||||||
&'a self,
|
&'a self,
|
||||||
r: N,
|
r: N,
|
||||||
) -> impl Iterator<Item = RegionVid> + 'a {
|
) -> impl Iterator<Item = RegionVid> + 'a {
|
||||||
self.element_indices_contained_in(r)
|
self.free_regions
|
||||||
.map(move |i| self.elements.to_universal_region(i))
|
.row(r)
|
||||||
.take_while(move |v| v.is_some()) // universal regions are a prefix
|
.into_iter()
|
||||||
.map(move |v| v.unwrap())
|
.flat_map(|set| set.iter())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns all the elements contained in a given region's value.
|
/// Returns all the elements contained in a given region's value.
|
||||||
|
@ -267,8 +248,15 @@ impl<N: Idx> RegionValues<N> {
|
||||||
&'a self,
|
&'a self,
|
||||||
r: N,
|
r: N,
|
||||||
) -> impl Iterator<Item = RegionElement> + 'a {
|
) -> impl Iterator<Item = RegionElement> + 'a {
|
||||||
self.element_indices_contained_in(r)
|
let points_iter = self
|
||||||
.map(move |r| self.elements.to_element(r))
|
.locations_outlived_by(r)
|
||||||
|
.map(RegionElement::Location);
|
||||||
|
|
||||||
|
let free_regions_iter = self
|
||||||
|
.universal_regions_outlived_by(r)
|
||||||
|
.map(RegionElement::RootUniversalRegion);
|
||||||
|
|
||||||
|
points_iter.chain(free_regions_iter)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a "pretty" string value of the region. Meant for debugging.
|
/// Returns a "pretty" string value of the region. Meant for debugging.
|
||||||
|
@ -306,7 +294,7 @@ impl<N: Idx> RegionValues<N> {
|
||||||
open_location = Some((l, l));
|
open_location = Some((l, l));
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionElement::UniversalRegion(fr) => {
|
RegionElement::RootUniversalRegion(fr) => {
|
||||||
if let Some((location1, location2)) = open_location {
|
if let Some((location1, location2)) = open_location {
|
||||||
push_sep(&mut result);
|
push_sep(&mut result);
|
||||||
Self::push_location_range(&mut result, location1, location2);
|
Self::push_location_range(&mut result, location1, location2);
|
||||||
|
@ -341,3 +329,55 @@ impl<N: Idx> RegionValues<N> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
crate trait ToElementIndex: Debug + Copy {
|
||||||
|
fn add_to_row<N: Idx>(
|
||||||
|
self,
|
||||||
|
values: &mut RegionValues<N>,
|
||||||
|
row: N,
|
||||||
|
) -> bool;
|
||||||
|
|
||||||
|
fn contained_in_row<N: Idx>(
|
||||||
|
self,
|
||||||
|
values: &RegionValues<N>,
|
||||||
|
row: N,
|
||||||
|
) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToElementIndex for Location {
|
||||||
|
fn add_to_row<N: Idx>(
|
||||||
|
self,
|
||||||
|
values: &mut RegionValues<N>,
|
||||||
|
row: N,
|
||||||
|
) -> bool {
|
||||||
|
let index = values.elements.point_from_location(self);
|
||||||
|
values.points.add(row, index)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contained_in_row<N: Idx>(
|
||||||
|
self,
|
||||||
|
values: &RegionValues<N>,
|
||||||
|
row: N,
|
||||||
|
) -> bool {
|
||||||
|
let index = values.elements.point_from_location(self);
|
||||||
|
values.points.contains(row, index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToElementIndex for RegionVid {
|
||||||
|
fn add_to_row<N: Idx>(
|
||||||
|
self,
|
||||||
|
values: &mut RegionValues<N>,
|
||||||
|
row: N,
|
||||||
|
) -> bool {
|
||||||
|
values.free_regions.add(row, self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn contained_in_row<N: Idx>(
|
||||||
|
self,
|
||||||
|
values: &RegionValues<N>,
|
||||||
|
row: N,
|
||||||
|
) -> bool {
|
||||||
|
values.free_regions.contains(row, self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(decl_macro)]
|
#![feature(decl_macro)]
|
||||||
#![feature(fs_read_write)]
|
#![feature(fs_read_write)]
|
||||||
|
#![feature(in_band_lifetimes)]
|
||||||
#![feature(macro_vis_matcher)]
|
#![feature(macro_vis_matcher)]
|
||||||
#![feature(exhaustive_patterns)]
|
#![feature(exhaustive_patterns)]
|
||||||
#![feature(range_contains)]
|
#![feature(range_contains)]
|
||||||
|
|
Loading…
Reference in New Issue