@@ -570,24 +570,6 @@ fn count_ty_params(@t ty) -> uint {
570
570
ret _vec. len[ ast. def_id] ( * param_ids) ;
571
571
}
572
572
573
- fn type_contains_ty_vars( @t ty) -> bool {
574
- state obj checker( @mutable bool has_vars) {
575
- fn fold_simple_ty( @t ty) -> @t {
576
- alt ( ty. struct ) {
577
- case ( ty_var( _) ) {
578
- * has_vars = true;
579
- }
580
- case ( _) { }
581
- }
582
- ret ty;
583
- }
584
- }
585
-
586
- let @mutable bool b = @mutable false;
587
- fold_ty( checker( b) , ty) ;
588
- ret * b;
589
- }
590
-
591
573
// Type accessors for substructures of types
592
574
593
575
fn ty_fn_args( @t fty) -> vec[ arg] {
@@ -802,7 +784,10 @@ fn is_lval(@ast.expr expr) -> bool {
802
784
}
803
785
}
804
786
805
- // Type unification
787
+ // Type unification via Robinson's algorithm (Robinson 1965). Implemented as
788
+ // described in Hoder and Voronkov:
789
+ //
790
+ // http://www.cs.man.ac.uk/~hoderk/ubench/unification_full.pdf
806
791
807
792
fn unify( @ty. t expected, @ty. t actual, & unify_handler handler)
808
793
-> unify_result {
@@ -822,7 +807,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
822
807
ret ures_err( terr_mismatch, expected, actual) ;
823
808
}
824
809
825
- fn unify_fn( & hashmap[ int, @ty. t] bindings,
810
+ fn unify_fn( @ hashmap[ int, @ty. t] bindings,
826
811
@ty. t expected,
827
812
@ty. t actual,
828
813
& unify_handler handler,
@@ -891,7 +876,7 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
891
876
892
877
}
893
878
894
- fn unify_obj( & hashmap[ int, @ty. t] bindings,
879
+ fn unify_obj( @ hashmap[ int, @ty. t] bindings,
895
880
@ty. t expected,
896
881
@ty. t actual,
897
882
& unify_handler handler,
@@ -952,27 +937,44 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
952
937
ret ures_ok( t) ;
953
938
}
954
939
955
- fn unify_step( & hashmap[ int, @ty. t] bindings, @ty. t expected, @ty. t actual,
956
- & unify_handler handler) -> unify_result {
940
+ fn resolve( @hashmap[ int, @t] bindings, @t typ) -> @t {
941
+ alt ( typ. struct ) {
942
+ case ( ty_var( ?id) ) {
943
+ alt ( bindings. find( id) ) {
944
+ case ( some[ @t] ( ?typ2) ) {
945
+ ret resolve( bindings, typ2) ;
946
+ }
947
+ case ( none[ @t] ) {
948
+ // fall through
949
+ }
950
+ }
951
+ }
952
+ case ( _) {
953
+ // fall through
954
+ }
955
+ }
956
+ ret typ;
957
+ }
958
+
959
+ fn unify_step( @hashmap[ int, @ty. t] bindings, @ty. t in_expected,
960
+ @ty. t in_actual, & unify_handler handler) -> unify_result {
961
+
962
+ // Resolve any bindings.
963
+ auto expected = resolve( bindings, in_expected) ;
964
+ auto actual = resolve( bindings, in_actual) ;
965
+
957
966
// TODO: rewrite this using tuple pattern matching when available, to
958
967
// avoid all this rightward drift and spikiness.
959
968
969
+ // TODO: occurs check, to make sure we don't loop forever when
970
+ // unifying e.g. 'a and option['a]
971
+
960
972
alt ( actual. struct ) {
961
973
// If the RHS is a variable type, then just do the appropriate
962
974
// binding.
963
975
case ( ty. ty_var( ?actual_id) ) {
964
- alt ( bindings. find( actual_id) ) {
965
- case ( some[ @ty. t] ( ?actual_ty) ) {
966
- // FIXME: change the binding here?
967
- // FIXME: "be"
968
- ret unify_step( bindings, expected, actual_ty,
969
- handler) ;
970
- }
971
- case ( none[ @ty. t] ) {
972
- bindings. insert( actual_id, expected) ;
973
- ret ures_ok( expected) ;
974
- }
975
- }
976
+ bindings. insert( actual_id, expected) ;
977
+ ret ures_ok( expected) ;
976
978
}
977
979
case ( ty. ty_local( ?actual_id) ) {
978
980
auto actual_ty = handler. resolve_local( actual_id) ;
@@ -1077,8 +1079,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1077
1079
}
1078
1080
}
1079
1081
1080
- // TODO: ty_var
1081
-
1082
1082
case ( _) {
1083
1083
ret ures_err( terr_mismatch, expected, actual) ;
1084
1084
}
@@ -1102,8 +1102,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1102
1102
}
1103
1103
}
1104
1104
1105
- // TODO: ty_var
1106
-
1107
1105
case ( _) {
1108
1106
ret ures_err( terr_mismatch, expected, actual) ;
1109
1107
}
@@ -1152,8 +1150,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1152
1150
ret ures_ok( plain_ty( ty. ty_tup( result_elems) ) ) ;
1153
1151
}
1154
1152
1155
- // TODO: ty_var
1156
-
1157
1153
case ( _) {
1158
1154
ret ures_err( terr_mismatch, expected, actual) ;
1159
1155
}
@@ -1213,8 +1209,6 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1213
1209
ret ures_ok( plain_ty( ty. ty_rec( result_fields) ) ) ;
1214
1210
}
1215
1211
1216
- // TODO: ty_var
1217
-
1218
1212
case ( _) {
1219
1213
ret ures_err( terr_mismatch, expected, actual) ;
1220
1214
}
@@ -1248,20 +1242,9 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1248
1242
}
1249
1243
1250
1244
case ( ty. ty_var( ?expected_id) ) {
1251
- alt ( bindings. find( expected_id) ) {
1252
- case ( some[ @ty. t] ( ?expected_ty) ) {
1253
- // FIXME: change the binding here?
1254
- // FIXME: "be"
1255
- ret unify_step( bindings,
1256
- expected_ty,
1257
- actual,
1258
- handler) ;
1259
- }
1260
- case ( none[ @ty. t] ) {
1261
- bindings. insert( expected_id, actual) ;
1262
- ret ures_ok( actual) ;
1263
- }
1264
- }
1245
+ // Add a binding.
1246
+ bindings. insert( expected_id, actual) ;
1247
+ ret ures_ok( actual) ;
1265
1248
}
1266
1249
1267
1250
case ( ty. ty_local( ?expected_id) ) {
@@ -1289,31 +1272,43 @@ fn unify(@ty.t expected, @ty.t actual, &unify_handler handler)
1289
1272
fail;
1290
1273
}
1291
1274
1275
+ // Performs type binding substitution.
1276
+ fn substitute( @hashmap[ int, @t] bindings, @t typ) -> @t {
1277
+ state obj folder( @hashmap[ int, @t] bindings) {
1278
+ fn fold_simple_ty( @t typ) -> @t {
1279
+ alt ( typ. struct ) {
1280
+ case ( ty_var( ?id) ) {
1281
+ alt ( bindings. find( id) ) {
1282
+ case ( some[ @t] ( ?typ2) ) {
1283
+ ret substitute( bindings, typ2) ;
1284
+ }
1285
+ case ( none[ @t] ) {
1286
+ ret typ;
1287
+ }
1288
+ }
1289
+ }
1290
+ case ( _) {
1291
+ ret typ;
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+
1297
+ ret ty. fold_ty( folder( bindings) , typ) ;
1298
+ }
1299
+
1292
1300
fn hash_int( & int x) -> uint { ret x as uint; }
1293
1301
fn eq_int( & int a, & int b) -> bool { ret a == b; }
1294
1302
auto hasher = hash_int;
1295
1303
auto eqer = eq_int;
1296
- auto bindings = map. mk_hashmap[ int, @ty. t] ( hasher, eqer) ;
1297
-
1298
- // FIXME: this is a slow way of driving types into residual vars that
1299
- // occur up in the leaves of result type; it can likely be done better
1300
- // when unification is actually ... down in the leaves.
1304
+ auto bindings = @map. mk_hashmap[ int, @ty. t] ( hasher, eqer) ;
1301
1305
1302
1306
auto ures = unify_step( bindings, expected, actual, handler) ;
1303
- while ( true) {
1304
- alt ( ures) {
1305
- case ( ures_ok( ?t) ) {
1306
- if ( !type_contains_ty_vars( t) ) {
1307
- ret ures;
1308
- }
1309
- ures = unify_step( bindings, t, actual, handler) ;
1310
- }
1311
- case ( _) {
1312
- ret ures;
1313
- }
1314
- }
1307
+ alt ( ures) {
1308
+ case ( ures_ok( ?t) ) { ret ures_ok( substitute( bindings, t) ) ; }
1309
+ case ( _) { ret ures; }
1315
1310
}
1316
- fail;
1311
+ fail; // not reached
1317
1312
}
1318
1313
1319
1314
fn type_err_to_str( & ty. type_err err) -> str {
0 commit comments