]> git.lizzy.rs Git - rust.git/blob - src/librustc_data_structures/transitive_relation.rs
Auto merge of #65838 - estebank:resilient-recovery, r=Centril
[rust.git] / src / librustc_data_structures / transitive_relation.rs
1 use rustc_index::bit_set::BitMatrix;
2 use crate::fx::FxHashMap;
3 use crate::stable_hasher::{HashStable, StableHasher};
4 use crate::sync::Lock;
5 use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
6 use std::fmt::Debug;
7 use std::hash::Hash;
8 use std::mem;
9
10 #[cfg(test)]
11 mod tests;
12
13 #[derive(Clone, Debug)]
14 pub struct TransitiveRelation<T: Eq + Hash> {
15     // List of elements. This is used to map from a T to a usize.
16     elements: Vec<T>,
17
18     // Maps each element to an index.
19     map: FxHashMap<T, Index>,
20
21     // List of base edges in the graph. Require to compute transitive
22     // closure.
23     edges: Vec<Edge>,
24
25     // This is a cached transitive closure derived from the edges.
26     // Currently, we build it lazilly and just throw out any existing
27     // copy whenever a new edge is added. (The Lock is to permit
28     // the lazy computation.) This is kind of silly, except for the
29     // fact its size is tied to `self.elements.len()`, so I wanted to
30     // wait before building it up to avoid reallocating as new edges
31     // are added with new elements. Perhaps better would be to ask the
32     // user for a batch of edges to minimize this effect, but I
33     // already wrote the code this way. :P -nmatsakis
34     closure: Lock<Option<BitMatrix<usize, usize>>>,
35 }
36
37 // HACK(eddyb) manual impl avoids `Default` bound on `T`.
38 impl<T: Eq + Hash> Default for TransitiveRelation<T> {
39     fn default() -> Self {
40         TransitiveRelation {
41             elements: Default::default(),
42             map: Default::default(),
43             edges: Default::default(),
44             closure: Default::default(),
45         }
46     }
47 }
48
49 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, RustcEncodable, RustcDecodable, Debug)]
50 struct Index(usize);
51
52 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Debug)]
53 struct Edge {
54     source: Index,
55     target: Index,
56 }
57
58 impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
59     pub fn is_empty(&self) -> bool {
60         self.edges.is_empty()
61     }
62
63     pub fn elements(&self) -> impl Iterator<Item=&T> {
64         self.elements.iter()
65     }
66
67     fn index(&self, a: &T) -> Option<Index> {
68         self.map.get(a).cloned()
69     }
70
71     fn add_index(&mut self, a: T) -> Index {
72         let &mut TransitiveRelation {
73             ref mut elements,
74             ref mut closure,
75             ref mut map,
76             ..
77         } = self;
78
79         *map.entry(a.clone())
80            .or_insert_with(|| {
81                elements.push(a);
82
83                // if we changed the dimensions, clear the cache
84                *closure.get_mut() = None;
85
86                Index(elements.len() - 1)
87            })
88     }
89
90     /// Applies the (partial) function to each edge and returns a new
91     /// relation. If `f` returns `None` for any end-point, returns
92     /// `None`.
93     pub fn maybe_map<F, U>(&self, mut f: F) -> Option<TransitiveRelation<U>>
94         where F: FnMut(&T) -> Option<U>,
95               U: Clone + Debug + Eq + Hash + Clone,
96     {
97         let mut result = TransitiveRelation::default();
98         for edge in &self.edges {
99             result.add(f(&self.elements[edge.source.0])?, f(&self.elements[edge.target.0])?);
100         }
101         Some(result)
102     }
103
104     /// Indicate that `a < b` (where `<` is this relation)
105     pub fn add(&mut self, a: T, b: T) {
106         let a = self.add_index(a);
107         let b = self.add_index(b);
108         let edge = Edge {
109             source: a,
110             target: b,
111         };
112         if !self.edges.contains(&edge) {
113             self.edges.push(edge);
114
115             // added an edge, clear the cache
116             *self.closure.get_mut() = None;
117         }
118     }
119
120     /// Checks whether `a < target` (transitively)
121     pub fn contains(&self, a: &T, b: &T) -> bool {
122         match (self.index(a), self.index(b)) {
123             (Some(a), Some(b)) => self.with_closure(|closure| closure.contains(a.0, b.0)),
124             (None, _) | (_, None) => false,
125         }
126     }
127
128     /// Thinking of `x R y` as an edge `x -> y` in a graph, this
129     /// returns all things reachable from `a`.
130     ///
131     /// Really this probably ought to be `impl Iterator<Item = &T>`, but
132     /// I'm too lazy to make that work, and -- given the caching
133     /// strategy -- it'd be a touch tricky anyhow.
134     pub fn reachable_from(&self, a: &T) -> Vec<&T> {
135         match self.index(a) {
136             Some(a) => self.with_closure(|closure| {
137                 closure.iter(a.0).map(|i| &self.elements[i]).collect()
138             }),
139             None => vec![],
140         }
141     }
142
143     /// Picks what I am referring to as the "postdominating"
144     /// upper-bound for `a` and `b`. This is usually the least upper
145     /// bound, but in cases where there is no single least upper
146     /// bound, it is the "mutual immediate postdominator", if you
147     /// imagine a graph where `a < b` means `a -> b`.
148     ///
149     /// This function is needed because region inference currently
150     /// requires that we produce a single "UB", and there is no best
151     /// choice for the LUB. Rather than pick arbitrarily, I pick a
152     /// less good, but predictable choice. This should help ensure
153     /// that region inference yields predictable results (though it
154     /// itself is not fully sufficient).
155     ///
156     /// Examples are probably clearer than any prose I could write
157     /// (there are corresponding tests below, btw). In each case,
158     /// the query is `postdom_upper_bound(a, b)`:
159     ///
160     /// ```text
161     /// // Returns Some(x), which is also LUB.
162     /// a -> a1 -> x
163     ///            ^
164     ///            |
165     /// b -> b1 ---+
166     ///
167     /// // Returns `Some(x)`, which is not LUB (there is none)
168     /// // diagonal edges run left-to-right.
169     /// a -> a1 -> x
170     ///   \/       ^
171     ///   /\       |
172     /// b -> b1 ---+
173     ///
174     /// // Returns `None`.
175     /// a -> a1
176     /// b -> b1
177     /// ```
178     pub fn postdom_upper_bound(&self, a: &T, b: &T) -> Option<&T> {
179         let mubs = self.minimal_upper_bounds(a, b);
180         self.mutual_immediate_postdominator(mubs)
181     }
182
183     /// Viewing the relation as a graph, computes the "mutual
184     /// immediate postdominator" of a set of points (if one
185     /// exists). See `postdom_upper_bound` for details.
186     pub fn mutual_immediate_postdominator<'a>(&'a self, mut mubs: Vec<&'a T>) -> Option<&'a T> {
187         loop {
188             match mubs.len() {
189                 0 => return None,
190                 1 => return Some(mubs[0]),
191                 _ => {
192                     let m = mubs.pop().unwrap();
193                     let n = mubs.pop().unwrap();
194                     mubs.extend(self.minimal_upper_bounds(n, m));
195                 }
196             }
197         }
198     }
199
200     /// Returns the set of bounds `X` such that:
201     ///
202     /// - `a < X` and `b < X`
203     /// - there is no `Y != X` such that `a < Y` and `Y < X`
204     ///   - except for the case where `X < a` (i.e., a strongly connected
205     ///     component in the graph). In that case, the smallest
206     ///     representative of the SCC is returned (as determined by the
207     ///     internal indices).
208     ///
209     /// Note that this set can, in principle, have any size.
210     pub fn minimal_upper_bounds(&self, a: &T, b: &T) -> Vec<&T> {
211         let (mut a, mut b) = match (self.index(a), self.index(b)) {
212             (Some(a), Some(b)) => (a, b),
213             (None, _) | (_, None) => {
214                 return vec![];
215             }
216         };
217
218         // in some cases, there are some arbitrary choices to be made;
219         // it doesn't really matter what we pick, as long as we pick
220         // the same thing consistently when queried, so ensure that
221         // (a, b) are in a consistent relative order
222         if a > b {
223             mem::swap(&mut a, &mut b);
224         }
225
226         let lub_indices = self.with_closure(|closure| {
227             // Easy case is when either a < b or b < a:
228             if closure.contains(a.0, b.0) {
229                 return vec![b.0];
230             }
231             if closure.contains(b.0, a.0) {
232                 return vec![a.0];
233             }
234
235             // Otherwise, the tricky part is that there may be some c
236             // where a < c and b < c. In fact, there may be many such
237             // values. So here is what we do:
238             //
239             // 1. Find the vector `[X | a < X && b < X]` of all values
240             //    `X` where `a < X` and `b < X`.  In terms of the
241             //    graph, this means all values reachable from both `a`
242             //    and `b`. Note that this vector is also a set, but we
243             //    use the term vector because the order matters
244             //    to the steps below.
245             //    - This vector contains upper bounds, but they are
246             //      not minimal upper bounds. So you may have e.g.
247             //      `[x, y, tcx, z]` where `x < tcx` and `y < tcx` and
248             //      `z < x` and `z < y`:
249             //
250             //           z --+---> x ----+----> tcx
251             //               |           |
252             //               |           |
253             //               +---> y ----+
254             //
255             //      In this case, we really want to return just `[z]`.
256             //      The following steps below achieve this by gradually
257             //      reducing the list.
258             // 2. Pare down the vector using `pare_down`. This will
259             //    remove elements from the vector that can be reached
260             //    by an earlier element.
261             //    - In the example above, this would convert `[x, y,
262             //      tcx, z]` to `[x, y, z]`. Note that `x` and `y` are
263             //      still in the vector; this is because while `z < x`
264             //      (and `z < y`) holds, `z` comes after them in the
265             //      vector.
266             // 3. Reverse the vector and repeat the pare down process.
267             //    - In the example above, we would reverse to
268             //      `[z, y, x]` and then pare down to `[z]`.
269             // 4. Reverse once more just so that we yield a vector in
270             //    increasing order of index. Not necessary, but why not.
271             //
272             // I believe this algorithm yields a minimal set. The
273             // argument is that, after step 2, we know that no element
274             // can reach its successors (in the vector, not the graph).
275             // After step 3, we know that no element can reach any of
276             // its predecesssors (because of step 2) nor successors
277             // (because we just called `pare_down`)
278             //
279             // This same algorithm is used in `parents` below.
280
281             let mut candidates = closure.intersect_rows(a.0, b.0); // (1)
282             pare_down(&mut candidates, closure); // (2)
283             candidates.reverse(); // (3a)
284             pare_down(&mut candidates, closure); // (3b)
285             candidates
286         });
287
288         lub_indices.into_iter()
289                    .rev() // (4)
290                    .map(|i| &self.elements[i])
291                    .collect()
292     }
293
294     /// Given an element A, returns the maximal set {B} of elements B
295     /// such that
296     ///
297     /// - A != B
298     /// - A R B is true
299     /// - for each i, j: B[i] R B[j] does not hold
300     ///
301     /// The intuition is that this moves "one step up" through a lattice
302     /// (where the relation is encoding the `<=` relation for the lattice).
303     /// So e.g., if the relation is `->` and we have
304     ///
305     /// ```
306     /// a -> b -> d -> f
307     /// |              ^
308     /// +--> c -> e ---+
309     /// ```
310     ///
311     /// then `parents(a)` returns `[b, c]`. The `postdom_parent` function
312     /// would further reduce this to just `f`.
313     pub fn parents(&self, a: &T) -> Vec<&T> {
314         let a = match self.index(a) {
315             Some(a) => a,
316             None => return vec![]
317         };
318
319         // Steal the algorithm for `minimal_upper_bounds` above, but
320         // with a slight tweak. In the case where `a R a`, we remove
321         // that from the set of candidates.
322         let ancestors = self.with_closure(|closure| {
323             let mut ancestors = closure.intersect_rows(a.0, a.0);
324
325             // Remove anything that can reach `a`. If this is a
326             // reflexive relation, this will include `a` itself.
327             ancestors.retain(|&e| !closure.contains(e, a.0));
328
329             pare_down(&mut ancestors, closure); // (2)
330             ancestors.reverse(); // (3a)
331             pare_down(&mut ancestors, closure); // (3b)
332             ancestors
333         });
334
335         ancestors.into_iter()
336                  .rev() // (4)
337                  .map(|i| &self.elements[i])
338                  .collect()
339     }
340
341     /// A "best" parent in some sense. See `parents` and
342     /// `postdom_upper_bound` for more details.
343     pub fn postdom_parent(&self, a: &T) -> Option<&T> {
344         self.mutual_immediate_postdominator(self.parents(a))
345     }
346
347     fn with_closure<OP, R>(&self, op: OP) -> R
348         where OP: FnOnce(&BitMatrix<usize, usize>) -> R
349     {
350         let mut closure_cell = self.closure.borrow_mut();
351         let mut closure = closure_cell.take();
352         if closure.is_none() {
353             closure = Some(self.compute_closure());
354         }
355         let result = op(closure.as_ref().unwrap());
356         *closure_cell = closure;
357         result
358     }
359
360     fn compute_closure(&self) -> BitMatrix<usize, usize> {
361         let mut matrix = BitMatrix::new(self.elements.len(),
362                                         self.elements.len());
363         let mut changed = true;
364         while changed {
365             changed = false;
366             for edge in &self.edges {
367                 // add an edge from S -> T
368                 changed |= matrix.insert(edge.source.0, edge.target.0);
369
370                 // add all outgoing edges from T into S
371                 changed |= matrix.union_rows(edge.target.0, edge.source.0);
372             }
373         }
374         matrix
375     }
376 }
377
378 /// Pare down is used as a step in the LUB computation. It edits the
379 /// candidates array in place by removing any element j for which
380 /// there exists an earlier element i<j such that i -> j. That is,
381 /// after you run `pare_down`, you know that for all elements that
382 /// remain in candidates, they cannot reach any of the elements that
383 /// come after them.
384 ///
385 /// Examples follow. Assume that a -> b -> c and x -> y -> z.
386 ///
387 /// - Input: `[a, b, x]`. Output: `[a, x]`.
388 /// - Input: `[b, a, x]`. Output: `[b, a, x]`.
389 /// - Input: `[a, x, b, y]`. Output: `[a, x]`.
390 fn pare_down(candidates: &mut Vec<usize>, closure: &BitMatrix<usize, usize>) {
391     let mut i = 0;
392     while i < candidates.len() {
393         let candidate_i = candidates[i];
394         i += 1;
395
396         let mut j = i;
397         let mut dead = 0;
398         while j < candidates.len() {
399             let candidate_j = candidates[j];
400             if closure.contains(candidate_i, candidate_j) {
401                 // If `i` can reach `j`, then we can remove `j`. So just
402                 // mark it as dead and move on; subsequent indices will be
403                 // shifted into its place.
404                 dead += 1;
405             } else {
406                 candidates[j - dead] = candidate_j;
407             }
408             j += 1;
409         }
410         candidates.truncate(j - dead);
411     }
412 }
413
414 impl<T> Encodable for TransitiveRelation<T>
415     where T: Clone + Encodable + Debug + Eq + Hash + Clone
416 {
417     fn encode<E: Encoder>(&self, s: &mut E) -> Result<(), E::Error> {
418         s.emit_struct("TransitiveRelation", 2, |s| {
419             s.emit_struct_field("elements", 0, |s| self.elements.encode(s))?;
420             s.emit_struct_field("edges", 1, |s| self.edges.encode(s))?;
421             Ok(())
422         })
423     }
424 }
425
426 impl<T> Decodable for TransitiveRelation<T>
427     where T: Clone + Decodable + Debug + Eq + Hash + Clone
428 {
429     fn decode<D: Decoder>(d: &mut D) -> Result<Self, D::Error> {
430         d.read_struct("TransitiveRelation", 2, |d| {
431             let elements: Vec<T> = d.read_struct_field("elements", 0, |d| Decodable::decode(d))?;
432             let edges = d.read_struct_field("edges", 1, |d| Decodable::decode(d))?;
433             let map = elements.iter()
434                               .enumerate()
435                               .map(|(index, elem)| (elem.clone(), Index(index)))
436                               .collect();
437             Ok(TransitiveRelation { elements, edges, map, closure: Lock::new(None) })
438         })
439     }
440 }
441
442 impl<CTX, T> HashStable<CTX> for TransitiveRelation<T>
443     where T: HashStable<CTX> + Eq + Debug + Clone + Hash
444 {
445     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
446         // We are assuming here that the relation graph has been built in a
447         // deterministic way and we can just hash it the way it is.
448         let TransitiveRelation {
449             ref elements,
450             ref edges,
451             // "map" is just a copy of elements vec
452             map: _,
453             // "closure" is just a copy of the data above
454             closure: _
455         } = *self;
456
457         elements.hash_stable(hcx, hasher);
458         edges.hash_stable(hcx, hasher);
459     }
460 }
461
462 impl<CTX> HashStable<CTX> for Edge {
463     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
464         let Edge {
465             ref source,
466             ref target,
467         } = *self;
468
469         source.hash_stable(hcx, hasher);
470         target.hash_stable(hcx, hasher);
471     }
472 }
473
474 impl<CTX> HashStable<CTX> for Index {
475     fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
476         let Index(idx) = *self;
477         idx.hash_stable(hcx, hasher);
478     }
479 }