pub struct TransitiveRelation<T> { /* private fields */ }
Implementations§
source§impl<T: Eq + Hash + Copy> TransitiveRelation<T>
impl<T: Eq + Hash + Copy> TransitiveRelation<T>
sourcepub fn maybe_map<F, U>(&self, f: F) -> Option<TransitiveRelation<U>>
pub fn maybe_map<F, U>(&self, f: F) -> Option<TransitiveRelation<U>>
Applies the (partial) function to each edge and returns a new relation including transitive closures.
sourcepub fn reachable_from(&self, a: T) -> Vec<T>
pub fn reachable_from(&self, a: T) -> Vec<T>
Thinking of x R y
as an edge x -> y
in a graph, this
returns all things reachable from a
.
Really this probably ought to be impl Iterator<Item = &T>
, but
I’m too lazy to make that work, and – given the caching
strategy – it’d be a touch tricky anyhow.
sourcepub fn postdom_upper_bound(&self, a: T, b: T) -> Option<T>
pub fn postdom_upper_bound(&self, a: T, b: T) -> Option<T>
Picks what I am referring to as the “postdominating”
upper-bound for a
and b
. This is usually the least upper
bound, but in cases where there is no single least upper
bound, it is the “mutual immediate postdominator”, if you
imagine a graph where a < b
means a -> b
.
This function is needed because region inference currently requires that we produce a single “UB”, and there is no best choice for the LUB. Rather than pick arbitrarily, I pick a less good, but predictable choice. This should help ensure that region inference yields predictable results (though it itself is not fully sufficient).
Examples are probably clearer than any prose I could write
(there are corresponding tests below, btw). In each case,
the query is postdom_upper_bound(a, b)
:
// Returns Some(x), which is also LUB.
a -> a1 -> x
^
|
b -> b1 ---+
// Returns `Some(x)`, which is not LUB (there is none)
// diagonal edges run left-to-right.
a -> a1 -> x
\/ ^
/\ |
b -> b1 ---+
// Returns `None`.
a -> a1
b -> b1
sourcepub fn mutual_immediate_postdominator(&self, mubs: Vec<T>) -> Option<T>
pub fn mutual_immediate_postdominator(&self, mubs: Vec<T>) -> Option<T>
Viewing the relation as a graph, computes the “mutual
immediate postdominator” of a set of points (if one
exists). See postdom_upper_bound
for details.
sourcepub fn minimal_upper_bounds(&self, a: T, b: T) -> Vec<T>
pub fn minimal_upper_bounds(&self, a: T, b: T) -> Vec<T>
Returns the set of bounds X
such that:
a < X
andb < X
- there is no
Y != X
such thata < Y
andY < X
- except for the case where
X < a
(i.e., a strongly connected component in the graph). In that case, the smallest representative of the SCC is returned (as determined by the internal indices).
- except for the case where
Note that this set can, in principle, have any size.
sourcepub fn parents(&self, a: T) -> Vec<T>
pub fn parents(&self, a: T) -> Vec<T>
Given an element A, returns the maximal set {B} of elements B such that
- A != B
- A R B is true
- for each i, j:
B[i]
RB[j]
does not hold
The intuition is that this moves “one step up” through a lattice
(where the relation is encoding the <=
relation for the lattice).
So e.g., if the relation is ->
and we have
a -> b -> d -> f
| ^
+--> c -> e ---+
then parents(a)
returns [b, c]
. The postdom_parent
function
would further reduce this to just f
.
sourcepub fn base_edges(&self) -> impl Iterator<Item = (T, T)> + '_
pub fn base_edges(&self) -> impl Iterator<Item = (T, T)> + '_
Lists all the base edges in the graph: the initial non-transitive set of element relations, which will be later used as the basis for the transitive closure computation.