@@ -16,53 +16,45 @@ export fixup_vars;
16
16
export resolve_var;
17
17
export compare_tys;
18
18
19
- type bound = option < ty :: t > ;
19
+ type bound < T : copy > = option < T > ;
20
20
21
- type bounds = { lb : bound , ub : bound } ;
21
+ type bounds < T : copy > = { lb : bound < T > , ub : bound < T > } ;
22
22
23
- enum var_value {
23
+ enum var_value < T : copy > {
24
24
redirect( uint ) ,
25
- bounded( bounds )
25
+ bounded( bounds < T > )
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
- }
28
+ type vals_and_bindings < T : copy > = {
29
+ vals : smallintmap < var_value < T > > ,
30
+ mut bindings : [ ( uint , var_value < T > ) ]
31
+ } ;
36
32
37
33
enum infer_ctxt = @{
38
34
tcx: ty:: ctxt,
39
- vals: smallintmap <var_value >,
40
- mut bindings: [ ( uint, var_value) ] ,
41
- region_vals: smallintmap<region_value>,
42
- mut region_bindings: [ ( uint, region_value) ]
35
+ vb: vals_and_bindings <ty:: t >,
36
+ rb: vals_and_bindings<ty:: region>,
43
37
} ;
44
38
45
39
type ures = result:: result < ( ) , ty:: type_err > ;
46
40
type fres < T > = result:: result < T , int > ;
47
41
48
42
fn new_infer_ctxt ( tcx : ty:: ctxt ) -> infer_ctxt {
49
43
infer_ctxt ( @{ tcx: tcx,
50
- vals: smallintmap:: mk ( ) ,
51
- mut bindings: [ ] ,
52
- region_vals: smallintmap:: mk ( ) ,
53
- mut region_bindings: [ ] } )
44
+ vb : { vals : smallintmap:: mk ( ) , mut bindings : [ ] } ,
45
+ rb : { vals : smallintmap:: mk ( ) , mut bindings : [ ] } } )
54
46
}
55
47
56
48
fn mk_subty ( cx : infer_ctxt , a : ty:: t , b : ty:: t ) -> ures {
57
49
#debug[ ">> mk_subty(%s <: %s)" , cx. ty_to_str ( a) , cx. ty_to_str ( b) ] ;
58
- cx. commit { ||
50
+ cx. commit ( cx . vb ) { ||
59
51
cx. tys ( a, b)
60
52
}
61
53
}
62
54
63
55
fn mk_eqty ( cx : infer_ctxt , a : ty:: t , b : ty:: t ) -> ures {
64
56
#debug[ "> mk_eqty(%s <: %s)" , cx. ty_to_str ( a) , cx. ty_to_str ( b) ] ;
65
- cx. commit { ||
57
+ cx. commit ( cx . vb ) { ||
66
58
mk_subty ( cx, a, b) . then { ||
67
59
mk_subty ( cx, b, a)
68
60
}
@@ -72,7 +64,7 @@ fn mk_eqty(cx: infer_ctxt, a: ty::t, b: ty::t) -> ures {
72
64
fn compare_tys ( tcx : ty:: ctxt , a : ty:: t , b : ty:: t ) -> ures {
73
65
let infcx = new_infer_ctxt ( tcx) ;
74
66
#debug[ "> compare_tys(%s == %s)" , infcx. ty_to_str ( a) , infcx. ty_to_str ( b) ] ;
75
- infcx. commit { ||
67
+ infcx. commit ( infcx . vb ) { ||
76
68
mk_subty ( infcx, a, b) . then { ||
77
69
mk_subty ( infcx, b, a)
78
70
}
@@ -122,54 +114,63 @@ impl unify_methods for infer_ctxt {
122
114
ty_to_str ( self . tcx , t)
123
115
}
124
116
125
- fn bound_to_str ( b : bound ) -> str {
117
+ fn ty_bound_to_str ( b : bound < ty :: t > ) -> str {
126
118
alt b {
127
119
none { "none" }
128
120
some( t) { self . ty_to_str( t) }
129
121
}
130
122
}
131
123
132
- fn bounds_to_str ( v : bounds ) -> str {
124
+ fn ty_bounds_to_str ( v : bounds < ty :: t > ) -> str {
133
125
#fmt[ "{%s <: X <: %s}" ,
134
- self . bound_to_str ( v. lb ) ,
135
- self . bound_to_str ( v. ub ) ]
126
+ self . ty_bound_to_str ( v. lb ) ,
127
+ self . ty_bound_to_str ( v. ub ) ]
136
128
}
137
129
138
- fn var_value_to_str ( v : var_value ) -> str {
130
+ fn ty_var_value_to_str ( v : var_value < ty :: t > ) -> str {
139
131
alt v {
140
132
redirect( v) { #fmt[ "redirect(%u)" , v] }
141
- bounded ( b) { self . bounds_to_str ( b) }
133
+ bounded ( b) { self . ty_bounds_to_str ( b) }
142
134
}
143
135
}
144
136
145
- fn set ( vid : uint , +new_v : var_value ) {
146
- let old_v = self . vals . get ( vid) ;
147
- vec:: push ( self . bindings , ( vid, old_v) ) ;
137
+ fn set < T : copy > ( vb : vals_and_bindings < T > , vid : uint ,
138
+ +new_v : var_value < T > ) {
148
139
140
+ let old_v = vb. vals . get ( vid) ;
141
+ vec:: push ( vb. bindings , ( vid, old_v) ) ;
142
+ vb. vals . insert ( vid, new_v) ;
143
+ }
144
+
145
+ fn set_ty ( vid : uint , +new_v : var_value < ty:: t > ) {
146
+ let old_v = self . vb . vals . get ( vid) ;
147
+ self . set ( self . vb , vid, new_v) ;
149
148
#debug[ "Updating variable <T%u> from %s to %s" ,
150
149
vid,
151
- self . var_value_to_str ( old_v) ,
152
- self . var_value_to_str ( new_v) ] ;
153
-
154
- self . vals . insert ( vid, new_v) ;
150
+ self . ty_var_value_to_str ( old_v) ,
151
+ self . ty_var_value_to_str ( new_v) ] ;
155
152
}
156
153
157
- fn rollback_to ( len : uint ) {
158
- while self . bindings . len ( ) != len {
159
- let ( vid, old_v) = vec:: pop ( self . bindings ) ;
160
- self . vals . insert ( vid, old_v) ;
154
+ fn rollback_to < T : copy > ( vb : vals_and_bindings < T > , len : uint ) {
155
+ while vb . bindings . len ( ) != len {
156
+ let ( vid, old_v) = vec:: pop ( vb . bindings ) ;
157
+ vb . vals . insert ( vid, old_v) ;
161
158
}
162
159
}
163
160
164
- fn commit < T : copy , E : copy > ( f : fn ( ) -> result < T , E > ) -> result < T , E > {
165
- assert self. bindings . len ( ) == 0 u;
166
- let r = self . try ( f) ;
167
- vec:: clear ( self . bindings ) ;
161
+ fn commit < T : copy , E : copy , U : copy > ( vb : vals_and_bindings < U > ,
162
+ f : fn ( ) -> result < T , E > ) -> result < T , E > {
163
+
164
+ assert vb. bindings . len ( ) == 0 u;
165
+ let r = self . try ( vb, f) ;
166
+ vec:: clear ( vb. bindings ) ;
168
167
ret r;
169
168
}
170
169
171
- fn try < T : copy , E : copy > ( f : fn ( ) -> result < T , E > ) -> result < T , E > {
172
- let l = self . bindings . len ( ) ;
170
+ fn try < T : copy , E : copy , U : copy > ( vb : vals_and_bindings < U > ,
171
+ f : fn ( ) -> result < T , E > ) -> result < T , E > {
172
+
173
+ let l = vb. bindings . len ( ) ;
173
174
#debug[ "try(l=%u)" , l] ;
174
175
let r = f ( ) ;
175
176
alt r {
@@ -179,17 +180,19 @@ impl unify_methods for infer_ctxt {
179
180
ret r;
180
181
}
181
182
182
- fn get ( vid : uint ) -> { root : uint , bounds : bounds } {
183
- alt self . vals . find ( vid) {
183
+ fn get < T : copy > ( vb : vals_and_bindings < T > , vid : uint )
184
+ -> { root : uint , bounds : bounds < T > } {
185
+
186
+ alt vb. vals . find ( vid) {
184
187
none {
185
188
let bnds = { lb : none, ub : none} ;
186
- self . vals . insert ( vid, bounded ( bnds) ) ;
189
+ vb . vals . insert ( vid, bounded ( bnds) ) ;
187
190
{ root: vid, bounds: bnds}
188
191
}
189
192
some ( redirect ( vid) ) {
190
- let { root, bounds} = self . get ( vid) ;
193
+ let { root, bounds} = self . get ( vb , vid) ;
191
194
if root != vid {
192
- self . vals . insert ( vid, redirect ( root) ) ;
195
+ vb . vals . insert ( vid, redirect ( root) ) ;
193
196
}
194
197
{ root: root, bounds: bounds}
195
198
}
@@ -199,31 +202,21 @@ impl unify_methods for infer_ctxt {
199
202
}
200
203
}
201
204
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
- }
205
+ fn get_var ( vid : uint ) -> { root : uint , bounds : bounds < ty:: t > } {
206
+ ret self . get ( self . vb , vid) ;
207
+ }
208
+
209
+ fn get_region ( rid : uint ) -> { root : uint , bounds : bounds < ty:: region > } {
210
+ ret self . get ( self . rb , rid) ;
222
211
}
223
212
224
213
// Combines the two bounds. Returns a bounds r where (r.lb <:
225
214
// a,b) and (a,b <: r.ub) (if such a bounds exists).
226
- fn merge_bnds ( a : bound , b : bound ) -> result < bounds , ty:: type_err > {
215
+ //
216
+ // TODO: Generalize this to region bounds too.
217
+ fn merge_bnds ( a : bound < ty:: t > , b : bound < ty:: t > )
218
+ -> result < bounds < ty:: t > , ty:: type_err > {
219
+
227
220
alt ( a, b) {
228
221
( none, none) {
229
222
ok ( { lb: none, ub: none} )
@@ -235,7 +228,7 @@ impl unify_methods for infer_ctxt {
235
228
ok ( { lb: b, ub: b} )
236
229
}
237
230
( some ( t_a) , some ( t_b) ) {
238
- let r1 = self . try { ||
231
+ let r1 = self . try ( self . vb ) { ||
239
232
self . tys ( t_a, t_b) . then { ||
240
233
ok ( { lb: a, ub: b} )
241
234
}
@@ -257,7 +250,9 @@ impl unify_methods for infer_ctxt {
257
250
// a.lb <: c.lb
258
251
// b.lb <: c.lb
259
252
// If this cannot be achieved, the result is failure.
260
- fn merge ( v_id : uint , a : bounds , b : bounds ) -> ures {
253
+ //
254
+ // TODO: Generalize to regions.
255
+ fn merge ( v_id : uint , a : bounds < ty:: t > , b : bounds < ty:: t > ) -> ures {
261
256
// Think of the two diamonds, we want to find the
262
257
// intersection. There are basically four possibilities (you
263
258
// can swap A/B in these pictures):
@@ -275,8 +270,8 @@ impl unify_methods for infer_ctxt {
275
270
276
271
#debug[ "merge(<T%u>,%s,%s)" ,
277
272
v_id,
278
- self . bounds_to_str ( a) ,
279
- self . bounds_to_str ( b) ] ;
273
+ self . ty_bounds_to_str ( a) ,
274
+ self . ty_bounds_to_str ( b) ] ;
280
275
281
276
chain ( self . merge_bnds ( a. ub , b. ub ) ) { |ub|
282
277
chain ( self . merge_bnds ( a. lb , b. lb ) ) { |lb|
@@ -285,17 +280,18 @@ impl unify_methods for infer_ctxt {
285
280
// the new bounds must themselves
286
281
// be relatable:
287
282
self . bnds ( lb. ub , ub. lb ) . then { ||
288
- self . set ( v_id, bounded ( bnds) ) ;
283
+ self . set ( self . vb , v_id, bounded ( bnds) ) ;
289
284
self . uok ( )
290
285
}
291
286
}
292
287
}
293
288
}
294
289
290
+ // TODO: Generalize to regions.
295
291
fn vars ( a_id : uint , b_id : uint ) -> ures {
296
292
// Need to make sub_id a subtype of sup_id.
297
- let { root: a_id , bounds : a_bounds } = self . get ( a_id) ;
298
- let { root: b_id , bounds : b_bounds } = self . get ( b_id) ;
293
+ let { root: a_id , bounds : a_bounds } = self . get ( self . vb , a_id) ;
294
+ let { root: b_id , bounds : b_bounds } = self . get ( self . vb , b_id) ;
299
295
300
296
#debug[ "vars(<T%u>=%s <: <T%u>=%s)" ,
301
297
a_id, self . bounds_to_str ( a_bounds) ,
@@ -321,26 +317,26 @@ impl unify_methods for infer_ctxt {
321
317
// but that's the route we choose to take.
322
318
self . merge ( a_id, a_bounds, b_bounds) . then { ||
323
319
// For max perf, we should consider the rank here.
324
- self . set ( b_id, redirect ( a_id) ) ;
320
+ self . set ( self . vb , b_id, redirect ( a_id) ) ;
325
321
self . uok ( )
326
322
}
327
323
}
328
324
329
325
fn varty ( a_id : uint , b : ty:: t ) -> ures {
330
- let { root: a_id , bounds : a_bounds } = self . get ( a_id) ;
326
+ let { root: a_id , bounds : a_bounds } = self . get ( self . vb , a_id) ;
331
327
#debug[ "varty(<T%u>=%s <: %s)" ,
332
- a_id, self . bounds_to_str ( a_bounds) ,
328
+ a_id, self . ty_bounds_to_str ( a_bounds) ,
333
329
self . ty_to_str ( b) ] ;
334
330
let b_bounds = { lb: none, ub: some ( b) } ;
335
331
self . merge ( a_id, a_bounds, b_bounds)
336
332
}
337
333
338
334
fn tyvar ( a : ty:: t , b_id : uint ) -> ures {
339
335
let a_bounds = { lb: some ( a) , ub: none} ;
340
- let { root: b_id , bounds : b_bounds } = self . get ( b_id) ;
336
+ let { root: b_id , bounds : b_bounds } = self . get ( self . vb , b_id) ;
341
337
#debug[ "tyvar(%s <: <T%u>=%s)" ,
342
338
self . ty_to_str ( a) ,
343
- b_id, self . bounds_to_str ( b_bounds) ] ;
339
+ b_id, self . ty_bounds_to_str ( b_bounds) ] ;
344
340
self . merge ( b_id, a_bounds, b_bounds)
345
341
}
346
342
@@ -530,10 +526,11 @@ impl unify_methods for infer_ctxt {
530
526
ret self. uok ( ) ;
531
527
}
532
528
533
- fn bnds ( a : bound , b : bound ) -> ures {
529
+ // TODO: Generalize this.
530
+ fn bnds ( a : bound < ty:: t > , b : bound < ty:: t > ) -> ures {
534
531
#debug ( "bnds(%s <: %s)" ,
535
- self . bound_to_str ( a) ,
536
- self . bound_to_str ( b) ) ;
532
+ self . ty_bound_to_str ( a) ,
533
+ self . ty_bound_to_str ( b) ) ;
537
534
538
535
alt ( a, b) {
539
536
( none, none) |
@@ -662,8 +659,10 @@ impl resolve_methods for infer_ctxt {
662
659
result:: err ( v)
663
660
}
664
661
665
- fn resolve_var ( vid : int ) -> fres < ty:: t > {
666
- let { root: _ , bounds } = self . get ( vid as uint ) ;
662
+ fn resolve_var < T : copy > ( vb : vals_and_bindings < T > , bot_guard : fn ( T ) ->bool ,
663
+ vid : int ) -> fres < T > {
664
+
665
+ let { root: _ , bounds } = self . get ( vb, vid as uint ) ;
667
666
668
667
// Nonobvious: prefer the most specific type
669
668
// (i.e., the lower bound) to the more general
@@ -672,16 +671,20 @@ impl resolve_methods for infer_ctxt {
672
671
// perf. penalties, so it pays to know more.
673
672
674
673
alt bounds {
675
- { ub : _, lb : some ( t) } if !type_is_bot ( t) { self . rok ( t) }
676
- { ub: some ( t) , lb: _ } { self . rok ( t) }
677
- { ub: _, lb: some ( t) } { self . rok ( t) }
674
+ { ub : _, lb : some ( t) } if !bot_guard ( t) { result :: ok ( t) }
675
+ { ub: some ( t) , lb: _ } { result :: ok ( t) }
676
+ { ub: _, lb: some ( t) } { result :: ok ( t) }
678
677
{ ub: none, lb: none } { self . rerr ( vid) }
679
678
}
680
679
}
681
680
681
+ fn resolve_ty_var ( vid : int ) -> fres < ty:: t > {
682
+ ret self . resolve_var ( self . vb , { |t| type_is_bot ( t) } , vid) ;
683
+ }
684
+
682
685
fn resolve_ty ( typ : ty:: t ) -> fres < ty:: t > {
683
686
alt ty:: get ( typ) . struct {
684
- ty:: ty_var ( vid) { self . resolve_var ( vid) }
687
+ ty:: ty_var ( vid) { self . resolve_ty_var ( vid) }
685
688
ty:: ty_rptr ( ty:: re_var ( rid) , base_ty) {
686
689
alt self . resolve_region ( rid as int ) {
687
690
result:: err ( terr) { result:: err ( terr) }
@@ -699,7 +702,7 @@ impl resolve_methods for infer_ctxt {
699
702
vid : int ) -> ty:: t {
700
703
// Should really return a fixup_result instead of a t, but fold_ty
701
704
// doesn't allow returning anything but a t.
702
- alt self . resolve_var ( vid) {
705
+ alt self . resolve_ty_var ( vid) {
703
706
result:: err ( vid) {
704
707
* unresolved = some ( vid) ;
705
708
ret ty:: mk_var ( self . tcx , vid) ;
0 commit comments