@@ -267,7 +267,7 @@ type bounds<T:copy> = {lb: bound<T>, ub: bound<T>};
267
267
268
268
enum var_value < V : copy , T : copy > {
269
269
redirect( V ) ,
270
- root( T )
270
+ root( T , uint ) ,
271
271
}
272
272
273
273
type vals_and_bindings < V : copy , T : copy > = {
@@ -278,6 +278,7 @@ type vals_and_bindings<V:copy, T:copy> = {
278
278
enum node < V : copy , T : copy > = {
279
279
root: V ,
280
280
possible_types: T ,
281
+ rank: uint,
281
282
} ;
282
283
283
284
enum infer_ctxt = @{
@@ -475,7 +476,8 @@ impl<V:copy vid, T:copy to_str> of to_str for var_value<V,T> {
475
476
fn to_str ( cx : infer_ctxt ) -> str {
476
477
alt self {
477
478
redirect( vid) { #fmt ( "redirect(%s)" , vid. to_str ( ) ) }
478
- root ( pt) { #fmt ( "root(%s)" , pt. to_str ( cx) ) }
479
+ root ( pt, rk) { #fmt ( "root(%s, %s)" , pt. to_str ( cx) ,
480
+ uint:: to_str ( rk, 10 u) ) }
479
481
}
480
482
}
481
483
}
@@ -578,7 +580,7 @@ impl methods for infer_ctxt {
578
580
let id = * self . ty_var_counter ;
579
581
* self . ty_var_counter += 1 u;
580
582
self . tvb . vals . insert ( id,
581
- root ( { lb: none, ub: none} ) ) ;
583
+ root ( { lb: none, ub: none} , 0 u ) ) ;
582
584
ret tv_vid( id) ;
583
585
}
584
586
@@ -595,7 +597,7 @@ impl methods for infer_ctxt {
595
597
* self . ty_var_integral_counter += 1 u;
596
598
597
599
self . tvib . vals . insert ( id,
598
- root ( int_ty_set_all ( ) ) ) ;
600
+ root ( int_ty_set_all ( ) , 0 u ) ) ;
599
601
ret tvi_vid( id) ;
600
602
}
601
603
@@ -607,7 +609,7 @@ impl methods for infer_ctxt {
607
609
let id = * self . region_var_counter ;
608
610
* self . region_var_counter += 1 u;
609
611
self . rb . vals . insert ( id,
610
- root ( { lb: none, ub: none} ) ) ;
612
+ root ( { lb: none, ub: none} , 0 u ) ) ;
611
613
ret region_vid( id) ;
612
614
}
613
615
@@ -661,8 +663,8 @@ impl unify_methods for infer_ctxt {
661
663
}
662
664
nde
663
665
}
664
- root ( pt) {
665
- node ( { root: vid, possible_types: pt} )
666
+ root ( pt, rk ) {
667
+ node ( { root: vid, possible_types: pt, rank : rk } )
666
668
}
667
669
}
668
670
}
@@ -722,9 +724,10 @@ impl unify_methods for infer_ctxt {
722
724
// a.lb <: c.lb
723
725
// b.lb <: c.lb
724
726
// If this cannot be achieved, the result is failure.
727
+
725
728
fn set_var_to_merged_bounds<V : copy vid, T : copy to_str st> (
726
729
vb: vals_and_bindings<V , bounds<T >>,
727
- v_id: V , a: bounds<T >, b: bounds<T >) -> ures {
730
+ v_id: V , a: bounds<T >, b: bounds<T >, rank : uint ) -> ures {
728
731
729
732
// Think of the two diamonds, we want to find the
730
733
// intersection. There are basically four possibilities (you
@@ -765,7 +768,7 @@ impl unify_methods for infer_ctxt {
765
768
// the new bounds must themselves
766
769
// be relatable:
767
770
self . bnds( bnds. lb, bnds. ub) . then { ||
768
- self . set( vb, v_id, root( bnds) ) ;
771
+ self . set( vb, v_id, root( bnds, rank ) ) ;
769
772
uok( )
770
773
}
771
774
} } } } }
@@ -802,15 +805,42 @@ impl unify_methods for infer_ctxt {
802
805
_ { /*fallthrough*/ }
803
806
}
804
807
805
- // For max perf, we should consider the rank here. But for now,
806
- // we always make b redirect to a.
807
- self. set ( vb, b_id, redirect ( a_id) ) ;
808
-
809
808
// Otherwise, we need to merge A and B so as to guarantee that
810
809
// A remains a subtype of B. Actually, there are other options,
811
810
// but that's the route we choose to take.
812
- self . set_var_to_merged_bounds ( vb, a_id, a_bounds, b_bounds) . then { ||
813
- uok ( )
811
+
812
+ // Rank optimization
813
+
814
+ // Make the node with greater rank the parent of the node with
815
+ // smaller rank.
816
+ if nde_a. rank > nde_b. rank {
817
+ #debug[ "vars(): a has smaller rank" ] ;
818
+ // a has greater rank, so a should become b's parent,
819
+ // i.e., b should redirect to a.
820
+ self . set ( vb, b_id, redirect ( a_id) ) ;
821
+ self . set_var_to_merged_bounds (
822
+ vb, a_id, a_bounds, b_bounds, nde_a. rank ) . then { ||
823
+ uok ( )
824
+ }
825
+ } else if nde_a. rank < nde_b. rank {
826
+ #debug[ "vars(): b has smaller rank" ] ;
827
+ // b has geater rank, so a should redirect to b.
828
+ self . set ( vb, a_id, redirect ( b_id) ) ;
829
+ self . set_var_to_merged_bounds (
830
+ vb, b_id, a_bounds, b_bounds, nde_b. rank ) . then { ||
831
+ uok ( )
832
+ }
833
+ } else {
834
+ #debug[ "vars(): a and b have equal rank" ] ;
835
+ assert nde_a. rank == nde_b. rank ;
836
+ // If equal, just redirect one to the other and increment
837
+ // the other's rank. We choose arbitrarily to redirect b
838
+ // to a and increment a's rank.
839
+ self . set ( vb, b_id, redirect ( a_id) ) ;
840
+ self . set_var_to_merged_bounds (
841
+ vb, a_id, a_bounds, b_bounds, nde_a. rank + 1 u) . then { ||
842
+ uok ( )
843
+ }
814
844
}
815
845
}
816
846
@@ -835,8 +865,29 @@ impl unify_methods for infer_ctxt {
835
865
if * intersection == INT_TY_SET_EMPTY {
836
866
ret err ( ty:: terr_no_integral_type) ;
837
867
}
838
- self . set ( vb, a_id, root ( intersection) ) ;
839
- self . set ( vb, b_id, redirect ( a_id) ) ;
868
+
869
+ // Rank optimization
870
+ if nde_a. rank > nde_b. rank {
871
+ #debug[ "vars_integral(): a has smaller rank" ] ;
872
+ // a has greater rank, so a should become b's parent,
873
+ // i.e., b should redirect to a.
874
+ self . set ( vb, a_id, root ( intersection, nde_a. rank ) ) ;
875
+ self . set ( vb, b_id, redirect ( a_id) ) ;
876
+ } else if nde_a. rank < nde_b. rank {
877
+ #debug[ "vars_integral(): b has smaller rank" ] ;
878
+ // b has greater rank, so a should redirect to b.
879
+ self . set ( vb, b_id, root ( intersection, nde_b. rank ) ) ;
880
+ self . set ( vb, a_id, redirect ( b_id) ) ;
881
+ } else {
882
+ #debug[ "vars_integral(): a and b have equal rank" ] ;
883
+ assert nde_a. rank == nde_b. rank ;
884
+ // If equal, just redirect one to the other and increment
885
+ // the other's rank. We choose arbitrarily to redirect b
886
+ // to a and increment a's rank.
887
+ self . set ( vb, a_id, root ( intersection, nde_a. rank + 1 u) ) ;
888
+ self . set ( vb, b_id, redirect ( a_id) ) ;
889
+ } ;
890
+
840
891
uok ( )
841
892
}
842
893
@@ -852,7 +903,8 @@ impl unify_methods for infer_ctxt {
852
903
a_id. to_str ( ) , a_bounds. to_str ( self ) ,
853
904
b. to_str ( self ) ] ;
854
905
let b_bounds = { lb: none, ub: some ( b) } ;
855
- self . set_var_to_merged_bounds ( vb, a_id, a_bounds, b_bounds)
906
+ self . set_var_to_merged_bounds ( vb, a_id, a_bounds, b_bounds,
907
+ nde_a. rank )
856
908
}
857
909
858
910
fn vart_integral < V : copy vid> (
@@ -871,7 +923,7 @@ impl unify_methods for infer_ctxt {
871
923
if * intersection == INT_TY_SET_EMPTY {
872
924
ret err ( ty:: terr_no_integral_type) ;
873
925
}
874
- self . set ( vb, a_id, root ( intersection) ) ;
926
+ self . set ( vb, a_id, root ( intersection, nde_a . rank ) ) ;
875
927
uok ( )
876
928
}
877
929
@@ -887,7 +939,8 @@ impl unify_methods for infer_ctxt {
887
939
#debug[ "tvar(%s <: %s=%s)" ,
888
940
a. to_str ( self ) ,
889
941
b_id. to_str ( ) , b_bounds. to_str ( self ) ] ;
890
- self . set_var_to_merged_bounds ( vb, b_id, a_bounds, b_bounds)
942
+ self . set_var_to_merged_bounds ( vb, b_id, a_bounds, b_bounds,
943
+ nde_b. rank )
891
944
}
892
945
893
946
fn tvar_integral < V : copy vid> (
@@ -906,7 +959,7 @@ impl unify_methods for infer_ctxt {
906
959
if * intersection == INT_TY_SET_EMPTY {
907
960
ret err ( ty:: terr_no_integral_type) ;
908
961
}
909
- self . set ( vb, b_id, root ( intersection) ) ;
962
+ self . set ( vb, b_id, root ( intersection, nde_b . rank ) ) ;
910
963
uok ( )
911
964
}
912
965
@@ -1197,7 +1250,8 @@ impl methods for resolve_state {
1197
1250
self . infcx. set(
1198
1251
self . infcx. tvib, vid,
1199
1252
root( convert_integral_ty_to_int_ty_set( self . infcx. tcx,
1200
- ty) ) ) ;
1253
+ ty) ,
1254
+ nde. rank) ) ;
1201
1255
ty
1202
1256
}
1203
1257
force_none {
@@ -2564,7 +2618,8 @@ fn lattice_var_t<V:copy vid, T:copy to_str st, L:lattice_ops combine>(
2564
2618
#debug[ "bnd=none" ] ;
2565
2619
let a_bounds = self . with_bnd( a_bounds, b) ;
2566
2620
self . infcx( ) . bnds( a_bounds. lb, a_bounds. ub) . then { ||
2567
- self . infcx( ) . set( vb, a_id, root( a_bounds) ) ;
2621
+ self . infcx( ) . set( vb, a_id, root( a_bounds,
2622
+ nde_a. rank) ) ;
2568
2623
ok( b)
2569
2624
}
2570
2625
}
0 commit comments