@@ -36,6 +36,12 @@ impl From<InsnId> for usize {
3636 }
3737}
3838
39+ impl From < usize > for InsnId {
40+ fn from ( val : usize ) -> Self {
41+ InsnId ( val)
42+ }
43+ }
44+
3945impl std:: fmt:: Display for InsnId {
4046 fn fmt ( & self , f : & mut std:: fmt:: Formatter ) -> std:: fmt:: Result {
4147 write ! ( f, "v{}" , self . 0 )
@@ -2273,28 +2279,28 @@ impl<'a> FunctionGraphvizPrinter<'a> {
22732279/// in missing optimizations.
22742280#[ derive( Debug ) ]
22752281struct UnionFind < T : Copy + Into < usize > > {
2276- forwarded : Vec < Option < T > > ,
2282+ forwarded : Vec < T > ,
22772283}
22782284
2279- impl < T : Copy + Into < usize > + PartialEq > UnionFind < T > {
2285+ impl < T : Copy + Into < usize > + PartialEq + std :: convert :: From < usize > > UnionFind < T > {
22802286 fn new ( ) -> UnionFind < T > {
22812287 UnionFind { forwarded : vec ! [ ] }
22822288 }
22832289
22842290 /// Private. Return the internal representation of the forwarding pointer for a given element.
2285- fn at ( & self , idx : T ) -> Option < T > {
2286- self . forwarded . get ( idx. into ( ) ) . copied ( ) . flatten ( )
2291+ fn at ( & self , idx : T ) -> T {
2292+ self . forwarded . get ( idx. into ( ) ) . unwrap_or ( & idx ) . to_owned ( )
22872293 }
22882294
22892295 /// Private. Set the internal representation of the forwarding pointer for the given element
22902296 /// `idx`. Extend the internal vector if necessary.
22912297 fn set ( & mut self , idx : T , value : T ) {
22922298 if idx. into ( ) >= self . forwarded . len ( ) {
2293- self . forwarded . resize ( idx. into ( ) +1 , None ) ;
2294- }
2295- if idx != value {
2296- self . forwarded [ idx. into ( ) ] = Some ( value) ;
2299+ for i in self . forwarded . len ( ) ..=idx. into ( ) {
2300+ self . forwarded . push ( i. into ( ) ) ;
2301+ }
22972302 }
2303+ self . forwarded [ idx. into ( ) ] = value;
22982304 }
22992305
23002306 /// Find the set representative for `insn`. Perform path compression at the same time to speed
@@ -2321,21 +2327,18 @@ impl<T: Copy + Into<usize> + PartialEq> UnionFind<T> {
23212327 fn find_const ( & self , insn : T ) -> T {
23222328 let mut result = insn;
23232329 loop {
2324- match self . at ( result) {
2325- None => return result,
2326- Some ( insn) => {
2327- assert ! ( result != insn, "cycle detected" ) ;
2328- result = insn;
2329- }
2330- }
2330+ let found = self . at ( result) ;
2331+ if found == result { return found; }
2332+ result = found;
23312333 }
23322334 }
23332335
23342336 /// Union the two sets containing `insn` and `target` such that every element in `insn`s set is
23352337 /// now part of `target`'s. Neither argument must be the representative in its set.
23362338 pub fn make_equal_to ( & mut self , insn : T , target : T ) {
2337- let found = self . find ( insn) ;
2338- self . set ( found, target) ;
2339+ let insn = self . find ( insn) ;
2340+ let target = self . find ( target) ;
2341+ self . set ( insn, target) ;
23392342 }
23402343}
23412344
@@ -8906,6 +8909,12 @@ mod union_find_tests {
89068909 assert_eq ! ( uf. find( 3usize ) , 4 ) ;
89078910 }
89088911
8912+ #[ test]
8913+ fn test_find_with_unknown_element_returns_self ( ) {
8914+ let mut uf = UnionFind :: new ( ) ;
8915+ assert_eq ! ( uf. find( 10usize ) , 10 ) ;
8916+ }
8917+
89098918 #[ test]
89108919 fn test_find_halts_with_identity_make_equal_to ( ) {
89118920 let mut uf = UnionFind :: < usize > :: new ( ) ;
@@ -8927,9 +8936,20 @@ mod union_find_tests {
89278936 let mut uf = UnionFind :: new ( ) ;
89288937 uf. make_equal_to ( 3 , 4 ) ;
89298938 uf. make_equal_to ( 4 , 5 ) ;
8930- assert_eq ! ( uf. at( 3usize ) , Some ( 4 ) ) ;
8939+ assert_eq ! ( uf. at( 3usize ) , 4 ) ;
89318940 assert_eq ! ( uf. find( 3usize ) , 5 ) ;
8932- assert_eq ! ( uf. at( 3usize ) , Some ( 5 ) ) ;
8941+ assert_eq ! ( uf. at( 3usize ) , 5 ) ;
8942+ }
8943+
8944+ #[ test]
8945+ fn test_make_equal_to_does_not_create_cycles ( ) {
8946+ let mut uf = UnionFind :: new ( ) ;
8947+ uf. make_equal_to ( 3 , 4 ) ;
8948+ uf. make_equal_to ( 4 , 5 ) ;
8949+ uf. make_equal_to ( 5 , 3 ) ;
8950+ assert_eq ! ( uf. find( 3usize ) , 5 ) ;
8951+ assert_eq ! ( uf. find( 4usize ) , 5 ) ;
8952+ assert_eq ! ( uf. find( 5usize ) , 5 ) ;
89338953 }
89348954}
89358955
0 commit comments