@@ -25,10 +25,21 @@ enum var_value {
25
25
bounded( bounds )
26
26
}
27
27
28
+ type region_bound = option < ty:: region > ;
29
+
30
+ type region_bounds = { lb : region_bound , ub : region_bound } ;
31
+
32
+ enum region_value {
33
+ rv_redirect( uint ) ,
34
+ rv_bounded( region_bounds )
35
+ }
36
+
28
37
enum infer_ctxt = @{
29
38
tcx: ty:: ctxt,
30
39
vals: smallintmap <var_value >,
31
- mut bindings: [ ( uint, var_value) ]
40
+ mut bindings: [ ( uint, var_value) ] ,
41
+ region_vals: smallintmap<region_value>,
42
+ mut region_bindings: [ ( uint, region_value) ]
32
43
} ;
33
44
34
45
type ures = result:: result < ( ) , ty:: type_err > ;
@@ -37,7 +48,9 @@ type fres<T> = result::result<T,int>;
37
48
fn new_infer_ctxt ( tcx : ty:: ctxt ) -> infer_ctxt {
38
49
infer_ctxt ( @{ tcx: tcx,
39
50
vals: smallintmap:: mk ( ) ,
40
- mut bindings: [ ] } )
51
+ mut bindings: [ ] ,
52
+ region_vals: smallintmap:: mk ( ) ,
53
+ mut region_bindings: [ ] } )
41
54
}
42
55
43
56
fn mk_subty ( cx : infer_ctxt , a : ty:: t , b : ty:: t ) -> ures {
@@ -186,6 +199,28 @@ impl unify_methods for infer_ctxt {
186
199
}
187
200
}
188
201
202
+ // FIXME: See if we can't throw some polymorphism on this to make this
203
+ // less of a straight copy of the above.
204
+ fn get_region ( rid : uint ) -> { root : uint , bounds : region_bounds } {
205
+ alt self . region_vals . find ( rid) {
206
+ none {
207
+ let bnds = { lb : none, ub : none} ;
208
+ self . region_vals . insert ( rid, rv_bounded ( bnds) ) ;
209
+ { root: rid, bounds: bnds}
210
+ }
211
+ some ( rv_redirect ( rid) ) {
212
+ let { root, bounds} = self . get_region ( rid) ;
213
+ if root != rid {
214
+ self . region_vals . insert ( rid, rv_redirect ( root) ) ;
215
+ }
216
+ { root: root, bounds: bounds}
217
+ }
218
+ some ( rv_bounded ( bounds) ) {
219
+ { root: rid, bounds: bounds}
220
+ }
221
+ }
222
+ }
223
+
189
224
// Combines the two bounds. Returns a bounds r where (r.lb <:
190
225
// a,b) and (a,b <: r.ub) (if such a bounds exists).
191
226
fn merge_bnds ( a : bound , b : bound ) -> result < bounds , ty:: type_err > {
@@ -603,7 +638,7 @@ impl resolve_methods for infer_ctxt {
603
638
result:: ok ( t)
604
639
}
605
640
606
- fn rerr ( v : int ) -> fres < ty :: t > {
641
+ fn rerr < T > ( v : int ) -> fres < T > {
607
642
#debug[ "Resolve error: %?" , v] ;
608
643
result:: err ( v)
609
644
}
@@ -628,6 +663,14 @@ impl resolve_methods for infer_ctxt {
628
663
fn resolve_ty ( typ : ty:: t ) -> fres < ty:: t > {
629
664
alt ty:: get ( typ) . struct {
630
665
ty:: ty_var ( vid) { self . resolve_var ( vid) }
666
+ ty:: ty_rptr ( ty:: re_var ( rid) , base_ty) {
667
+ alt self . resolve_region ( rid as int ) {
668
+ result:: err ( terr) { result:: err ( terr) }
669
+ result:: ok ( region) {
670
+ self . rok ( ty:: mk_rptr ( self . tcx , region, base_ty) )
671
+ }
672
+ }
673
+ }
631
674
_ { self. rok ( typ) }
632
675
}
633
676
}
@@ -682,4 +725,61 @@ impl resolve_methods for infer_ctxt {
682
725
some ( var_id) { ret self . rerr ( var_id) ; }
683
726
}
684
727
}
728
+
729
+ // FIXME: These should be integrated with the two functions above instead
730
+ // of being such blatant lazy duplicates.
731
+
732
+ fn resolve_region ( rid : int ) -> fres < ty:: region > {
733
+ let { root: _ , bounds } = self . get_region ( rid as uint ) ;
734
+
735
+ // See comments in resolve_ty above re. nonobviousness.
736
+
737
+ alt bounds {
738
+ { ub : _, lb : some ( r) } |
739
+ { ub: some ( r) , lb: _ } |
740
+ { ub: _, lb: some ( r) } { result:: ok ( r) }
741
+ { ub: none, lb: none } { self . rerr ( rid) }
742
+ }
743
+ }
744
+
745
+ fn subst_regions ( unresolved : @mutable option < int > ,
746
+ regions_seen : std:: list:: list < int > ,
747
+ rid : int ) -> ty:: region {
748
+ // Should really return a fixup_result instead of a t, but fold_ty
749
+ // doesn't allow returning anything but a t.
750
+ alt self . resolve_region ( rid) {
751
+ result:: err ( rid) {
752
+ * unresolved = some ( rid) ;
753
+ ret ty:: re_var ( rid as uint ) ;
754
+ }
755
+ result:: ok ( rr) {
756
+ let mut give_up = false ;
757
+ std:: list:: iter ( regions_seen) { |r|
758
+ if r == rid {
759
+ * unresolved = some ( -1 ) ; // hack: communicate inf region
760
+ give_up = true ;
761
+ }
762
+ }
763
+ ret rr;
764
+ }
765
+ }
766
+ }
767
+
768
+ fn fixup_regions ( typ : ty:: t ) -> fres < ty:: t > {
769
+ let unresolved = @mutable none :: < int > ;
770
+ let rty = ty:: fold_ty ( self . tcx , ty:: fm_rptr ( { |region, _under_rptr|
771
+ alt region {
772
+ ty : : re_var ( rid) {
773
+ self . subst_regions ( unresolved, std:: list:: nil, rid as int )
774
+ }
775
+ _ { region }
776
+ }
777
+ } ) , typ) ;
778
+
779
+ let ur = * unresolved;
780
+ alt ur {
781
+ none { ret self. rok ( rty) ; }
782
+ some ( var_id) { ret self . rerr ( var_id) ; }
783
+ }
784
+ }
685
785
}
0 commit comments