@@ -185,7 +185,14 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
185
185
/// b -> b1
186
186
/// ```
187
187
pub fn postdom_upper_bound ( & self , a : & T , b : & T ) -> Option < & T > {
188
- let mut mubs = self . minimal_upper_bounds ( a, b) ;
188
+ let mubs = self . minimal_upper_bounds ( a, b) ;
189
+ self . mutual_immediate_postdominator ( mubs)
190
+ }
191
+
192
+ /// Viewing the relation as a graph, computes the "mutual
193
+ /// immediate postdominator" of a set of points (if one
194
+ /// exists). See `postdom_upper_bound` for details.
195
+ pub fn mutual_immediate_postdominator < ' a > ( & ' a self , mut mubs : Vec < & ' a T > ) -> Option < & ' a T > {
189
196
loop {
190
197
match mubs. len ( ) {
191
198
0 => return None ,
@@ -277,6 +284,8 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
277
284
// After step 3, we know that no element can reach any of
278
285
// its predecesssors (because of step 2) nor successors
279
286
// (because we just called `pare_down`)
287
+ //
288
+ // This same algorithm is used in `parents` below.
280
289
281
290
let mut candidates = closure. intersection ( a. 0 , b. 0 ) ; // (1)
282
291
pare_down ( & mut candidates, closure) ; // (2)
@@ -291,6 +300,59 @@ impl<T: Clone + Debug + Eq + Hash + Clone> TransitiveRelation<T> {
291
300
. collect ( )
292
301
}
293
302
303
+ /// Given an element A, returns the maximal set {B} of elements B
304
+ /// such that
305
+ ///
306
+ /// - A != A
307
+ /// - A R B is true
308
+ /// - for each i, j: B[i] R B[j] does not hold
309
+ ///
310
+ /// The intuition is that this moves "one step up" through a lattice
311
+ /// (where the relation is encoding the `<=` relation for the lattice).
312
+ /// So e.g. if the relation is `->` and we have
313
+ ///
314
+ /// ```
315
+ /// a -> b -> d -> f
316
+ /// | ^
317
+ /// +--> c -> e ---+
318
+ /// ```
319
+ ///
320
+ /// then `parents(a)` returns `[b, c]`. The `postdom_parent` function
321
+ /// would further reduce this to just `f`.
322
+ pub fn parents ( & self , a : & T ) -> Vec < & T > {
323
+ let a = match self . index ( a) {
324
+ Some ( a) => a,
325
+ None => return vec ! [ ]
326
+ } ;
327
+
328
+ // Steal the algorithm for `minimal_upper_bounds` above, but
329
+ // with a slight tweak. In the case where `a R a`, we remove
330
+ // that from the set of candidates.
331
+ let ancestors = self . with_closure ( |closure| {
332
+ let mut ancestors = closure. intersection ( a. 0 , a. 0 ) ;
333
+
334
+ // Remove anything that can reach `a`. If this is a
335
+ // reflexive relation, this will include `a` itself.
336
+ ancestors. retain ( |& e| !closure. contains ( e, a. 0 ) ) ;
337
+
338
+ pare_down ( & mut ancestors, closure) ; // (2)
339
+ ancestors. reverse ( ) ; // (3a)
340
+ pare_down ( & mut ancestors, closure) ; // (3b)
341
+ ancestors
342
+ } ) ;
343
+
344
+ ancestors. into_iter ( )
345
+ . rev ( ) // (4)
346
+ . map ( |i| & self . elements [ i] )
347
+ . collect ( )
348
+ }
349
+
350
+ /// A "best" parent in some sense. See `parents` and
351
+ /// `postdom_upper_bound` for more details.
352
+ pub fn postdom_parent ( & self , a : & T ) -> Option < & T > {
353
+ self . mutual_immediate_postdominator ( self . parents ( a) )
354
+ }
355
+
294
356
fn with_closure < OP , R > ( & self , op : OP ) -> R
295
357
where OP : FnOnce ( & BitMatrix ) -> R
296
358
{
@@ -469,11 +531,17 @@ fn test_many_steps() {
469
531
}
470
532
471
533
#[ test]
472
- fn mubs_triange ( ) {
534
+ fn mubs_triangle ( ) {
535
+ // a -> tcx
536
+ // ^
537
+ // |
538
+ // b
473
539
let mut relation = TransitiveRelation :: new ( ) ;
474
540
relation. add ( "a" , "tcx" ) ;
475
541
relation. add ( "b" , "tcx" ) ;
476
542
assert_eq ! ( relation. minimal_upper_bounds( & "a" , & "b" ) , vec![ & "tcx" ] ) ;
543
+ assert_eq ! ( relation. parents( & "a" ) , vec![ & "tcx" ] ) ;
544
+ assert_eq ! ( relation. parents( & "b" ) , vec![ & "tcx" ] ) ;
477
545
}
478
546
479
547
#[ test]
@@ -499,6 +567,9 @@ fn mubs_best_choice1() {
499
567
relation. add ( "3" , "2" ) ;
500
568
501
569
assert_eq ! ( relation. minimal_upper_bounds( & "0" , & "3" ) , vec![ & "2" ] ) ;
570
+ assert_eq ! ( relation. parents( & "0" ) , vec![ & "2" ] ) ;
571
+ assert_eq ! ( relation. parents( & "2" ) , vec![ & "1" ] ) ;
572
+ assert ! ( relation. parents( & "1" ) . is_empty( ) ) ;
502
573
}
503
574
504
575
#[ test]
@@ -523,6 +594,9 @@ fn mubs_best_choice2() {
523
594
relation. add ( "3" , "2" ) ;
524
595
525
596
assert_eq ! ( relation. minimal_upper_bounds( & "0" , & "3" ) , vec![ & "1" ] ) ;
597
+ assert_eq ! ( relation. parents( & "0" ) , vec![ & "1" ] ) ;
598
+ assert_eq ! ( relation. parents( & "1" ) , vec![ & "2" ] ) ;
599
+ assert ! ( relation. parents( & "2" ) . is_empty( ) ) ;
526
600
}
527
601
528
602
#[ test]
@@ -537,10 +611,15 @@ fn mubs_no_best_choice() {
537
611
relation. add ( "3" , "2" ) ;
538
612
539
613
assert_eq ! ( relation. minimal_upper_bounds( & "0" , & "3" ) , vec![ & "1" , & "2" ] ) ;
614
+ assert_eq ! ( relation. parents( & "0" ) , vec![ & "1" , & "2" ] ) ;
615
+ assert_eq ! ( relation. parents( & "3" ) , vec![ & "1" , & "2" ] ) ;
540
616
}
541
617
542
618
#[ test]
543
619
fn mubs_best_choice_scc ( ) {
620
+ // in this case, 1 and 2 form a cycle; we pick arbitrarily (but
621
+ // consistently).
622
+
544
623
let mut relation = TransitiveRelation :: new ( ) ;
545
624
relation. add ( "0" , "1" ) ;
546
625
relation. add ( "0" , "2" ) ;
@@ -552,6 +631,7 @@ fn mubs_best_choice_scc() {
552
631
relation. add ( "3" , "2" ) ;
553
632
554
633
assert_eq ! ( relation. minimal_upper_bounds( & "0" , & "3" ) , vec![ & "1" ] ) ;
634
+ assert_eq ! ( relation. parents( & "0" ) , vec![ & "1" ] ) ;
555
635
}
556
636
557
637
#[ test]
@@ -573,6 +653,8 @@ fn pdub_crisscross() {
573
653
assert_eq ! ( relation. minimal_upper_bounds( & "a" , & "b" ) ,
574
654
vec![ & "a1" , & "b1" ] ) ;
575
655
assert_eq ! ( relation. postdom_upper_bound( & "a" , & "b" ) , Some ( & "x" ) ) ;
656
+ assert_eq ! ( relation. postdom_parent( & "a" ) , Some ( & "x" ) ) ;
657
+ assert_eq ! ( relation. postdom_parent( & "b" ) , Some ( & "x" ) ) ;
576
658
}
577
659
578
660
#[ test]
@@ -604,6 +686,9 @@ fn pdub_crisscross_more() {
604
686
assert_eq ! ( relation. minimal_upper_bounds( & "a1" , & "b1" ) ,
605
687
vec![ & "a2" , & "b2" ] ) ;
606
688
assert_eq ! ( relation. postdom_upper_bound( & "a" , & "b" ) , Some ( & "x" ) ) ;
689
+
690
+ assert_eq ! ( relation. postdom_parent( & "a" ) , Some ( & "x" ) ) ;
691
+ assert_eq ! ( relation. postdom_parent( & "b" ) , Some ( & "x" ) ) ;
607
692
}
608
693
609
694
#[ test]
@@ -621,6 +706,11 @@ fn pdub_lub() {
621
706
622
707
assert_eq ! ( relation. minimal_upper_bounds( & "a" , & "b" ) , vec![ & "x" ] ) ;
623
708
assert_eq ! ( relation. postdom_upper_bound( & "a" , & "b" ) , Some ( & "x" ) ) ;
709
+
710
+ assert_eq ! ( relation. postdom_parent( & "a" ) , Some ( & "a1" ) ) ;
711
+ assert_eq ! ( relation. postdom_parent( & "b" ) , Some ( & "b1" ) ) ;
712
+ assert_eq ! ( relation. postdom_parent( & "a1" ) , Some ( & "x" ) ) ;
713
+ assert_eq ! ( relation. postdom_parent( & "b1" ) , Some ( & "x" ) ) ;
624
714
}
625
715
626
716
#[ test]
@@ -722,3 +812,39 @@ fn mubs_scc_4() {
722
812
723
813
assert_eq ! ( relation. minimal_upper_bounds( & "a" , & "b" ) , vec![ & "c" ] ) ;
724
814
}
815
+
816
+ #[ test]
817
+ fn parent ( ) {
818
+ // An example that was misbehaving in the compiler.
819
+ //
820
+ // 4 -> 1 -> 3
821
+ // \ | /
822
+ // \ v /
823
+ // 2 -> 0
824
+ //
825
+ // plus a bunch of self-loops
826
+ //
827
+ // Here `->` represents `<=` and `0` is `'static`.
828
+
829
+ let pairs = vec ! [
830
+ ( 2 , /*->*/ 0 ) ,
831
+ ( 2 , /*->*/ 2 ) ,
832
+ ( 0 , /*->*/ 0 ) ,
833
+ ( 0 , /*->*/ 0 ) ,
834
+ ( 1 , /*->*/ 0 ) ,
835
+ ( 1 , /*->*/ 1 ) ,
836
+ ( 3 , /*->*/ 0 ) ,
837
+ ( 3 , /*->*/ 3 ) ,
838
+ ( 4 , /*->*/ 0 ) ,
839
+ ( 4 , /*->*/ 1 ) ,
840
+ ( 1 , /*->*/ 3 ) ,
841
+ ] ;
842
+
843
+ let mut relation = TransitiveRelation :: new ( ) ;
844
+ for ( a, b) in pairs {
845
+ relation. add ( a, b) ;
846
+ }
847
+
848
+ let p = relation. postdom_parent ( & 3 ) ;
849
+ assert_eq ! ( p, Some ( & 0 ) ) ;
850
+ }
0 commit comments