@@ -201,41 +201,11 @@ impl of st for ty::region {
201
201
}
202
202
}
203
203
204
- // Most of these methods, like tys() and so forth, take two parameters
205
- // a and b and they are tasked with "ensuring that a is a subtype of
206
- // b". They return success or failure. They make changes in-place to
207
- // the variable bindings: these changes are recorded in the `bindings`
208
- // array, which then allows the changes to be rolled back if needed.
209
- //
210
- // The merge() and merge_bnds() methods are somewhat different in that
211
- // they compute a new type range for a variable (generally a subset of
212
- // the old range). They therefore return a result.
213
- impl unify_methods for infer_ctxt {
214
- fn uok ( ) -> ures {
215
- ok ( ( ) )
216
- }
217
-
218
- fn uerr ( e : ty:: type_err ) -> ures {
219
- #debug[ "Unification error: %?" , e] ;
220
- err ( e)
221
- }
222
-
223
- fn set < V : copy vid, T : copy to_str > (
224
- vb : vals_and_bindings < V , T > , vid : V ,
225
- +new_v : var_value < V , T > ) {
226
-
227
- let old_v = vb. vals . get ( vid. to_uint ( ) ) ;
228
- vec:: push ( vb. bindings , ( vid, old_v) ) ;
229
- vb. vals . insert ( vid. to_uint ( ) , new_v) ;
230
-
231
- #debug[ "Updating variable %s from %s to %s" ,
232
- vid. to_str ( ) , old_v. to_str ( self ) , new_v. to_str ( self ) ] ;
233
- }
234
-
235
- fn set_ty ( vid : ty_vid , +new_v : var_value < ty_vid , ty:: t > ) {
236
- self . set ( self . vb , vid, new_v) ;
237
- }
204
+ fn uok ( ) -> ures {
205
+ ok ( ( ) )
206
+ }
238
207
208
+ impl methods for infer_ctxt {
239
209
fn commit < T , E > ( f : fn ( ) -> result < T , E > ) -> result < T , E > {
240
210
241
211
assert self. vb . bindings . len ( ) == 0 u;
@@ -276,6 +246,21 @@ impl unify_methods for infer_ctxt {
276
246
}
277
247
ret r;
278
248
}
249
+ }
250
+
251
+ impl unify_methods for infer_ctxt {
252
+
253
+ fn set < V : copy vid, T : copy to_str > (
254
+ vb : vals_and_bindings < V , T > , vid : V ,
255
+ +new_v : var_value < V , T > ) {
256
+
257
+ let old_v = vb. vals. get ( vid. to_uint ( ) ) ;
258
+ vec:: push ( vb. bindings , ( vid , old_v ) ) ;
259
+ vb. vals. insert ( vid. to_uint ( ) , new_v ) ;
260
+
261
+ #debug[ "Updating variable %s from %s to %s ",
262
+ vid. to_str ( ) , old_v. to_str ( self ) , new_v. to_str ( self ) ] ;
263
+ }
279
264
280
265
fn get < V : copy vid, T : copy > (
281
266
vb : vals_and_bindings < V , T > , vid : V )
@@ -397,7 +382,7 @@ impl unify_methods for infer_ctxt {
397
382
// be relatable:
398
383
self . bnds ( bnds. lb , bnds. ub ) . then { ||
399
384
self . set ( vb, v_id, bounded ( bnds) ) ;
400
- self . uok ( )
385
+ uok ( )
401
386
}
402
387
} } } } }
403
388
}
@@ -414,7 +399,7 @@ impl unify_methods for infer_ctxt {
414
399
a_id. to_str ( ) , a_bounds. to_str ( self ) ,
415
400
b_id. to_str ( ) , b_bounds. to_str ( self ) ] ;
416
401
417
- if a_id == b_id { ret self . uok ( ) ; }
402
+ if a_id == b_id { ret uok ( ) ; }
418
403
419
404
// If both A's UB and B's LB have already been bound to types,
420
405
// see if we can make those types subtypes.
@@ -437,7 +422,7 @@ impl unify_methods for infer_ctxt {
437
422
// A remains a subtype of B. Actually, there are other options,
438
423
// but that's the route we choose to take.
439
424
self . set_var_to_merged_bounds ( vb, a_id, a_bounds, b_bounds) . then { ||
440
- self . uok ( )
425
+ uok ( )
441
426
}
442
427
}
443
428
@@ -470,7 +455,7 @@ impl unify_methods for infer_ctxt {
470
455
actual_constr : @ty:: type_constr ) -> ures {
471
456
472
457
let err_res =
473
- self . uerr ( ty:: terr_constr_mismatch ( expected, actual_constr) ) ;
458
+ err ( ty:: terr_constr_mismatch ( expected, actual_constr) ) ;
474
459
475
460
if expected. node . id != actual_constr. node . id { ret err_res; }
476
461
let expected_arg_len = vec:: len ( expected. node . args ) ;
@@ -505,7 +490,7 @@ impl unify_methods for infer_ctxt {
505
490
}
506
491
i += 1 u;
507
492
}
508
- ret self . uok( ) ;
493
+ ret uok( ) ;
509
494
}
510
495
511
496
fn bnds < T : copy to_str st> (
@@ -517,7 +502,7 @@ impl unify_methods for infer_ctxt {
517
502
( none, none) |
518
503
( some( _) , none) |
519
504
( none, some( _) ) {
520
- self . uok( )
505
+ uok( )
521
506
}
522
507
( some( t_a) , some( t_b) ) {
523
508
t_a. sub( self , t_b)
@@ -534,7 +519,7 @@ impl unify_methods for infer_ctxt {
534
519
self . constrs( a, b)
535
520
}
536
521
} else {
537
- self . uerr ( ty:: terr_constr_len( bs. len( ) , as. len( ) ) )
522
+ err ( ty:: terr_constr_len( bs. len( ) , as. len( ) ) )
538
523
}
539
524
}
540
525
@@ -688,33 +673,103 @@ impl resolve_methods for infer_ctxt {
688
673
}
689
674
}
690
675
676
+ // ______________________________________________________________________
677
+ // Type assignment
678
+ //
679
+ // True if rvalues of type `a` can be assigned to lvalues of type `b`.
680
+
681
+ impl assignment for infer_ctxt {
682
+ fn assign_tys( a: ty:: t, b : ty:: t,
683
+ encl_blk_id : ast:: node_id) -> ures {
684
+
685
+ #debug[ "assign_tys(%s, %s)" , a. to_str( self ) , b. to_str( self ) ] ;
686
+ let _r = indenter( ) ;
687
+
688
+ alt ( ty:: get( a) . struct , ty:: get( b) . struct ) {
689
+ ( ty:: ty_bot, _) {
690
+ uok( )
691
+ }
692
+
693
+ ( ty:: ty_var( a_id) , ty:: ty_var( b_id) ) {
694
+ let { root: _, bounds: a_bounds} = self . get( self . vb, a_id) ;
695
+ let { root: _, bounds: b_bounds} = self . get( self . vb, b_id) ;
696
+ self . assign_vars_or_sub( a, b, a_bounds, b_bounds, encl_blk_id)
697
+ }
698
+
699
+ ( ty:: ty_var( a_id) , _) {
700
+ let { root: _, bounds: a_bounds} = self . get( self . vb, a_id) ;
701
+ let b_bounds = { lb: some( b) , ub: none} ;
702
+ self . assign_vars_or_sub( a, b, a_bounds, b_bounds, encl_blk_id)
703
+ }
704
+
705
+ ( _, ty:: ty_var( b_id) ) {
706
+ let a_bounds = { lb: none, ub: some( a) } ;
707
+ let { root: _, bounds: b_bounds} = self . get( self . vb, b_id) ;
708
+ self . assign_vars_or_sub( a, b, a_bounds, b_bounds, encl_blk_id)
709
+ }
710
+
711
+ ( ty:: ty_box( a_mt) , ty:: ty_rptr( _, _) ) |
712
+ ( ty:: ty_uniq( a_mt) , ty:: ty_rptr( _, _) ) {
713
+ let a_r = ty:: re_scope( encl_blk_id) ;
714
+ let a_ty = ty:: mk_rptr( self . tcx, a_r, a_mt) ;
715
+ self . sub_tys( a_ty, b) . to_ures( )
716
+ }
717
+
718
+ _ {
719
+ self . sub_tys( a, b) . to_ures( )
720
+ }
721
+ }
722
+ }
723
+
724
+ fn assign_tys_or_sub( a: ty:: t, b: ty:: t,
725
+ a_b: ty:: t, b_b: ty:: t,
726
+ encl_blk_id: ast:: node_id) -> ures {
727
+ self. try { ||
728
+ self . assign_tys( a_b, b_b, encl_blk_id)
729
+ } . chain_err { |_e|
730
+ self . sub_tys( a, b)
731
+ }
732
+ }
733
+
734
+ fn assign_vars_or_sub( a: ty:: t, b: ty:: t,
735
+ a_bounds: bounds < ty:: t > , b_bounds: bounds < ty:: t > ,
736
+ encl_blk_id: ast:: node_id) -> ures {
737
+
738
+ alt ( a_bounds. ub, b_bounds. lb) {
739
+ ( some( a_ub) , some( b_lb) ) {
740
+ self . assign_tys_or_sub( a, b, a_ub, b_lb, encl_blk_id)
741
+ }
742
+ _ {
743
+ self . sub_tys( a, b) . to_ures( )
744
+ }
745
+ }
746
+ }
747
+ }
748
+
691
749
// ______________________________________________________________________
692
750
// Type combining
693
751
//
694
- // There are two type combiners, lub and gub. The first computes the
695
- // Least Upper Bound of two types `a` and `b`---that is, a mutual
752
+ // There are three type combiners, sub, lub, and gub. `sub` is a bit
753
+ // different from the other two: it takes two types and makes the first
754
+ // a subtype of the other, or fails if this cannot be done. It does
755
+ // return a new type but its return value is meaningless---it is only
756
+ // there to allow for greater code reuse.
757
+ //
758
+ // `lub` and `glb` compute the Least Upper Bound and Greatest Lower
759
+ // Bound respectively of two types `a` and `b`. The LUB is a mutual
696
760
// supertype type `c` where `a <: c` and `b <: c`. As the name
697
- // implies, it tries to pick the most precise `c` possible. `glb`
698
- // computes the greatest lower bound---that is, it computes a mutual
699
- // subtype, aiming for the most general such type possible. Both
700
- // computations may fail.
761
+ // implies, it tries to pick the most precise `c` possible. The GLB
762
+ // is a mutual subtype, aiming for the most general such type
763
+ // possible. Both computations may fail.
701
764
//
702
765
// There is a lot of common code for these operations, which is
703
- // abstracted out into functions named `c_X ()` which take a combiner
766
+ // abstracted out into functions named `super_X ()` which take a combiner
704
767
// instance as the first parameter. This would be better implemented
705
768
// using traits.
706
769
//
707
- // The `c_X()` top-level items work for *both LUB and GLB*: any
708
- // operation which varies between LUB and GLB will be dynamically
709
- // dispatched using a `self.Y()` operation.
710
- //
711
- // In principle, the subtyping relation computed above could be built
712
- // on the combine framework---this would result in less code but would
713
- // be less efficient. There is a significant performance gain from
714
- // not recreating types unless we need to. Even so, we could write
715
- // the routines with a few more generics in there to mask type
716
- // construction (which is, after all, the significant expense) but I
717
- // haven't gotten around to it.
770
+ // The `super_X()` top-level items work for *sub, lub, and glb*: any
771
+ // operation which varies will be dynamically dispatched using a
772
+ // `self.Y()` operation.
718
773
719
774
type cres < T > = result < T , ty:: type_err > ;
720
775
@@ -736,7 +791,7 @@ iface combine {
736
791
fn regions( a: ty:: region, b: ty:: region) -> cres < ty:: region > ;
737
792
}
738
793
739
- enum sub = infer_ctxt; // "less than" == " subtype" or "subregion"
794
+ enum sub = infer_ctxt; // "subtype", "subregion" etc
740
795
enum lub = infer_ctxt; // "least upper bound" (common supertype)
741
796
enum glb = infer_ctxt; // "greatest lower bound" (common subtype)
742
797
@@ -1445,7 +1500,8 @@ impl of combine for glb {
1445
1500
// ______________________________________________________________________
1446
1501
// Lattice operations on variables
1447
1502
//
1448
- // this is common code used by both LUB and GLB
1503
+ // This is common code used by both LUB and GLB to compute the LUB/GLB
1504
+ // for pairs of variables or for variables and values.
1449
1505
1450
1506
iface lattice_ops {
1451
1507
fn bnd< T : copy > ( b: bounds < T > ) -> option < T > ;
0 commit comments